@adea-ai/ui 0.120.0 → 0.122.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 (63) hide show
  1. package/dist/components/composites/account-menu/account-menu.d.ts +8 -0
  2. package/dist/components/composites/account-menu/account-menu.d.ts.map +1 -1
  3. package/dist/components/composites/account-menu/account-menu.js +43 -15
  4. package/dist/components/composites/account-menu/account-menu.js.map +1 -1
  5. package/dist/components/conversation/composer-menu.d.ts +31 -0
  6. package/dist/components/conversation/composer-menu.d.ts.map +1 -0
  7. package/dist/components/conversation/composer-menu.js +63 -0
  8. package/dist/components/conversation/composer-menu.js.map +1 -0
  9. package/dist/components/conversation/conversation-pane.d.ts +38 -0
  10. package/dist/components/conversation/conversation-pane.d.ts.map +1 -0
  11. package/dist/components/conversation/conversation-pane.js +83 -0
  12. package/dist/components/conversation/conversation-pane.js.map +1 -0
  13. package/dist/components/conversation/conversation-surface.d.ts +6 -0
  14. package/dist/components/conversation/conversation-surface.d.ts.map +1 -1
  15. package/dist/components/conversation/conversation-surface.js +10 -4
  16. package/dist/components/conversation/conversation-surface.js.map +1 -1
  17. package/dist/components/conversation/index.d.ts +2 -0
  18. package/dist/components/conversation/index.d.ts.map +1 -1
  19. package/dist/components/conversation/index.js +3 -1
  20. package/dist/components/conversation/message-composer.d.ts +6 -0
  21. package/dist/components/conversation/message-composer.d.ts.map +1 -1
  22. package/dist/components/conversation/message-composer.js +10 -1
  23. package/dist/components/conversation/message-composer.js.map +1 -1
  24. package/dist/components/ui/command/command.d.ts +13 -0
  25. package/dist/components/ui/command/command.d.ts.map +1 -1
  26. package/dist/components/ui/command/command.js +35 -2
  27. package/dist/components/ui/command/command.js.map +1 -1
  28. package/dist/components/ui/command/index.d.ts +1 -1
  29. package/dist/components/ui/command/index.d.ts.map +1 -1
  30. package/dist/components/ui/command/index.js +2 -2
  31. package/dist/components/ui/kbd/index.d.ts +1 -0
  32. package/dist/components/ui/kbd/index.d.ts.map +1 -1
  33. package/dist/components/ui/kbd/index.js +2 -1
  34. package/dist/components/ui/kbd/platform-modifier.d.ts +28 -0
  35. package/dist/components/ui/kbd/platform-modifier.d.ts.map +1 -0
  36. package/dist/components/ui/kbd/platform-modifier.js +37 -0
  37. package/dist/components/ui/kbd/platform-modifier.js.map +1 -0
  38. package/dist/index.js +5 -2
  39. package/dist/r/conversation.json +10 -0
  40. package/dist/r/kbd.json +5 -0
  41. package/dist/r/registry.json +15 -0
  42. package/dist/r/src/components/composites/account-menu/account-menu.tsx +44 -4
  43. package/dist/r/src/components/conversation/composer-menu.tsx +67 -0
  44. package/dist/r/src/components/conversation/conversation-pane.tsx +111 -0
  45. package/dist/r/src/components/conversation/conversation-surface.tsx +12 -1
  46. package/dist/r/src/components/conversation/index.ts +7 -0
  47. package/dist/r/src/components/conversation/message-composer.tsx +8 -0
  48. package/dist/r/src/components/ui/command/command.tsx +35 -0
  49. package/dist/r/src/components/ui/command/index.ts +2 -0
  50. package/dist/r/src/components/ui/kbd/index.ts +5 -0
  51. package/dist/r/src/components/ui/kbd/platform-modifier.ts +37 -0
  52. package/package.json +1 -1
  53. package/registry.json +15 -0
  54. package/src/components/composites/account-menu/account-menu.tsx +44 -4
  55. package/src/components/conversation/composer-menu.tsx +67 -0
  56. package/src/components/conversation/conversation-pane.tsx +111 -0
  57. package/src/components/conversation/conversation-surface.tsx +12 -1
  58. package/src/components/conversation/index.ts +7 -0
  59. package/src/components/conversation/message-composer.tsx +8 -0
  60. package/src/components/ui/command/command.tsx +35 -0
  61. package/src/components/ui/command/index.ts +2 -0
  62. package/src/components/ui/kbd/index.ts +5 -0
  63. package/src/components/ui/kbd/platform-modifier.ts +37 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAChG,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAChG,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACpC,KAAK,kCAAkC,EACvC,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,YAAY,EACZ,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAChG,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAChG,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACpC,KAAK,kCAAkC,EACvC,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,YAAY,EACZ,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAA"}
@@ -2,9 +2,11 @@ import { BusySendButton } from "./busy-send-button.js";
2
2
  import { ChatComposer } from "./chat-composer.js";
3
3
  import { ConversationAvatar } from "./conversation-avatar.js";
4
4
  import { ConversationSurface } from "./conversation-surface.js";
5
+ import { ConversationPane } from "./conversation-pane.js";
6
+ import { ComposerMenu, ComposerMenuItem } from "./composer-menu.js";
5
7
  import { ComposerAttachmentButton, ComposerHint, MessageComposer } from "./message-composer.js";
6
8
  import { MessageBody, MessageDayDivider, MessageGroup, MessageRow } from "./message-row.js";
7
9
  import { TranscriptComposition, transcriptDisclosureKey } from "./transcript-composition.js";
8
10
  import { AttachmentCard, ThreadPanel } from "./thread-panel.js";
9
11
  import { PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, countLines, expandAll, findTokenRanges, formatToken, isPasteBlock, nextSeq, pruneBlocks, recollapsePastes, remapCarriedBlocks, shouldCollapse, stripTrailingBlankLines, tokenRangeAt } from "./paste-tokens.js";
10
- export { AttachmentCard, BusySendButton, ChatComposer, ComposerAttachmentButton, ComposerHint, ConversationAvatar, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, ThreadPanel, TranscriptComposition, countLines, expandAll, findTokenRanges, formatToken, isPasteBlock, nextSeq, pruneBlocks, recollapsePastes, remapCarriedBlocks, shouldCollapse, stripTrailingBlankLines, tokenRangeAt, transcriptDisclosureKey };
12
+ export { AttachmentCard, BusySendButton, ChatComposer, ComposerAttachmentButton, ComposerHint, ComposerMenu, ComposerMenuItem, ConversationAvatar, ConversationPane, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, ThreadPanel, TranscriptComposition, countLines, expandAll, findTokenRanges, formatToken, isPasteBlock, nextSeq, pruneBlocks, recollapsePastes, remapCarriedBlocks, shouldCollapse, stripTrailingBlankLines, tokenRangeAt, transcriptDisclosureKey };
@@ -52,6 +52,12 @@ export type MessageComposerProps = Omit<ComponentProps<'form'>, 'onSubmit'> & {
52
52
  trailing?: JSX.Element;
53
53
  /** A menu rendered above the field, e.g. mention suggestions. */
54
54
  menu?: JSX.Element;
55
+ /**
56
+ * Host progress rendered in the composer's own live region, e.g. dictation
57
+ * state — plain paragraphs are progress, a `role="alert"` paragraph is a
58
+ * failure. Sending and send-failure copy stays the composer's own.
59
+ */
60
+ status?: JSX.Element;
55
61
  /** The reply target, drawn as a strip above the field. */
56
62
  replyTo?: {
57
63
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"message-composer.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/message-composer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAIxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAgB5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IAC5E,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,iFAAiF;IACjF,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sDAAsD;IACtD,OAAO,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACtB,iEAAiE;IACjE,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,IAAI,CAAA;KAAE,CAAA;IAClD,iFAAiF;IACjF,QAAQ,CAAC,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAA;IACnC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gFAAgF;IAChF,SAAS,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACrC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;CAC3C,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,eAmM1D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,eAkB1E;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,eAetD"}
1
+ {"version":3,"file":"message-composer.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/message-composer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAIxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAgB5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IAC5E,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,iFAAiF;IACjF,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sDAAsD;IACtD,OAAO,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACtB,iEAAiE;IACjE,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACpB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,IAAI,CAAA;KAAE,CAAA;IAClD,iFAAiF;IACjF,QAAQ,CAAC,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAA;IACnC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gFAAgF;IAChF,SAAS,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACrC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;CAC3C,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,eAqM1D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,eAkB1E;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,eAetD"}
@@ -34,6 +34,7 @@ function MessageComposer(props) {
34
34
  "leading",
35
35
  "trailing",
36
36
  "menu",
37
+ "status",
37
38
  "replyTo",
38
39
  "inputRef",
39
40
  "inputId",
@@ -255,7 +256,15 @@ function MessageComposer(props) {
255
256
  get children() {
256
257
  return [memo(() => pendingLabel()), "…"];
257
258
  }
258
- }));
259
+ }), null);
260
+ insert(_el$10, createComponent(Show, {
261
+ get when() {
262
+ return local.status;
263
+ },
264
+ get children() {
265
+ return local.status;
266
+ }
267
+ }), null);
259
268
  effect(() => className(_el$3, cn("border-input bg-card flex flex-col gap-1 rounded-lg border p-2", "transition-[color,box-shadow,border-color] ease-out", "focus-within:border-ring focus-within:ring-3 focus-within:ring-primary-subtle", local.disabled && "opacity-50")));
260
269
  return _el$;
261
270
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"message-composer.js","names":["CornerDownLeft","Paperclip","Send","X","ComponentProps","JSX","Ref","Show","createSignal","createUniqueId","splitProps","cn","ActionButton","Button","Kbd","Spinner","Textarea","createComposerImeGuard","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","MessageComposerProps","Omit","value","onValueChange","onSubmit","Promise","placeholder","disabled","submitLabel","showHint","leading","Element","trailing","menu","replyTo","label","onDismiss","inputRef","HTMLTextAreaElement","inputId","inputLabel","inputDescription","inputDescribedBy","inputSize","inputResize","MessageComposer","props","local","rest","sending","setSending","error","setError","ime","descriptionId","describedBy","undefined","filter","Boolean","join","actionLabel","pendingLabel","toLowerCase","canSend","trim","length","send","onKeyDown","EventHandlerUnion","KeyboardEvent","defaultPrevented","key","shiftKey","metaKey","ctrlKey","claimEnter","onFormKeyDown","HTMLFormElement","isComposing","keyCode","preventDefault","stopPropagation","_el$","_tmpl$3","_el$3","firstChild","_el$4","_el$5","_el$10","nextSibling","$$keydown","addEventListener","_$spread","_$mergeProps","class","_$insert","_$createComponent","when","children","_el$2","_tmpl$","reply","_el$11","_tmpl$4","_el$12","_el$13","type","variant","size","tooltip","onClick","ref","r$","_ref$","id","onCompositionStart","onCompositionEnd","onFocus","onBlur","onInput","currentTarget","rows","aria-label","aria-describedby","resize","description","_el$14","_tmpl$5","_$setAttribute","_$memo","fallback","_el$6","_tmpl$2","_el$7","_el$8","_el$9","_el$1","_el$0","message","_el$15","_tmpl$6","_$effect","_$className","ComposerAttachmentButton","count","open","aria-expanded","ComposerHint","_el$16","_tmpl$7","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$delegateEvents"],"sources":["../../../src/components/conversation/message-composer.tsx"],"sourcesContent":["import { CornerDownLeft, Paperclip, Send, X } from 'lucide-solid'\nimport type { ComponentProps, JSX, Ref } from 'solid-js'\nimport { Show, createSignal, createUniqueId, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { ActionButton } from '../composites/action-button/action-button'\nimport { Button } from '../ui/button/button'\nimport { Kbd } from '../ui/kbd/kbd'\nimport { Spinner } from '../ui/spinner/spinner'\nimport { Textarea } from '../ui/textarea/textarea'\nimport { createComposerImeGuard } from './ime-guard'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\n/**\n * MessageComposer.\n *\n * The field a message is written in. It is a form, and it behaves like one: Enter\n * sends, Shift+Enter breaks the line, Escape clears the error from anywhere in\n * the composer unless a nested control or an active IME already owns the key.\n *\n * ## What it does not know\n *\n * No mention model, no attachment model, no dictation, no idempotency keys. The\n * first version of this composer was written against adea's agent and artifact\n * types, which meant it could only ever be used by adea. Here the attachment control\n * is a *slot*, the mention menu is a slot, and a caller that has an agent model\n * renders one; a caller that does not gets a composer without it.\n *\n * ## The three things it does own\n *\n * **Enter sends, Shift+Enter breaks the line.** That is the convention every chat\n * application shares, and getting it wrong is the single most irritating thing a\n * composer can do. `⌘`/`Ctrl`+Enter is accepted too, because someone arriving from an\n * editor will try it.\n *\n * **The send button is disabled when there is nothing to send.** A control that\n * accepts a press and does nothing is worse than one that says it cannot.\n *\n * **The status region is `aria-live`.** \"Sending…\" and a failure both land there, so\n * a screen reader hears the outcome without the composer stealing focus.\n *\n * Enter ownership follows KiroCrew's pinned IME latch: candidate commits keep\n * their native default action, and the post-composition Enter cannot send or\n * insert an accidental newline. Composition abandoned by focus/blur recovers;\n * the Solid owner's cleanup settles its timer. See ime-guard.ts for provenance.\n */\nexport type MessageComposerProps = Omit<ComponentProps<'form'>, 'onSubmit'> & {\n /** The draft. Controlled: the caller owns the text, because it usually persists. */\n value: string\n onValueChange: (value: string) => void\n /** Called on send. A rejection is surfaced as an error and the draft is kept. */\n onSubmit: () => void | Promise<void>\n placeholder?: string\n /** Disable the whole composer, e.g. while the channel is read-only. */\n disabled?: boolean\n /** Accessible name and tooltip for the action, e.g. \"Reply\". */\n submitLabel?: string\n /** Show the keyboard hint under the field. */\n showHint?: boolean\n /** A leading control group, e.g. an attach button. */\n leading?: JSX.Element\n /** A trailing group before the send button, e.g. a dictation toggle. */\n trailing?: JSX.Element\n /** A menu rendered above the field, e.g. mention suggestions. */\n menu?: JSX.Element\n /** The reply target, drawn as a strip above the field. */\n replyTo?: { label: string; onDismiss: () => void }\n /** Ref to the actual message textarea, for host focus and selection behavior. */\n inputRef?: Ref<HTMLTextAreaElement>\n /** Stable host-owned id for the actual textarea. */\n inputId?: string\n /** Accessible name for the actual textarea. Defaults to \"Message\" or \"Reply message\". */\n inputLabel?: string\n /** Additional help text associated with the actual textarea. */\n inputDescription?: string\n /** Existing host description id, combined with `inputDescription` when supplied. */\n inputDescribedBy?: string\n /** Comfortable uses the shared 4rem minimum and 12rem maximum field heights. */\n inputSize?: 'default' | 'comfortable'\n /** The shared resize behavior for the actual textarea. */\n inputResize?: 'vertical' | 'none' | 'both'\n}\n\nexport function MessageComposer(props: MessageComposerProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'value',\n 'onValueChange',\n 'onSubmit',\n 'placeholder',\n 'disabled',\n 'submitLabel',\n 'showHint',\n 'leading',\n 'trailing',\n 'menu',\n 'replyTo',\n 'inputRef',\n 'inputId',\n 'inputLabel',\n 'inputDescription',\n 'inputDescribedBy',\n 'inputSize',\n 'inputResize',\n 'onKeyDown',\n ])\n\n const [sending, setSending] = createSignal(false)\n const [error, setError] = createSignal<string | null>(null)\n const ime = createComposerImeGuard()\n const descriptionId = `message-composer-help-${createUniqueId()}`\n const describedBy = () =>\n [local.inputDescribedBy, local.inputDescription ? descriptionId : undefined]\n .filter(Boolean)\n .join(' ') || undefined\n const actionLabel = () => local.submitLabel ?? 'Send message'\n const pendingLabel = () =>\n `Sending ${local.submitLabel ? local.submitLabel.toLowerCase() : 'message'}`\n\n const canSend = () => local.value.trim().length > 0 && !local.disabled && !sending()\n\n const send = async () => {\n if (!canSend()) return\n setSending(true)\n setError(null)\n try {\n await local.onSubmit()\n } catch {\n // The draft is deliberately left in place. A send that fails and clears the\n // field loses the user's work, which is the worst outcome available here.\n setError('Message not sent. Your draft is still here; retry when the connection recovers.')\n } finally {\n setSending(false)\n }\n }\n\n const onKeyDown: JSX.EventHandlerUnion<HTMLTextAreaElement, KeyboardEvent> = (event) => {\n if (event.defaultPrevented) return\n if (event.key !== 'Enter') return\n // Shift breaks the line; a bare Enter, or a modified one, sends.\n if (event.shiftKey && !event.metaKey && !event.ctrlKey) return\n if (!ime.claimEnter(event)) return\n void send()\n }\n\n const onFormKeyDown: JSX.EventHandlerUnion<HTMLFormElement, KeyboardEvent> = (event) => {\n invokeEventHandler(local.onKeyDown, event)\n if (\n event.defaultPrevented ||\n event.key !== 'Escape' ||\n !error() ||\n event.isComposing ||\n event.keyCode === 229\n ) {\n return\n }\n setError(null)\n event.preventDefault()\n event.stopPropagation()\n }\n\n return (\n <form\n data-slot=\"message-composer\"\n class={cn('flex flex-col gap-2', local.class)}\n onSubmit={(event) => {\n event.preventDefault()\n void send()\n }}\n onKeyDown={onFormKeyDown}\n {...rest}\n >\n <Show when={local.menu}>\n <div>{local.menu}</div>\n </Show>\n\n <Show when={local.replyTo}>\n {(reply) => (\n <div class=\"bg-muted text-muted-foreground flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs\">\n <span class=\"min-w-0 flex-1 truncate\">Replying to {reply().label}</span>\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label=\"Cancel reply\"\n tooltip=\"Cancel reply\"\n onClick={() => reply().onDismiss()}\n >\n <X />\n </ActionButton>\n </div>\n )}\n </Show>\n\n <div\n class={cn(\n 'border-input bg-card flex flex-col gap-1 rounded-lg border p-2',\n 'transition-[color,box-shadow,border-color] ease-out',\n 'focus-within:border-ring focus-within:ring-3 focus-within:ring-primary-subtle',\n local.disabled && 'opacity-50'\n )}\n >\n <Textarea\n ref={local.inputRef}\n id={local.inputId}\n onCompositionStart={ime.onCompositionStart}\n onCompositionEnd={ime.onCompositionEnd}\n onFocus={ime.onFocus}\n onBlur={ime.onBlur}\n value={local.value}\n onInput={(event) => local.onValueChange(event.currentTarget.value)}\n onKeyDown={onKeyDown}\n placeholder={local.placeholder ?? 'Write a message…'}\n disabled={local.disabled}\n rows={1}\n aria-label={\n local.inputLabel ?? (local.submitLabel ? `${local.submitLabel} message` : 'Message')\n }\n aria-describedby={describedBy()}\n variant=\"composer\"\n size={local.inputSize ?? 'comfortable'}\n resize={local.inputResize ?? 'vertical'}\n />\n <Show when={local.inputDescription}>\n {(description) => (\n <span id={descriptionId} class=\"sr-only\">\n {description()}\n </span>\n )}\n </Show>\n\n <div class=\"flex items-center gap-1\">\n <Show when={local.leading}>{local.leading}</Show>\n <div class=\"ms-auto flex items-center gap-1\">\n <Show when={local.trailing}>{local.trailing}</Show>\n <ActionButton\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!canSend()}\n aria-label={sending() ? pendingLabel() : actionLabel()}\n tooltip={actionLabel()}\n >\n <Show when={sending()} fallback={<Send />}>\n <Spinner size=\"sm\" label={false} class=\"text-primary-foreground\" />\n </Show>\n </ActionButton>\n </div>\n </div>\n </div>\n\n <Show when={local.showHint}>\n <p class=\"text-muted-foreground flex items-center gap-1.5 text-2xs\">\n <Kbd>Enter</Kbd> to send\n <span aria-hidden=\"true\">·</span>\n <Kbd>Shift</Kbd> <Kbd>Enter</Kbd> for a new line\n </p>\n </Show>\n\n {/* A live region, so the outcome is announced without moving focus out of the\n field the user is typing in. */}\n <div role=\"status\" aria-live=\"polite\" class=\"min-h-0\">\n <Show\n when={sending()}\n fallback={\n <Show when={error()}>\n {(message) => (\n <p class=\"text-foreground border-s-2 border-destructive ps-2 text-xs\">\n {message()}\n </p>\n )}\n </Show>\n }\n >\n {pendingLabel()}…\n </Show>\n </div>\n </form>\n )\n}\n\n/**\n * The attachment control.\n *\n * A slot rather than a built-in, because what can be attached is the application's\n * business — but the *button* is shared, so it looks and behaves the same in both.\n * The count is announced, since a paperclip alone does not say whether anything is\n * attached.\n */\nexport function ComposerAttachmentButton(\n props: ComponentProps<typeof Button> & { count?: number; open?: boolean }\n) {\n const [local, rest] = splitProps(props, ['count', 'open', 'children'])\n\n return (\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={local.count ? `${local.count} attached, add an attachment` : 'Add an attachment'}\n aria-expanded={local.open}\n tooltip=\"Add an attachment\"\n class=\"text-muted-foreground\"\n {...rest}\n >\n {local.children ?? <Paperclip />}\n </ActionButton>\n )\n}\n\n/** The hint a composer shows when the field is empty, as a one-line prompt. */\nexport function ComposerHint(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n return (\n <p\n class={cn('text-muted-foreground flex items-center gap-1.5 text-2xs', local.class)}\n {...rest}\n >\n {local.children ?? (\n <>\n <CornerDownLeft aria-hidden=\"true\" class=\"size-3\" />\n <Kbd>Enter</Kbd> to send\n </>\n )}\n </p>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAWA,SAASkB,mBAAmBC,SAAkBC,OAAc;CAC1D,IAAIE,MAAMC,QAAQJ,OAAO,GAAG;EAC1B,MAAM,CAACK,UAAUC,QAAQN;EACzBK,SAASC,MAAML,KAAK;CACtB,OAAO,IAAI,OAAOD,YAAY,YAE5BK,QAASJ,KAAK;AAElB;AAwEA,SAAgB+B,gBAAgBC,OAA6B;CAC3D,MAAM,CAACC,OAAOC,QAAQ5C,WAAW0C,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAW,CACZ;CAED,MAAM,CAACG,SAASC,cAAchD,aAAa,KAAK;CAChD,MAAM,CAACiD,OAAOC,YAAYlD,aAA4B,IAAI;CAC1D,MAAMmD,MAAM1C,uBAAuB;CACnC,MAAM2C,gBAAgB,yBAAyBnD,eAAe;CAC9D,MAAMoD,oBACJ,CAACR,MAAML,kBAAkBK,MAAMN,mBAAmBa,gBAAgBE,KAAAA,CAAS,CAAC,CACzEC,OAAOC,OAAO,CAAC,CACfC,KAAK,GAAG,KAAKH,KAAAA;CAClB,MAAMI,oBAAoBb,MAAMnB,eAAe;CAC/C,MAAMiC,qBACJ,WAAWd,MAAMnB,cAAcmB,MAAMnB,YAAYkC,YAAY,IAAI;CAEnE,MAAMC,gBAAgBhB,MAAMzB,MAAM0C,KAAK,CAAC,CAACC,SAAS,KAAK,CAAClB,MAAMpB,YAAY,CAACsB,QAAQ;CAEnF,MAAMiB,OAAO,YAAY;EACvB,IAAI,CAACH,QAAQ,GAAG;EAChBb,WAAW,IAAI;EACfE,SAAS,IAAI;EACb,IAAI;GACF,MAAML,MAAMvB,SAAS;EACvB,QAAQ;GAGN4B,SAAS,iFAAiF;EAC5F,UAAU;GACRF,WAAW,KAAK;EAClB;CACF;CAEA,MAAMiB,aAAwErD,UAAU;EACtF,IAAIA,MAAMwD,kBAAkB;EAC5B,IAAIxD,MAAMyD,QAAQ,SAAS;EAE3B,IAAIzD,MAAM0D,YAAY,CAAC1D,MAAM2D,WAAW,CAAC3D,MAAM4D,SAAS;EACxD,IAAI,CAACrB,IAAIsB,WAAW7D,KAAK,GAAG;EAC5B,KAAU;CACZ;CAEA,MAAM8D,iBAAwE9D,UAAU;EACtFF,mBAAmBmC,MAAMoB,WAAWrD,KAAK;EACzC,IACEA,MAAMwD,oBACNxD,MAAMyD,QAAQ,YACd,CAACpB,MAAM,KACPrC,MAAMgE,eACNhE,MAAMiE,YAAY,KAElB;EAEF3B,SAAS,IAAI;EACbtC,MAAMkE,eAAe;EACrBlE,MAAMmE,gBAAgB;CACxB;CAEA,cAAA;EAAA,IAAAC,OAAAC,QAAA,GAAAC,QAAAF,KAAAG,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAD,YAAAG,SAAAJ,MAAAK;EAAAP,KAAAQ,YAQed;EAAaM,KAAAS,iBAAA,WAJb7E,UAAU;GACnBA,MAAMkE,eAAe;GACrB,KAAU;EACZ,CAAC;EAAAY,OAAAV,MAAAW,WAAA,EAAA,KAAA,WAAA;GAAA,OAJMxF,GAAG,uBAAuB0C,MAAM+C,KAAK;EAAC,EAAA,GAMzC9C,IAAI,GAAA,OAAA,IAAA;EAAA+C,OAAAb,MAAAc,gBAEP/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMd;GAAI;GAAA,IAAAiE,WAAA;IAAA,IAAAC,QAAAC,OAAA;IAAAL,OAAAI,aACdpD,MAAMd,IAAI;IAAA,OAAAkE;GAAA;EAAA,CAAA,GAAAf,KAAA;EAAAW,OAAAb,MAAAc,gBAGjB/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMb;GAAO;GAAAgE,WACrBG,iBAAK;IAAA,IAAAC,SAAAC,QAAA,GAAAC,SAAAF,OAAAjB;IAAAmB,OAAAnB;IAAAU,OAAAS,cAEgDH,MAAM,CAAC,CAAClE,OAAK,IAAA;IAAA4D,OAAAO,QAAAN,gBAC/D1F,cAAY;KACXoG,MAAI;KACJC,SAAO;KACPC,MAAI;KAAA,cAAA;KAEJC,SAAO;KACPC,eAAeT,MAAM,CAAC,CAACjE,UAAU;KAAC,IAAA8D,WAAA;MAAA,OAAAF,gBAEjCnG,GAAC,CAAA,CAAA;KAAA;IAAA,CAAA,GAAA,IAAA;IAAA,OAAAyG;GAAA,EAAA,CAAA;EAGP,CAAA,GAAAlB,KAAA;EAAAW,OAAAX,OAAAY,gBAWAtF,UAAQ;GAAAqG,IAAAC,IAAA;IAAA,IAAAC,QACFlE,MAAMV;IAAQ,OAAA4E,UAAA,aAAAA,MAAAD,EAAA,IAAdjE,MAAMV,WAAQ2E;GAAA;GAAA,IACnBE,KAAE;IAAA,OAAEnE,MAAMR;GAAO;GAAA,IACjB4E,qBAAkB;IAAA,OAAE9D,IAAI8D;GAAkB;GAAA,IAC1CC,mBAAgB;IAAA,OAAE/D,IAAI+D;GAAgB;GAAA,IACtCC,UAAO;IAAA,OAAEhE,IAAIgE;GAAO;GAAA,IACpBC,SAAM;IAAA,OAAEjE,IAAIiE;GAAM;GAAA,IAClBhG,QAAK;IAAA,OAAEyB,MAAMzB;GAAK;GAClBiG,UAAUzG,UAAUiC,MAAMxB,cAAcT,MAAM0G,cAAclG,KAAK;GACtD6C;GAAS,IACpBzC,cAAW;IAAA,OAAEqB,MAAMrB,eAAe;GAAkB;GAAA,IACpDC,WAAQ;IAAA,OAAEoB,MAAMpB;GAAQ;GACxB8F,MAAM;GAAC,KAAA,gBAAA;IAAA,OAEL1E,MAAMP,eAAeO,MAAMnB,cAAc,GAAGmB,MAAMnB,YAAW,YAAa;GAAU;GAAA,KAAA,sBAAA;IAAA,OAEpE2B,YAAY;GAAC;GAC/BoD,SAAO;GAAA,IACPC,OAAI;IAAA,OAAE7D,MAAMJ,aAAa;GAAa;GAAA,IACtCiF,SAAM;IAAA,OAAE7E,MAAMH,eAAe;GAAU;EAAA,CAAA,GAAA0C,KAAA;EAAAS,OAAAX,OAAAY,gBAExC/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMN;GAAgB;GAAAyD,WAC9B2B,uBAAW;IAAA,IAAAC,SAAAC,QAAA;IAAAC,aAAAF,QAAA,MACDxE,aAAa;IAAAyC,OAAA+B,QACpBD,WAAW;IAAA,OAAAC;GAAA,EAAA,CAAA;EAEf,CAAA,GAAAxC,KAAA;EAAAS,OAAAT,OAAAU,gBAIA/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMjB;GAAO;GAAA,IAAAoE,WAAA;IAAA,OAAGnD,MAAMjB;GAAO;EAAA,CAAA,GAAAyD,KAAA;EAAAQ,OAAAR,OAAAS,gBAEtC/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMf;GAAQ;GAAA,IAAAkE,WAAA;IAAA,OAAGnD,MAAMf;GAAQ;EAAA,CAAA,GAAA,IAAA;EAAA+D,OAAAR,OAAAS,gBAC1C1F,cAAY;GACXoG,MAAI;GACJE,MAAI;GAAA,IACJjF,WAAQ;IAAA,OAAE,CAACoC,QAAQ;GAAC;GAAA,KAAA,gBAAA;IAAA,OACRkE,WAAA,CAAA,CAAAhF,QAAQ,CAAC,CAAA,CAAA,IAAGY,aAAa,IAAID,YAAY;GAAC;GAAA,IACtDiD,UAAO;IAAA,OAAEjD,YAAY;GAAC;GAAA,IAAAsC,WAAA;IAAA,OAAAF,gBAErB/F,MAAI;KAAA,IAACgG,OAAI;MAAA,OAAEhD,QAAQ;KAAC;KAAA,IAAEiF,WAAQ;MAAA,OAAAlC,gBAAGpG,MAAI,CAAA,CAAA;KAAA;KAAA,IAAAsG,WAAA;MAAA,OAAAF,gBACnCvF,SAAO;OAACmG,MAAI;OAAMzE,OAAO;OAAK,SAAA;MAAA,CAAA;KAAA;IAAA,CAAA;GAAA;EAAA,CAAA,GAAA,IAAA;EAAA4D,OAAAb,MAAAc,gBAOxC/F,MAAI;GAAA,IAACgG,OAAI;IAAA,OAAElD,MAAMlB;GAAQ;GAAA,IAAAqE,WAAA;IAAA,IAAAiC,QAAAC,QAAA,GAAAC,QAAAF,MAAA9C,YAAAkD,QAAAF,MAAA5C,YAAAA,aAAA+C,QAAAD,MAAA9C;IAAA+C,MAAA/C;IAAAM,OAAAoC,OAAAnC,gBAErBxF,KAAG,EAAA0F,UAAA,QAAA,CAAA,GAAAmC,KAAA;IAAAtC,OAAAoC,OAAAnC,gBAEHxF,KAAG,EAAA0F,UAAA,QAAA,CAAA,GAAAqC,KAAA;IAAAxC,OAAAoC,OAAAnC,gBAAcxF,KAAG,EAAA0F,UAAA,QAAA,CAAA,GAAAsC,KAAA;IAAA,OAAAL;GAAA;EAAA,CAAA,GAAA3C,MAAA;EAAAO,OAAAP,QAAAQ,gBAOtB/F,MAAI;GAAA,IACHgG,OAAI;IAAA,OAAEhD,QAAQ;GAAC;GAAA,IACfiF,WAAQ;IAAA,OAAAlC,gBACL/F,MAAI;KAAA,IAACgG,OAAI;MAAA,OAAE9C,MAAM;KAAC;KAAA+C,WACfwC,mBAAO;MAAA,IAAAC,SAAAC,QAAA;MAAA7C,OAAA4C,QAEJD,OAAO;MAAA,OAAAC;KAAA,EAAA,CAAA;IAEX,CAAA;GAAA;GAAA,IAAAzC,WAAA;IAAA,OAAA,CAAA+B,WAIJpE,aAAa,CAAC,GAAA,GAAA;GAAA;EAAA,CAAA,CAAA;EAAAgF,aAAAC,UAAA1D,OA9EV/E,GACL,kEACA,uDACA,iFACA0C,MAAMpB,YAAY,YACpB,CAAC,CAAA;EAAA,OAAAuD;CAAA,EAAA,CAAA;AA8ET;;;;;;;;;AAUA,SAAgB6D,yBACdjG,OACA;CACA,MAAM,CAACC,OAAOC,QAAQ5C,WAAW0C,OAAO;EAAC;EAAS;EAAQ;CAAU,CAAC;CAErE,OAAAkD,gBACG1F,cAAYuF,WAAA;EACXa,MAAI;EACJC,SAAO;EACPC,MAAI;EAAA,KAAA,gBAAA;GAAA,OACQqB,WAAA,CAAA,CAAAlF,MAAMiG,KAAK,CAAA,CAAA,IAAG,GAAGjG,MAAMiG,MAAK,gCAAiC;EAAmB;EAAA,KAAA,mBAAA;GAAA,OAC7EjG,MAAMkG;EAAI;EACzBpC,SAAO;EAAA,SAAA;CAAA,GAEH7D,MAAI,EAAA,IAAAkD,WAAA;EAAA,OAEPnD,MAAMmD,YAAQF,gBAAKrG,WAAS,CAAA,CAAA;CAAG,EAAA,CAAA,CAAA;AAGtC;;AAGA,SAAgBwJ,aAAarG,OAA4B;CACvD,MAAM,CAACC,OAAOC,QAAQ5C,WAAW0C,OAAO,CAAC,SAAS,UAAU,CAAC;CAC7D,cAAA;EAAA,IAAAsG,SAAAC,QAAA;EAAAzD,OAAAwD,QAAAvD,WAAA,EAAA,KAAA,WAAA;GAAA,OAEWxF,GAAG,4DAA4D0C,MAAM+C,KAAK;EAAC,EAAA,GAC9E9C,IAAI,GAAA,OAAA,IAAA;EAAA+C,OAAAqD,cAEPrG,MAAMmD,YAAQ;GAAAF,gBAEVtG,gBAAc;IAAA,eAAA;IAAA,SAAA;GAAA,CAAA;GAAAsG,gBACdxF,KAAG,EAAA0F,UAAA,QAAA,CAAA;GAAA;EAAA,CAEP;EAAA,OAAAkD;CAAA,EAAA,CAAA;AAGP;AAACE,eAAA,CAAA,SAAA,CAAA"}
1
+ {"version":3,"file":"message-composer.js","names":["CornerDownLeft","Paperclip","Send","X","ComponentProps","JSX","Ref","Show","createSignal","createUniqueId","splitProps","cn","ActionButton","Button","Kbd","Spinner","Textarea","createComposerImeGuard","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","MessageComposerProps","Omit","value","onValueChange","onSubmit","Promise","placeholder","disabled","submitLabel","showHint","leading","Element","trailing","menu","status","replyTo","label","onDismiss","inputRef","HTMLTextAreaElement","inputId","inputLabel","inputDescription","inputDescribedBy","inputSize","inputResize","MessageComposer","props","local","rest","sending","setSending","error","setError","ime","descriptionId","describedBy","undefined","filter","Boolean","join","actionLabel","pendingLabel","toLowerCase","canSend","trim","length","send","onKeyDown","EventHandlerUnion","KeyboardEvent","defaultPrevented","key","shiftKey","metaKey","ctrlKey","claimEnter","onFormKeyDown","HTMLFormElement","isComposing","keyCode","preventDefault","stopPropagation","_el$","_tmpl$3","_el$3","firstChild","_el$4","_el$5","_el$10","nextSibling","$$keydown","addEventListener","_$spread","_$mergeProps","class","_$insert","_$createComponent","when","children","_el$2","_tmpl$","reply","_el$11","_tmpl$4","_el$12","_el$13","type","variant","size","tooltip","onClick","ref","r$","_ref$","id","onCompositionStart","onCompositionEnd","onFocus","onBlur","onInput","currentTarget","rows","aria-label","aria-describedby","resize","description","_el$14","_tmpl$5","_$setAttribute","_$memo","fallback","_el$6","_tmpl$2","_el$7","_el$8","_el$9","_el$1","_el$0","message","_el$15","_tmpl$6","_$effect","_$className","ComposerAttachmentButton","count","open","aria-expanded","ComposerHint","_el$16","_tmpl$7","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$delegateEvents"],"sources":["../../../src/components/conversation/message-composer.tsx"],"sourcesContent":["import { CornerDownLeft, Paperclip, Send, X } from 'lucide-solid'\nimport type { ComponentProps, JSX, Ref } from 'solid-js'\nimport { Show, createSignal, createUniqueId, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { ActionButton } from '../composites/action-button/action-button'\nimport { Button } from '../ui/button/button'\nimport { Kbd } from '../ui/kbd/kbd'\nimport { Spinner } from '../ui/spinner/spinner'\nimport { Textarea } from '../ui/textarea/textarea'\nimport { createComposerImeGuard } from './ime-guard'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\n/**\n * MessageComposer.\n *\n * The field a message is written in. It is a form, and it behaves like one: Enter\n * sends, Shift+Enter breaks the line, Escape clears the error from anywhere in\n * the composer unless a nested control or an active IME already owns the key.\n *\n * ## What it does not know\n *\n * No mention model, no attachment model, no dictation, no idempotency keys. The\n * first version of this composer was written against adea's agent and artifact\n * types, which meant it could only ever be used by adea. Here the attachment control\n * is a *slot*, the mention menu is a slot, and a caller that has an agent model\n * renders one; a caller that does not gets a composer without it.\n *\n * ## The three things it does own\n *\n * **Enter sends, Shift+Enter breaks the line.** That is the convention every chat\n * application shares, and getting it wrong is the single most irritating thing a\n * composer can do. `⌘`/`Ctrl`+Enter is accepted too, because someone arriving from an\n * editor will try it.\n *\n * **The send button is disabled when there is nothing to send.** A control that\n * accepts a press and does nothing is worse than one that says it cannot.\n *\n * **The status region is `aria-live`.** \"Sending…\" and a failure both land there, so\n * a screen reader hears the outcome without the composer stealing focus.\n *\n * Enter ownership follows KiroCrew's pinned IME latch: candidate commits keep\n * their native default action, and the post-composition Enter cannot send or\n * insert an accidental newline. Composition abandoned by focus/blur recovers;\n * the Solid owner's cleanup settles its timer. See ime-guard.ts for provenance.\n */\nexport type MessageComposerProps = Omit<ComponentProps<'form'>, 'onSubmit'> & {\n /** The draft. Controlled: the caller owns the text, because it usually persists. */\n value: string\n onValueChange: (value: string) => void\n /** Called on send. A rejection is surfaced as an error and the draft is kept. */\n onSubmit: () => void | Promise<void>\n placeholder?: string\n /** Disable the whole composer, e.g. while the channel is read-only. */\n disabled?: boolean\n /** Accessible name and tooltip for the action, e.g. \"Reply\". */\n submitLabel?: string\n /** Show the keyboard hint under the field. */\n showHint?: boolean\n /** A leading control group, e.g. an attach button. */\n leading?: JSX.Element\n /** A trailing group before the send button, e.g. a dictation toggle. */\n trailing?: JSX.Element\n /** A menu rendered above the field, e.g. mention suggestions. */\n menu?: JSX.Element\n /**\n * Host progress rendered in the composer's own live region, e.g. dictation\n * state — plain paragraphs are progress, a `role=\"alert\"` paragraph is a\n * failure. Sending and send-failure copy stays the composer's own.\n */\n status?: JSX.Element\n /** The reply target, drawn as a strip above the field. */\n replyTo?: { label: string; onDismiss: () => void }\n /** Ref to the actual message textarea, for host focus and selection behavior. */\n inputRef?: Ref<HTMLTextAreaElement>\n /** Stable host-owned id for the actual textarea. */\n inputId?: string\n /** Accessible name for the actual textarea. Defaults to \"Message\" or \"Reply message\". */\n inputLabel?: string\n /** Additional help text associated with the actual textarea. */\n inputDescription?: string\n /** Existing host description id, combined with `inputDescription` when supplied. */\n inputDescribedBy?: string\n /** Comfortable uses the shared 4rem minimum and 12rem maximum field heights. */\n inputSize?: 'default' | 'comfortable'\n /** The shared resize behavior for the actual textarea. */\n inputResize?: 'vertical' | 'none' | 'both'\n}\n\nexport function MessageComposer(props: MessageComposerProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'value',\n 'onValueChange',\n 'onSubmit',\n 'placeholder',\n 'disabled',\n 'submitLabel',\n 'showHint',\n 'leading',\n 'trailing',\n 'menu',\n 'status',\n 'replyTo',\n 'inputRef',\n 'inputId',\n 'inputLabel',\n 'inputDescription',\n 'inputDescribedBy',\n 'inputSize',\n 'inputResize',\n 'onKeyDown',\n ])\n\n const [sending, setSending] = createSignal(false)\n const [error, setError] = createSignal<string | null>(null)\n const ime = createComposerImeGuard()\n const descriptionId = `message-composer-help-${createUniqueId()}`\n const describedBy = () =>\n [local.inputDescribedBy, local.inputDescription ? descriptionId : undefined]\n .filter(Boolean)\n .join(' ') || undefined\n const actionLabel = () => local.submitLabel ?? 'Send message'\n const pendingLabel = () =>\n `Sending ${local.submitLabel ? local.submitLabel.toLowerCase() : 'message'}`\n\n const canSend = () => local.value.trim().length > 0 && !local.disabled && !sending()\n\n const send = async () => {\n if (!canSend()) return\n setSending(true)\n setError(null)\n try {\n await local.onSubmit()\n } catch {\n // The draft is deliberately left in place. A send that fails and clears the\n // field loses the user's work, which is the worst outcome available here.\n setError('Message not sent. Your draft is still here; retry when the connection recovers.')\n } finally {\n setSending(false)\n }\n }\n\n const onKeyDown: JSX.EventHandlerUnion<HTMLTextAreaElement, KeyboardEvent> = (event) => {\n if (event.defaultPrevented) return\n if (event.key !== 'Enter') return\n // Shift breaks the line; a bare Enter, or a modified one, sends.\n if (event.shiftKey && !event.metaKey && !event.ctrlKey) return\n if (!ime.claimEnter(event)) return\n void send()\n }\n\n const onFormKeyDown: JSX.EventHandlerUnion<HTMLFormElement, KeyboardEvent> = (event) => {\n invokeEventHandler(local.onKeyDown, event)\n if (\n event.defaultPrevented ||\n event.key !== 'Escape' ||\n !error() ||\n event.isComposing ||\n event.keyCode === 229\n ) {\n return\n }\n setError(null)\n event.preventDefault()\n event.stopPropagation()\n }\n\n return (\n <form\n data-slot=\"message-composer\"\n class={cn('flex flex-col gap-2', local.class)}\n onSubmit={(event) => {\n event.preventDefault()\n void send()\n }}\n onKeyDown={onFormKeyDown}\n {...rest}\n >\n <Show when={local.menu}>\n <div>{local.menu}</div>\n </Show>\n\n <Show when={local.replyTo}>\n {(reply) => (\n <div class=\"bg-muted text-muted-foreground flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs\">\n <span class=\"min-w-0 flex-1 truncate\">Replying to {reply().label}</span>\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label=\"Cancel reply\"\n tooltip=\"Cancel reply\"\n onClick={() => reply().onDismiss()}\n >\n <X />\n </ActionButton>\n </div>\n )}\n </Show>\n\n <div\n class={cn(\n 'border-input bg-card flex flex-col gap-1 rounded-lg border p-2',\n 'transition-[color,box-shadow,border-color] ease-out',\n 'focus-within:border-ring focus-within:ring-3 focus-within:ring-primary-subtle',\n local.disabled && 'opacity-50'\n )}\n >\n <Textarea\n ref={local.inputRef}\n id={local.inputId}\n onCompositionStart={ime.onCompositionStart}\n onCompositionEnd={ime.onCompositionEnd}\n onFocus={ime.onFocus}\n onBlur={ime.onBlur}\n value={local.value}\n onInput={(event) => local.onValueChange(event.currentTarget.value)}\n onKeyDown={onKeyDown}\n placeholder={local.placeholder ?? 'Write a message…'}\n disabled={local.disabled}\n rows={1}\n aria-label={\n local.inputLabel ?? (local.submitLabel ? `${local.submitLabel} message` : 'Message')\n }\n aria-describedby={describedBy()}\n variant=\"composer\"\n size={local.inputSize ?? 'comfortable'}\n resize={local.inputResize ?? 'vertical'}\n />\n <Show when={local.inputDescription}>\n {(description) => (\n <span id={descriptionId} class=\"sr-only\">\n {description()}\n </span>\n )}\n </Show>\n\n <div class=\"flex items-center gap-1\">\n <Show when={local.leading}>{local.leading}</Show>\n <div class=\"ms-auto flex items-center gap-1\">\n <Show when={local.trailing}>{local.trailing}</Show>\n <ActionButton\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!canSend()}\n aria-label={sending() ? pendingLabel() : actionLabel()}\n tooltip={actionLabel()}\n >\n <Show when={sending()} fallback={<Send />}>\n <Spinner size=\"sm\" label={false} class=\"text-primary-foreground\" />\n </Show>\n </ActionButton>\n </div>\n </div>\n </div>\n\n <Show when={local.showHint}>\n <p class=\"text-muted-foreground flex items-center gap-1.5 text-2xs\">\n <Kbd>Enter</Kbd> to send\n <span aria-hidden=\"true\">·</span>\n <Kbd>Shift</Kbd> <Kbd>Enter</Kbd> for a new line\n </p>\n </Show>\n\n {/* A live region, so the outcome is announced without moving focus out of the\n field the user is typing in. */}\n <div role=\"status\" aria-live=\"polite\" class=\"min-h-0\">\n <Show\n when={sending()}\n fallback={\n <Show when={error()}>\n {(message) => (\n <p class=\"text-foreground border-s-2 border-destructive ps-2 text-xs\">\n {message()}\n </p>\n )}\n </Show>\n }\n >\n {pendingLabel()}…\n </Show>\n <Show when={local.status}>{local.status}</Show>\n </div>\n </form>\n )\n}\n\n/**\n * The attachment control.\n *\n * A slot rather than a built-in, because what can be attached is the application's\n * business — but the *button* is shared, so it looks and behaves the same in both.\n * The count is announced, since a paperclip alone does not say whether anything is\n * attached.\n */\nexport function ComposerAttachmentButton(\n props: ComponentProps<typeof Button> & { count?: number; open?: boolean }\n) {\n const [local, rest] = splitProps(props, ['count', 'open', 'children'])\n\n return (\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={local.count ? `${local.count} attached, add an attachment` : 'Add an attachment'}\n aria-expanded={local.open}\n tooltip=\"Add an attachment\"\n class=\"text-muted-foreground\"\n {...rest}\n >\n {local.children ?? <Paperclip />}\n </ActionButton>\n )\n}\n\n/** The hint a composer shows when the field is empty, as a one-line prompt. */\nexport function ComposerHint(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n return (\n <p\n class={cn('text-muted-foreground flex items-center gap-1.5 text-2xs', local.class)}\n {...rest}\n >\n {local.children ?? (\n <>\n <CornerDownLeft aria-hidden=\"true\" class=\"size-3\" />\n <Kbd>Enter</Kbd> to send\n </>\n )}\n </p>\n )\n}\n"],"mappings":"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"}
@@ -52,5 +52,18 @@ export declare function CommandShortcut(props: {
52
52
  class?: string;
53
53
  children?: ComponentProps<'span'>['children'];
54
54
  }): import("solid-js").JSX.Element;
55
+ /**
56
+ * The status line a command surface reports under its list: searching, offline,
57
+ * a partial result caveat. The copy and the live-role semantics (`status`,
58
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
59
+ * line's shape is not something every caller should redraw.
60
+ */
61
+ export declare function CommandStatus(props: ComponentProps<'p'>): import("solid-js").JSX.Element;
62
+ /**
63
+ * The keyboard hint a palette footer carries, right-aligned under the list so
64
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
65
+ * what the user has already been doing by the time they read it.
66
+ */
67
+ export declare function CommandHint(props: ComponentProps<'p'>): import("solid-js").JSX.Element;
55
68
  export {};
56
69
  //# sourceMappingURL=command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/command.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,IAAI,UAAU,EAC3B,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,WAAW,IAAI,QAAQ,EACvB,WAAW,IAAI,QAAQ,EACvB,cAAc,IAAI,WAAW,EAC7B,WAAW,IAAI,QAAQ,EACvB,gBAAgB,IAAI,aAAa,EAElC,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAa9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAY7D;AAED,KAAK,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GACzD,IAAI,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAAC,CAAA;AAE5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,kCAqEtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAmBnE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAgCjE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAcnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAanE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAkBjE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,kCAG3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,kCAQvE;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAA;CAC9C,kCAWA"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/command.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,IAAI,UAAU,EAC3B,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,WAAW,IAAI,QAAQ,EACvB,WAAW,IAAI,QAAQ,EACvB,cAAc,IAAI,WAAW,EAC7B,WAAW,IAAI,QAAQ,EACvB,gBAAgB,IAAI,aAAa,EAElC,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAa9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAY7D;AAED,KAAK,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GACzD,IAAI,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAAC,CAAA;AAE5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,kCAqEtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAmBnE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAgCjE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAcnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAanE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAkBjE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,kCAG3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,kCAQvE;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAA;CAC9C,kCAWA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,kCAUvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,kCAUrD"}
@@ -1,7 +1,7 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
2
  import { menuItem } from "../../../lib/overlay.js";
3
3
  import { createDialogFocusRestoration } from "../dialog/dialog.js";
4
- import { className, createComponent, effect, insert, mergeProps, template, use } from "solid-js/web";
4
+ import { className, createComponent, effect, insert, mergeProps, spread, template, use } from "solid-js/web";
5
5
  import { Search } from "lucide-solid";
6
6
  import { createEffect, createSignal, splitProps } from "solid-js";
7
7
  import { CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandRoot, CommandSeparator, useCommandState } from "cmdk-solid";
@@ -10,6 +10,8 @@ import { Dialog } from "@kobalte/core/dialog";
10
10
  var _tmpl$ = /*#__PURE__*/ template(`<div data-slot=command-input-wrapper class="flex h-11 items-center gap-2 border-b border-border px-3">`);
11
11
  var _tmpl$2 = /*#__PURE__*/ template(`<div class=contents>`);
12
12
  var _tmpl$3 = /*#__PURE__*/ template(`<span>`);
13
+ var _tmpl$4 = /*#__PURE__*/ template(`<p data-slot=command-status>`);
14
+ var _tmpl$5 = /*#__PURE__*/ template(`<p data-slot=command-hint>`);
13
15
  var commandItem = menuItem.replace("data-[disabled]:pointer-events-none", "").replace("data-[disabled]:text-muted-foreground", "");
14
16
  /**
15
17
  * Command.
@@ -195,7 +197,38 @@ function CommandShortcut(props) {
195
197
  return _el$3;
196
198
  })();
197
199
  }
200
+ /**
201
+ * The status line a command surface reports under its list: searching, offline,
202
+ * a partial result caveat. The copy and the live-role semantics (`status`,
203
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
204
+ * line's shape is not something every caller should redraw.
205
+ */
206
+ function CommandStatus(props) {
207
+ const [local, rest] = splitProps(props, ["class"]);
208
+ return (() => {
209
+ var _el$4 = _tmpl$4();
210
+ spread(_el$4, mergeProps({ get ["class"]() {
211
+ return cn("text-muted-foreground px-4 py-4 text-center text-sm", local.class);
212
+ } }, rest), false, false);
213
+ return _el$4;
214
+ })();
215
+ }
216
+ /**
217
+ * The keyboard hint a palette footer carries, right-aligned under the list so
218
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
219
+ * what the user has already been doing by the time they read it.
220
+ */
221
+ function CommandHint(props) {
222
+ const [local, rest] = splitProps(props, ["class"]);
223
+ return (() => {
224
+ var _el$5 = _tmpl$5();
225
+ spread(_el$5, mergeProps({ get ["class"]() {
226
+ return cn("text-muted-foreground px-4 pb-1.5 text-right text-xs", local.class);
227
+ } }, rest), false, false);
228
+ return _el$5;
229
+ })();
230
+ }
198
231
  //#endregion
199
- export { Command, CommandDialog, CommandEmpty$1 as CommandEmpty, CommandGroup$1 as CommandGroup, CommandInput$1 as CommandInput, CommandItem$1 as CommandItem, CommandList$1 as CommandList, CommandLoading$1 as CommandLoading, CommandSeparator$1 as CommandSeparator, CommandShortcut };
232
+ export { Command, CommandDialog, CommandEmpty$1 as CommandEmpty, CommandGroup$1 as CommandGroup, CommandHint, CommandInput$1 as CommandInput, CommandItem$1 as CommandItem, CommandList$1 as CommandList, CommandLoading$1 as CommandLoading, CommandSeparator$1 as CommandSeparator, CommandShortcut, CommandStatus };
200
233
 
201
234
  //# sourceMappingURL=command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n // The selected row sits on the accent rung — the same primary-subtle\n // fill the settings navigation's selected row owns — instead of the\n // popover rung, so what is chosen keeps the accent the checked menus\n // already carry in their indicators.\n 'group/command-item text-popover-foreground data-[selected=true]:bg-primary-subtle data-[selected=true]:text-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","CommandStatus","_el$4","_tmpl$4","_$spread","CommandHint","_el$5","_tmpl$5","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n // The selected row sits on the accent rung — the same primary-subtle\n // fill the settings navigation's selected row owns — instead of the\n // popover rung, so what is chosen keeps the accent the checked menus\n // already carry in their indicators.\n 'group/command-item text-popover-foreground data-[selected=true]:bg-primary-subtle data-[selected=true]:text-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n\n/**\n * The status line a command surface reports under its list: searching, offline,\n * a partial result caveat. The copy and the live-role semantics (`status`,\n * `alert`) are the caller's — a palette's failure modes are app facts — but the\n * line's shape is not something every caller should redraw.\n */\nexport function CommandStatus(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <p\n data-slot=\"command-status\"\n class={cn('text-muted-foreground px-4 py-4 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/**\n * The keyboard hint a palette footer carries, right-aligned under the list so\n * it reads as furniture rather than a result. Muted on purpose: the arrows are\n * what the user has already been doing by the time they read it.\n */\nexport function CommandHint(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <p\n data-slot=\"command-hint\"\n class={cn('text-muted-foreground px-4 pb-1.5 text-right text-xs', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, } from './command';
1
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus, } from './command';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,WAAW,CAAA"}
@@ -1,2 +1,2 @@
1
- import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut } from "./command.js";
2
- export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut };
1
+ import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus } from "./command.js";
2
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus };
@@ -1,2 +1,3 @@
1
1
  export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants, type KbdChordProps, type KbdSize, } from './kbd';
2
+ export { platformModifierKey, searchShortcutKeyshortcuts, searchShortcutLabel, } from './platform-modifier';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,OAAO,GACb,MAAM,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,OAAO,GACb,MAAM,OAAO,CAAA;AACd,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,qBAAqB,CAAA"}
@@ -1,2 +1,3 @@
1
1
  import { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants } from "./kbd.js";
2
- export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants };
2
+ import { platformModifierKey, searchShortcutKeyshortcuts, searchShortcutLabel } from "./platform-modifier.js";
3
+ export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants, platformModifierKey, searchShortcutKeyshortcuts, searchShortcutLabel };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Which modifier a chord should advertise.
3
+ *
4
+ * Every global chord in the product binds `(metaKey || ctrlKey)`, so the
5
+ * working key is the platform's command modifier wherever the app runs — but
6
+ * Apple platforms draw it as ⌘ and everyone else spells it Ctrl. A chord
7
+ * label drawn from anything else (a hardcoded ⌘, say) advertises a key that
8
+ * does not work as drawn on Windows and Linux.
9
+ *
10
+ * These helpers are the one place that decides the glyph, so every surface
11
+ * that draws or announces a shortcut — rail rows, menus, a pane's search
12
+ * field — draws the same one. They sit next to the `Kbd` caps because the
13
+ * glyph is a property of the drawing, not of the feature that shows it: a
14
+ * spelled-out `Ctrl` needs one cap per word (a `KbdGroup`), while `⌘K` can
15
+ * ride `KbdChord`'s one-cap-per-character split.
16
+ */
17
+ /** The modifier glyph the running OS renders for Meta: ⌘ on Apple platforms, Ctrl elsewhere. */
18
+ export declare function platformModifierKey(platform?: string): '⌘' | 'Ctrl';
19
+ /** The workspace search chord label as the rail's hover text draws it: the
20
+ * platform modifier plus K (`⌘K`, or `Ctrl+K` where ⌘ does not exist). */
21
+ export declare function searchShortcutLabel(platform?: string): string;
22
+ /**
23
+ * The `aria-keyshortcuts` for the search chord. The binding accepts Meta and
24
+ * Ctrl alike, so the announced shortcuts name both: a hardcoded `Meta+K`
25
+ * would promise a key the row does not keep on non-Apple platforms.
26
+ */
27
+ export declare const searchShortcutKeyshortcuts = "Meta+K Control+K";
28
+ //# sourceMappingURL=platform-modifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-modifier.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/platform-modifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,CAKnE;AAED;2EAC2E;AAC3E,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,qBAAqB,CAAA"}
@@ -0,0 +1,37 @@
1
+ //#region src/components/ui/kbd/platform-modifier.ts
2
+ /**
3
+ * Which modifier a chord should advertise.
4
+ *
5
+ * Every global chord in the product binds `(metaKey || ctrlKey)`, so the
6
+ * working key is the platform's command modifier wherever the app runs — but
7
+ * Apple platforms draw it as ⌘ and everyone else spells it Ctrl. A chord
8
+ * label drawn from anything else (a hardcoded ⌘, say) advertises a key that
9
+ * does not work as drawn on Windows and Linux.
10
+ *
11
+ * These helpers are the one place that decides the glyph, so every surface
12
+ * that draws or announces a shortcut — rail rows, menus, a pane's search
13
+ * field — draws the same one. They sit next to the `Kbd` caps because the
14
+ * glyph is a property of the drawing, not of the feature that shows it: a
15
+ * spelled-out `Ctrl` needs one cap per word (a `KbdGroup`), while `⌘K` can
16
+ * ride `KbdChord`'s one-cap-per-character split.
17
+ */
18
+ /** The modifier glyph the running OS renders for Meta: ⌘ on Apple platforms, Ctrl elsewhere. */
19
+ function platformModifierKey(platform) {
20
+ const browserPlatform = platform ?? (typeof navigator === "undefined" ? "" : navigator.platform);
21
+ return /Mac|iPhone|iPad|iPod/i.test(browserPlatform) ? "⌘" : "Ctrl";
22
+ }
23
+ /** The workspace search chord label as the rail's hover text draws it: the
24
+ * platform modifier plus K (`⌘K`, or `Ctrl+K` where ⌘ does not exist). */
25
+ function searchShortcutLabel(platform) {
26
+ return platformModifierKey(platform) === "⌘" ? "⌘K" : "Ctrl+K";
27
+ }
28
+ /**
29
+ * The `aria-keyshortcuts` for the search chord. The binding accepts Meta and
30
+ * Ctrl alike, so the announced shortcuts name both: a hardcoded `Meta+K`
31
+ * would promise a key the row does not keep on non-Apple platforms.
32
+ */
33
+ var searchShortcutKeyshortcuts = "Meta+K Control+K";
34
+ //#endregion
35
+ export { platformModifierKey, searchShortcutKeyshortcuts, searchShortcutLabel };
36
+
37
+ //# sourceMappingURL=platform-modifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-modifier.js","names":[],"sources":["../../../../src/components/ui/kbd/platform-modifier.ts"],"sourcesContent":["/**\n * Which modifier a chord should advertise.\n *\n * Every global chord in the product binds `(metaKey || ctrlKey)`, so the\n * working key is the platform's command modifier wherever the app runs — but\n * Apple platforms draw it as ⌘ and everyone else spells it Ctrl. A chord\n * label drawn from anything else (a hardcoded ⌘, say) advertises a key that\n * does not work as drawn on Windows and Linux.\n *\n * These helpers are the one place that decides the glyph, so every surface\n * that draws or announces a shortcut — rail rows, menus, a pane's search\n * field — draws the same one. They sit next to the `Kbd` caps because the\n * glyph is a property of the drawing, not of the feature that shows it: a\n * spelled-out `Ctrl` needs one cap per word (a `KbdGroup`), while `⌘K` can\n * ride `KbdChord`'s one-cap-per-character split.\n */\n\n/** The modifier glyph the running OS renders for Meta: ⌘ on Apple platforms, Ctrl elsewhere. */\nexport function platformModifierKey(platform?: string): '⌘' | 'Ctrl' {\n // The guard keeps server renders honest: no navigator means no Apple\n // platform string, so they fall back to the spelled-out modifier.\n const browserPlatform = platform ?? (typeof navigator === 'undefined' ? '' : navigator.platform)\n return /Mac|iPhone|iPad|iPod/i.test(browserPlatform) ? '⌘' : 'Ctrl'\n}\n\n/** The workspace search chord label as the rail's hover text draws it: the\n * platform modifier plus K (`⌘K`, or `Ctrl+K` where ⌘ does not exist). */\nexport function searchShortcutLabel(platform?: string): string {\n return platformModifierKey(platform) === '⌘' ? '⌘K' : 'Ctrl+K'\n}\n\n/**\n * The `aria-keyshortcuts` for the search chord. The binding accepts Meta and\n * Ctrl alike, so the announced shortcuts name both: a hardcoded `Meta+K`\n * would promise a key the row does not keep on non-Apple platforms.\n */\nexport const searchShortcutKeyshortcuts = 'Meta+K Control+K'\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,SAAgB,oBAAoB,UAAiC;CAGnE,MAAM,kBAAkB,aAAa,OAAO,cAAc,cAAc,KAAK,UAAU;CACvF,OAAO,wBAAwB,KAAK,eAAe,IAAI,MAAM;AAC/D;;;AAIA,SAAgB,oBAAoB,UAA2B;CAC7D,OAAO,oBAAoB,QAAQ,MAAM,MAAM,OAAO;AACxD;;;;;;AAOA,IAAa,6BAA6B"}
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import { ValueCombobox } from "./components/ui/combobox/value-combobox.js";
22
22
  import { CodeBlock, InlineCode, TALL_CODE_BLOCK_PX } from "./components/ui/code-block/code-block.js";
23
23
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/ui/tooltip/tooltip.js";
24
24
  import { Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./components/ui/dialog/dialog.js";
25
- import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut } from "./components/ui/command/command.js";
25
+ import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus } from "./components/ui/command/command.js";
26
26
  import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "./components/ui/context-menu/context-menu.js";
27
27
  import { DiffBlock, DiffSummary, diffLineVariants, diffStats, diffTargetPath, parseDiff } from "./components/ui/diff-block/diff-block.js";
28
28
  import { DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection } from "./components/ui/detail-panel/detail-panel.js";
@@ -44,6 +44,7 @@ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGr
44
44
  import { SecretInputGroup } from "./components/ui/input-group/secret-input-group.js";
45
45
  import { InputOtp, InputOtpCaret } from "./components/ui/input-otp/input-otp.js";
46
46
  import { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants } from "./components/ui/kbd/kbd.js";
47
+ import { platformModifierKey, searchShortcutKeyshortcuts, searchShortcutLabel } from "./components/ui/kbd/platform-modifier.js";
47
48
  import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "./components/ui/menubar/menubar.js";
48
49
  import { ModalDialog } from "./components/ui/modal-dialog/modal-dialog.js";
49
50
  import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport } from "./components/ui/navigation-menu/navigation-menu.js";
@@ -93,6 +94,8 @@ import { BusySendButton } from "./components/conversation/busy-send-button.js";
93
94
  import { ChatComposer } from "./components/conversation/chat-composer.js";
94
95
  import { ConversationAvatar } from "./components/conversation/conversation-avatar.js";
95
96
  import { ConversationSurface } from "./components/conversation/conversation-surface.js";
97
+ import { ConversationPane } from "./components/conversation/conversation-pane.js";
98
+ import { ComposerMenu, ComposerMenuItem } from "./components/conversation/composer-menu.js";
96
99
  import { ComposerAttachmentButton, ComposerHint, MessageComposer } from "./components/conversation/message-composer.js";
97
100
  import { MessageBody, MessageDayDivider, MessageGroup, MessageRow } from "./components/conversation/message-row.js";
98
101
  import { TranscriptComposition, transcriptDisclosureKey } from "./components/conversation/transcript-composition.js";
@@ -130,4 +133,4 @@ import { AboutDialog } from "./components/composites/about-dialog/about-dialog.j
130
133
  import { HelpCenter } from "./components/composites/help-center/help-center.js";
131
134
  import { WorkspaceMark } from "./components/composites/workspace-mark/workspace-mark.js";
132
135
  import { writeClipboardText } from "./lib/clipboard.js";
133
- export { APPEARANCE_EDITOR_FONT_AXES, APPEARANCE_EDITOR_FONT_SIZE_MAX, APPEARANCE_EDITOR_FONT_SIZE_MIN, AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnnotationSurface, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearanceEditorActions, AppearanceFontSettingsGroup, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextualSidebar, ConversationAvatar, ConversationSurface, DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdChord, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, PixelResizeHandle, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, TreeRowActions, UpdateChannelControl, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, applyAppearanceFontSettings, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cardVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, fontSettingsBootstrapScript, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, kbdChordKeys, kbdGroupVariants, kbdVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeAppearanceEditorFontSettings, normalizeAppearanceEditorFontSize, normalizeLayout, parseDiff, plainTextFromMarkdown, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, splitPaneBalanced, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
136
+ export { APPEARANCE_EDITOR_FONT_AXES, APPEARANCE_EDITOR_FONT_SIZE_MAX, APPEARANCE_EDITOR_FONT_SIZE_MIN, AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnnotationSurface, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearanceEditorActions, AppearanceFontSettingsGroup, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus, ComposerAttachmentButton, ComposerHint, ComposerMenu, ComposerMenuItem, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextualSidebar, ConversationAvatar, ConversationPane, ConversationSurface, DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdChord, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, PixelResizeHandle, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, TreeRowActions, UpdateChannelControl, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, applyAppearanceFontSettings, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cardVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, fontSettingsBootstrapScript, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, kbdChordKeys, kbdGroupVariants, kbdVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeAppearanceEditorFontSettings, normalizeAppearanceEditorFontSize, normalizeLayout, parseDiff, plainTextFromMarkdown, platformModifierKey, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, searchShortcutKeyshortcuts, searchShortcutLabel, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, splitPaneBalanced, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
@@ -40,11 +40,21 @@
40
40
  "type": "registry:ui",
41
41
  "target": "components/conversation/chat-composer.tsx"
42
42
  },
43
+ {
44
+ "path": "src/components/conversation/composer-menu.tsx",
45
+ "type": "registry:ui",
46
+ "target": "components/conversation/composer-menu.tsx"
47
+ },
43
48
  {
44
49
  "path": "src/components/conversation/conversation-avatar.tsx",
45
50
  "type": "registry:ui",
46
51
  "target": "components/conversation/conversation-avatar.tsx"
47
52
  },
53
+ {
54
+ "path": "src/components/conversation/conversation-pane.tsx",
55
+ "type": "registry:ui",
56
+ "target": "components/conversation/conversation-pane.tsx"
57
+ },
48
58
  {
49
59
  "path": "src/components/conversation/conversation-surface.tsx",
50
60
  "type": "registry:ui",
package/dist/r/kbd.json CHANGED
@@ -17,6 +17,11 @@
17
17
  "path": "src/components/ui/kbd/kbd.tsx",
18
18
  "type": "registry:ui",
19
19
  "target": "components/ui/kbd/kbd.tsx"
20
+ },
21
+ {
22
+ "path": "src/components/ui/kbd/platform-modifier.ts",
23
+ "type": "registry:ui",
24
+ "target": "components/ui/kbd/platform-modifier.ts"
20
25
  }
21
26
  ]
22
27
  }