@k2b/ui 0.28.0 → 0.30.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 (278) hide show
  1. package/README.md +1 -1
  2. package/dist/base.css +2 -2
  3. package/dist/browser/actions/ContextMenu.js +5 -0
  4. package/dist/browser/actions/ContextMenu.js.map +1 -1
  5. package/dist/browser/actions/DragAndDrop.js +89 -0
  6. package/dist/browser/actions/DragAndDrop.js.map +1 -0
  7. package/dist/browser/actions/Dropdown.js +6 -3
  8. package/dist/browser/actions/Dropdown.js.map +1 -1
  9. package/dist/browser/actions/FilterChip.js +137 -7
  10. package/dist/browser/actions/FilterChip.js.map +1 -1
  11. package/dist/browser/actions/GestureMenu.js +26 -3
  12. package/dist/browser/actions/GestureMenu.js.map +1 -1
  13. package/dist/browser/actions/SegmentedControl.js +5 -9
  14. package/dist/browser/actions/SegmentedControl.js.map +1 -1
  15. package/dist/browser/actions/SpotlightSearch.js +6 -3
  16. package/dist/browser/actions/SpotlightSearch.js.map +1 -1
  17. package/dist/browser/actions/Tabs.js +5 -2
  18. package/dist/browser/actions/Tabs.js.map +1 -1
  19. package/dist/browser/actions/ViewTabs.js +294 -0
  20. package/dist/browser/actions/ViewTabs.js.map +1 -0
  21. package/dist/browser/actions/drag-and-drop-messages.js +75 -0
  22. package/dist/browser/actions/drag-and-drop-messages.js.map +1 -0
  23. package/dist/browser/actions/drag-and-drop.js +692 -0
  24. package/dist/browser/actions/drag-and-drop.js.map +1 -0
  25. package/dist/browser/actions/filter-messages.js +6 -2
  26. package/dist/browser/actions/filter-messages.js.map +1 -1
  27. package/dist/browser/actions/index.js +3 -1
  28. package/dist/browser/actions/index.js.map +1 -1
  29. package/dist/browser/chat/ChatComposer.js +1229 -605
  30. package/dist/browser/chat/ChatComposer.js.map +1 -1
  31. package/dist/browser/chat/ChatDecision.js +814 -0
  32. package/dist/browser/chat/ChatDecision.js.map +1 -0
  33. package/dist/browser/chat/ChatPrimitives.js +292 -153
  34. package/dist/browser/chat/ChatPrimitives.js.map +1 -1
  35. package/dist/browser/chat/ChatTimeline.js.map +1 -1
  36. package/dist/browser/chat/chat-messages.js +14 -0
  37. package/dist/browser/chat/chat-messages.js.map +1 -1
  38. package/dist/browser/chat/command-search.js +35 -17
  39. package/dist/browser/chat/command-search.js.map +1 -1
  40. package/dist/browser/chat/index.js +10 -3
  41. package/dist/browser/chat/index.js.map +1 -1
  42. package/dist/browser/chat/types.js.map +1 -1
  43. package/dist/browser/content/Calendar.js +146 -119
  44. package/dist/browser/content/Calendar.js.map +1 -1
  45. package/dist/browser/content/CalendarWeekView.js +291 -266
  46. package/dist/browser/content/CalendarWeekView.js.map +1 -1
  47. package/dist/browser/content/Chart.js +54 -71
  48. package/dist/browser/content/Chart.js.map +1 -1
  49. package/dist/browser/content/DataTable.js +224 -155
  50. package/dist/browser/content/DataTable.js.map +1 -1
  51. package/dist/browser/content/FileBrowser.js +2 -2
  52. package/dist/browser/content/FileBrowser.js.map +1 -1
  53. package/dist/browser/content/FileTree.js +42 -36
  54. package/dist/browser/content/FileTree.js.map +1 -1
  55. package/dist/browser/content/FileTypeIcon.js +72 -0
  56. package/dist/browser/content/FileTypeIcon.js.map +1 -0
  57. package/dist/browser/content/FileView.js +2 -2
  58. package/dist/browser/content/FileView.js.map +1 -1
  59. package/dist/browser/content/ReferenceChip.js +162 -0
  60. package/dist/browser/content/ReferenceChip.js.map +1 -0
  61. package/dist/browser/content/calendar-pointer.js +9 -0
  62. package/dist/browser/content/calendar-pointer.js.map +1 -1
  63. package/dist/browser/content/calendar-time-view.js +6 -3
  64. package/dist/browser/content/calendar-time-view.js.map +1 -1
  65. package/dist/browser/content/data-table-messages.js +4 -2
  66. package/dist/browser/content/data-table-messages.js.map +1 -1
  67. package/dist/browser/content/index.js +2 -0
  68. package/dist/browser/content/index.js.map +1 -1
  69. package/dist/browser/feedback/MovedHint.js +197 -0
  70. package/dist/browser/feedback/MovedHint.js.map +1 -0
  71. package/dist/browser/feedback/dialog-core.js +66 -9
  72. package/dist/browser/feedback/dialog-core.js.map +1 -1
  73. package/dist/browser/feedback/index.js +1 -0
  74. package/dist/browser/feedback/index.js.map +1 -1
  75. package/dist/browser/feedback/prompts.js +6 -1
  76. package/dist/browser/feedback/prompts.js.map +1 -1
  77. package/dist/browser/inputs/DatePicker.js +337 -212
  78. package/dist/browser/inputs/DatePicker.js.map +1 -1
  79. package/dist/browser/inputs/date-picker.js +59 -5
  80. package/dist/browser/inputs/date-picker.js.map +1 -1
  81. package/dist/browser/intl/messages.js +12 -0
  82. package/dist/browser/intl/messages.js.map +1 -1
  83. package/dist/browser/intl/weekend.js +39 -0
  84. package/dist/browser/intl/weekend.js.map +1 -0
  85. package/dist/browser/layout/AppOverview.js +1 -2
  86. package/dist/browser/layout/AppOverview.js.map +1 -1
  87. package/dist/browser/layout/AppWorkspace.js +947 -531
  88. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  89. package/dist/browser/layout/PageTitle.js +3 -2
  90. package/dist/browser/layout/PageTitle.js.map +1 -1
  91. package/dist/browser/layout/PanelDialog.js +88 -86
  92. package/dist/browser/layout/PanelDialog.js.map +1 -1
  93. package/dist/browser/layout/ResizeSeparator.js +81 -0
  94. package/dist/browser/layout/ResizeSeparator.js.map +1 -0
  95. package/dist/browser/layout/SettingsModal.js +2 -2
  96. package/dist/browser/layout/SettingsModal.js.map +1 -1
  97. package/dist/browser/layout/SidebarSwitcher.js +19 -11
  98. package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
  99. package/dist/browser/layout/TabBar.js +16 -13
  100. package/dist/browser/layout/TabBar.js.map +1 -1
  101. package/dist/browser/layout/app-host-width.js +44 -0
  102. package/dist/browser/layout/app-host-width.js.map +1 -0
  103. package/dist/browser/layout/app-workspace-controller.js +337 -44
  104. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  105. package/dist/browser/layout/index.js +4 -1
  106. package/dist/browser/layout/index.js.map +1 -1
  107. package/dist/browser/layout/resize-separator.js +90 -0
  108. package/dist/browser/layout/resize-separator.js.map +1 -0
  109. package/dist/browser/layout/workspace-messages.js +12 -2
  110. package/dist/browser/layout/workspace-messages.js.map +1 -1
  111. package/dist/browser/surfaces/LinkCard.js +1 -1
  112. package/dist/browser/surfaces/LinkCard.js.map +1 -1
  113. package/dist/browser/surfaces/Placeholder.js +45 -11
  114. package/dist/browser/surfaces/Placeholder.js.map +1 -1
  115. package/dist/browser/surfaces/StatCell.js +23 -0
  116. package/dist/browser/surfaces/StatCell.js.map +1 -1
  117. package/dist/browser/widgets/Widget.js +1 -1
  118. package/dist/browser/widgets/Widget.js.map +1 -1
  119. package/dist/ssr/actions/ContextMenu.js +5 -0
  120. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  121. package/dist/ssr/actions/DragAndDrop.js +63 -0
  122. package/dist/ssr/actions/DragAndDrop.js.map +1 -0
  123. package/dist/ssr/actions/Dropdown.js +5 -2
  124. package/dist/ssr/actions/Dropdown.js.map +1 -1
  125. package/dist/ssr/actions/FilterChip.js +59 -7
  126. package/dist/ssr/actions/FilterChip.js.map +1 -1
  127. package/dist/ssr/actions/GestureMenu.js +26 -3
  128. package/dist/ssr/actions/GestureMenu.js.map +1 -1
  129. package/dist/ssr/actions/SegmentedControl.js +1 -2
  130. package/dist/ssr/actions/SegmentedControl.js.map +1 -1
  131. package/dist/ssr/actions/SpotlightSearch.js +2 -2
  132. package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
  133. package/dist/ssr/actions/Tabs.js +2 -2
  134. package/dist/ssr/actions/Tabs.js.map +1 -1
  135. package/dist/ssr/actions/ViewTabs.js +211 -0
  136. package/dist/ssr/actions/ViewTabs.js.map +1 -0
  137. package/dist/ssr/actions/drag-and-drop-messages.js +75 -0
  138. package/dist/ssr/actions/drag-and-drop-messages.js.map +1 -0
  139. package/dist/ssr/actions/drag-and-drop.js +692 -0
  140. package/dist/ssr/actions/drag-and-drop.js.map +1 -0
  141. package/dist/ssr/actions/filter-messages.js +6 -2
  142. package/dist/ssr/actions/filter-messages.js.map +1 -1
  143. package/dist/ssr/actions/index.js +3 -1
  144. package/dist/ssr/actions/index.js.map +1 -1
  145. package/dist/ssr/chat/ChatComposer.js +668 -136
  146. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  147. package/dist/ssr/chat/ChatDecision.js +479 -0
  148. package/dist/ssr/chat/ChatDecision.js.map +1 -0
  149. package/dist/ssr/chat/ChatPrimitives.js +95 -24
  150. package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
  151. package/dist/ssr/chat/ChatTimeline.js.map +1 -1
  152. package/dist/ssr/chat/chat-messages.js +14 -0
  153. package/dist/ssr/chat/chat-messages.js.map +1 -1
  154. package/dist/ssr/chat/command-search.js +35 -17
  155. package/dist/ssr/chat/command-search.js.map +1 -1
  156. package/dist/ssr/chat/index.js +10 -3
  157. package/dist/ssr/chat/index.js.map +1 -1
  158. package/dist/ssr/chat/types.js.map +1 -1
  159. package/dist/ssr/content/Calendar.js +112 -103
  160. package/dist/ssr/content/Calendar.js.map +1 -1
  161. package/dist/ssr/content/CalendarWeekView.js +42 -28
  162. package/dist/ssr/content/CalendarWeekView.js.map +1 -1
  163. package/dist/ssr/content/Chart.js +19 -23
  164. package/dist/ssr/content/Chart.js.map +1 -1
  165. package/dist/ssr/content/DataTable.js +78 -31
  166. package/dist/ssr/content/DataTable.js.map +1 -1
  167. package/dist/ssr/content/FileBrowser.js +2 -2
  168. package/dist/ssr/content/FileBrowser.js.map +1 -1
  169. package/dist/ssr/content/FileTree.js +21 -14
  170. package/dist/ssr/content/FileTree.js.map +1 -1
  171. package/dist/ssr/content/FileTypeIcon.js +50 -0
  172. package/dist/ssr/content/FileTypeIcon.js.map +1 -0
  173. package/dist/ssr/content/FileView.js +2 -2
  174. package/dist/ssr/content/FileView.js.map +1 -1
  175. package/dist/ssr/content/ReferenceChip.js +121 -0
  176. package/dist/ssr/content/ReferenceChip.js.map +1 -0
  177. package/dist/ssr/content/calendar-pointer.js +9 -0
  178. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  179. package/dist/ssr/content/calendar-time-view.js +6 -3
  180. package/dist/ssr/content/calendar-time-view.js.map +1 -1
  181. package/dist/ssr/content/data-table-messages.js +4 -2
  182. package/dist/ssr/content/data-table-messages.js.map +1 -1
  183. package/dist/ssr/content/index.js +2 -0
  184. package/dist/ssr/content/index.js.map +1 -1
  185. package/dist/ssr/feedback/MovedHint.js +166 -0
  186. package/dist/ssr/feedback/MovedHint.js.map +1 -0
  187. package/dist/ssr/feedback/dialog-core.js +66 -9
  188. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  189. package/dist/ssr/feedback/index.js +1 -0
  190. package/dist/ssr/feedback/index.js.map +1 -1
  191. package/dist/ssr/feedback/prompts.js +6 -1
  192. package/dist/ssr/feedback/prompts.js.map +1 -1
  193. package/dist/ssr/inputs/DatePicker.js +138 -69
  194. package/dist/ssr/inputs/DatePicker.js.map +1 -1
  195. package/dist/ssr/inputs/date-picker.js +59 -5
  196. package/dist/ssr/inputs/date-picker.js.map +1 -1
  197. package/dist/ssr/intl/messages.js +12 -0
  198. package/dist/ssr/intl/messages.js.map +1 -1
  199. package/dist/ssr/intl/weekend.js +39 -0
  200. package/dist/ssr/intl/weekend.js.map +1 -0
  201. package/dist/ssr/layout/AppOverview.js +1 -2
  202. package/dist/ssr/layout/AppOverview.js.map +1 -1
  203. package/dist/ssr/layout/AppWorkspace.js +457 -116
  204. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  205. package/dist/ssr/layout/PageTitle.js +3 -2
  206. package/dist/ssr/layout/PageTitle.js.map +1 -1
  207. package/dist/ssr/layout/PanelDialog.js +7 -6
  208. package/dist/ssr/layout/PanelDialog.js.map +1 -1
  209. package/dist/ssr/layout/ResizeSeparator.js +45 -0
  210. package/dist/ssr/layout/ResizeSeparator.js.map +1 -0
  211. package/dist/ssr/layout/SettingsModal.js +2 -2
  212. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  213. package/dist/ssr/layout/SidebarSwitcher.js +19 -11
  214. package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
  215. package/dist/ssr/layout/TabBar.js +2 -2
  216. package/dist/ssr/layout/TabBar.js.map +1 -1
  217. package/dist/ssr/layout/app-host-width.js +44 -0
  218. package/dist/ssr/layout/app-host-width.js.map +1 -0
  219. package/dist/ssr/layout/app-workspace-controller.js +337 -44
  220. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  221. package/dist/ssr/layout/index.js +4 -1
  222. package/dist/ssr/layout/index.js.map +1 -1
  223. package/dist/ssr/layout/resize-separator.js +90 -0
  224. package/dist/ssr/layout/resize-separator.js.map +1 -0
  225. package/dist/ssr/layout/workspace-messages.js +12 -2
  226. package/dist/ssr/layout/workspace-messages.js.map +1 -1
  227. package/dist/ssr/surfaces/LinkCard.js +1 -1
  228. package/dist/ssr/surfaces/LinkCard.js.map +1 -1
  229. package/dist/ssr/surfaces/Placeholder.js +25 -6
  230. package/dist/ssr/surfaces/Placeholder.js.map +1 -1
  231. package/dist/ssr/surfaces/StatCell.js +23 -0
  232. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  233. package/dist/ssr/widgets/Widget.js +1 -1
  234. package/dist/ssr/widgets/Widget.js.map +1 -1
  235. package/dist/styles.css +1 -1
  236. package/dist/types/actions/ContextMenu.d.ts +1 -0
  237. package/dist/types/actions/DragAndDrop.d.ts +29 -0
  238. package/dist/types/actions/Dropdown.d.ts +4 -0
  239. package/dist/types/actions/FilterChip.d.ts +22 -0
  240. package/dist/types/actions/ViewTabs.d.ts +30 -0
  241. package/dist/types/actions/drag-and-drop-messages.d.ts +35 -0
  242. package/dist/types/actions/drag-and-drop.d.ts +36 -0
  243. package/dist/types/actions/filter-messages.d.ts +2 -0
  244. package/dist/types/actions/index.d.ts +6 -2
  245. package/dist/types/chat/ChatComposer.d.ts +71 -1
  246. package/dist/types/chat/ChatDecision.d.ts +149 -0
  247. package/dist/types/chat/ChatPrimitives.d.ts +14 -1
  248. package/dist/types/chat/ChatTimeline.d.ts +2 -1
  249. package/dist/types/chat/chat-messages.d.ts +7 -0
  250. package/dist/types/chat/command-search.d.ts +5 -0
  251. package/dist/types/chat/index.d.ts +28 -5
  252. package/dist/types/chat/types.d.ts +54 -1
  253. package/dist/types/content/Chart.d.ts +9 -3
  254. package/dist/types/content/DataTable.d.ts +3 -0
  255. package/dist/types/content/FileTypeIcon.d.ts +27 -0
  256. package/dist/types/content/ReferenceChip.d.ts +49 -0
  257. package/dist/types/content/calendar-pointer.d.ts +6 -0
  258. package/dist/types/content/data-table-messages.d.ts +1 -0
  259. package/dist/types/content/index.d.ts +3 -0
  260. package/dist/types/feedback/MovedHint.d.ts +25 -0
  261. package/dist/types/feedback/dialog-core.d.ts +5 -2
  262. package/dist/types/feedback/index.d.ts +2 -0
  263. package/dist/types/feedback/prompts.d.ts +2 -0
  264. package/dist/types/inputs/DatePicker.d.ts +7 -0
  265. package/dist/types/inputs/date-picker.d.ts +25 -1
  266. package/dist/types/intl/messages.d.ts +6 -0
  267. package/dist/types/intl/weekend.d.ts +12 -0
  268. package/dist/types/layout/AppWorkspace.d.ts +48 -10
  269. package/dist/types/layout/ResizeSeparator.d.ts +9 -0
  270. package/dist/types/layout/TabBar.d.ts +7 -0
  271. package/dist/types/layout/app-host-width.d.ts +6 -0
  272. package/dist/types/layout/app-workspace-controller.d.ts +2 -0
  273. package/dist/types/layout/index.d.ts +5 -2
  274. package/dist/types/layout/resize-separator.d.ts +18 -0
  275. package/dist/types/layout/workspace-messages.d.ts +5 -0
  276. package/dist/types/surfaces/Placeholder.d.ts +2 -1
  277. package/dist/types/surfaces/StatCell.d.ts +6 -0
  278. package/package.json +5 -5
@@ -25,41 +25,43 @@ var _tmpl$ = /*#__PURE__*/_$template(`<span><strong>`),
25
25
  _tmpl$0 = /*#__PURE__*/_$template(`<textarea class=k2b-chat-composer__measure rows=1 tabindex=-1 aria-hidden=true readonly>`),
26
26
  _tmpl$1 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__input role=group><!$><!/><textarea rows=1></textarea><!$><!/>`),
27
27
  _tmpl$10 = /*#__PURE__*/_$template(`<span>`),
28
- _tmpl$11 = /*#__PURE__*/_$template(`<small>`),
28
+ _tmpl$11 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__command-detail><small></small><small><i class="ti ti-loader-2 k2b-spin"aria-hidden=true></i><!$><!/>`),
29
29
  _tmpl$12 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__command-end><i class="ti ti-check"aria-hidden=true></i><span class=k2b-sr-only>`),
30
30
  _tmpl$13 = /*#__PURE__*/_$template(`<button class=k2b-chat-composer__command type=button role=option tabindex=-1><i aria-hidden=true></i><span class=k2b-chat-composer__command-text><strong></strong><!$><!/></span><!$><!/>`),
31
31
  _tmpl$14 = /*#__PURE__*/_$template(`<b>`),
32
- _tmpl$15 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-accessory><div class=k2b-chat-composer__commands role=listbox>`),
33
- _tmpl$16 = /*#__PURE__*/_$template(`<div role=status class=k2b-chat-composer__loading><i class="ti ti-loader-2 k2b-spin"aria-hidden=true></i><strong>`),
34
- _tmpl$17 = /*#__PURE__*/_$template(`<div role=status><i class="ti ti-alert-circle"></i> <!$><!/>`),
35
- _tmpl$18 = /*#__PURE__*/_$template(`<div role=status>`),
36
- _tmpl$19 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-accessory data-commands><div class=k2b-chat-composer__commands role=listbox><!$><!/><!$><!/><!$><!/><!$><!/>`),
37
- _tmpl$20 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-slot><div></div><!$><!/><!$><!/>`),
38
- _tmpl$21 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__hint aria-live=polite>`),
39
- _tmpl$22 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachments role=list tabindex=0>`),
40
- _tmpl$23 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__error role=alert><i class="ti ti-alert-circle"aria-hidden=true></i><!$><!/>`),
41
- _tmpl$24 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__row><!$><!/><!$><!/><div class=k2b-chat-composer__field><!$><!/><div class=k2b-chat-composer__field-tools><!$><!/><!$><!/><!$><!/></div></div><!$><!/>`),
42
- _tmpl$25 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-shell><!$><!/><section role=group><!$><!/><!$><!/><!$><!/><!$><!/></section><div class=k2b-sr-only role=status aria-live=polite></div><div class=k2b-chat-composer__status role=status><!$><!/><!$><!/>`),
43
- _tmpl$26 = /*#__PURE__*/_$template(`<button type=button role=option tabindex=-1><span class=k2b-chat-composer__emoji-glyph aria-hidden=true></span><strong></strong><!$><!/>`),
44
- _tmpl$27 = /*#__PURE__*/_$template(`<small>:<!$><!/>:`),
45
- _tmpl$28 = /*#__PURE__*/_$template(`<i class="ti ti-loader-2 k2b-spin"aria-hidden=true>`),
46
- _tmpl$29 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__command-placeholder aria-hidden=true><span></span><span><span></span><span>`),
47
- _tmpl$30 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__command-group role=group><div class=k2b-chat-composer__command-heading role=presentation><span></span><!$><!/></div><!$><!/><!$><!/>`),
48
- _tmpl$31 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__hint-text>`),
49
- _tmpl$32 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__dictation><i aria-hidden=true></i><span>`),
50
- _tmpl$33 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__hint-action>`),
51
- _tmpl$34 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__attachment-remove><i class="ti ti-x"aria-hidden=true>`),
52
- _tmpl$35 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachment role=listitem><div class=k2b-chat-composer__attachment-content><!$><!/><!$><!/></div><!$><!/>`),
53
- _tmpl$36 = /*#__PURE__*/_$template(`<img>`),
54
- _tmpl$37 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachment-identity><!$><!/><!$><!/>`),
55
- _tmpl$38 = /*#__PURE__*/_$template(`<a class=k2b-chat-composer__attachment-link target=_blank rel="noopener noreferrer"><!$><!/><!$><!/>`),
56
- _tmpl$39 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__attachment-action><!$><!/><!$><!/>`),
57
- _tmpl$40 = /*#__PURE__*/_$template(`<footer class=k2b-chat-composer__footer>`),
58
- _tmpl$41 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__tools><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
59
- _tmpl$42 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__submit><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
60
- _tmpl$43 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__status-line><i aria-hidden=true></i><span>`),
61
- _tmpl$44 = /*#__PURE__*/_$template(`<span class=k2b-sr-only>`);
62
- import { batch, children, createEffect, createMemo, createSignal, createUniqueId, For, onCleanup, onMount, Show, untrack } from "solid-js";
32
+ _tmpl$15 = /*#__PURE__*/_$template(`<small>`),
33
+ _tmpl$16 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-accessory><div class=k2b-chat-composer__commands role=listbox>`),
34
+ _tmpl$17 = /*#__PURE__*/_$template(`<label class=k2b-chat-composer__command-search><i class="ti ti-search"aria-hidden=true></i><input type=text role=combobox aria-autocomplete=list aria-expanded=true autocomplete=off autocapitalize=off>`),
35
+ _tmpl$18 = /*#__PURE__*/_$template(`<div role=status class=k2b-chat-composer__loading><i class="ti ti-loader-2 k2b-spin"aria-hidden=true></i><strong>`),
36
+ _tmpl$19 = /*#__PURE__*/_$template(`<div role=status><i class="ti ti-alert-circle"></i> <!$><!/>`),
37
+ _tmpl$20 = /*#__PURE__*/_$template(`<div role=status>`),
38
+ _tmpl$21 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-accessory data-commands><!$><!/><div class=k2b-chat-composer__commands role=listbox><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
39
+ _tmpl$22 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-slot><div></div><!$><!/><!$><!/>`),
40
+ _tmpl$23 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__hint aria-live=polite>`),
41
+ _tmpl$24 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachments role=list tabindex=0>`),
42
+ _tmpl$25 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__error role=alert><i class="ti ti-alert-circle"aria-hidden=true></i><!$><!/>`),
43
+ _tmpl$26 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__row><!$><!/><!$><!/><div class=k2b-chat-composer__field><!$><!/><div class=k2b-chat-composer__field-tools><!$><!/><!$><!/><!$><!/></div></div><!$><!/>`),
44
+ _tmpl$27 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer-shell><!$><!/><section role=group><!$><!/><!$><!/><!$><!/><!$><!/></section><div class=k2b-sr-only role=status aria-live=polite></div><div class=k2b-chat-composer__status role=status><!$><!/><!$><!/>`),
45
+ _tmpl$28 = /*#__PURE__*/_$template(`<button type=button role=option tabindex=-1><span class=k2b-chat-composer__emoji-glyph aria-hidden=true></span><strong></strong><!$><!/>`),
46
+ _tmpl$29 = /*#__PURE__*/_$template(`<small>:<!$><!/>:`),
47
+ _tmpl$30 = /*#__PURE__*/_$template(`<i class="ti ti-loader-2 k2b-spin"aria-hidden=true>`),
48
+ _tmpl$31 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__command-group role=group><div class=k2b-chat-composer__command-heading role=presentation><span></span><!$><!/></div><!$><!/><!$><!/>`),
49
+ _tmpl$32 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__command-placeholder aria-hidden=true><span></span><span><span></span><span>`),
50
+ _tmpl$33 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__hint-text>`),
51
+ _tmpl$34 = /*#__PURE__*/_$template(`<span class=k2b-chat-composer__dictation><i aria-hidden=true></i><span>`),
52
+ _tmpl$35 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__hint-action>`),
53
+ _tmpl$36 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__attachment-remove><i class="ti ti-x"aria-hidden=true>`),
54
+ _tmpl$37 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachment role=listitem><div class=k2b-chat-composer__attachment-content><!$><!/><!$><!/></div><!$><!/>`),
55
+ _tmpl$38 = /*#__PURE__*/_$template(`<img>`),
56
+ _tmpl$39 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__attachment-identity><!$><!/><!$><!/>`),
57
+ _tmpl$40 = /*#__PURE__*/_$template(`<a class=k2b-chat-composer__attachment-link target=_blank rel="noopener noreferrer"><!$><!/><!$><!/>`),
58
+ _tmpl$41 = /*#__PURE__*/_$template(`<button type=button class=k2b-chat-composer__attachment-action><!$><!/><!$><!/>`),
59
+ _tmpl$42 = /*#__PURE__*/_$template(`<footer class=k2b-chat-composer__footer>`),
60
+ _tmpl$43 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__tools><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
61
+ _tmpl$44 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__submit><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`),
62
+ _tmpl$45 = /*#__PURE__*/_$template(`<div class=k2b-chat-composer__status-line><i aria-hidden=true></i><span>`),
63
+ _tmpl$46 = /*#__PURE__*/_$template(`<span class=k2b-sr-only>`);
64
+ import { batch, children, createEffect, createMemo, createSignal, createUniqueId, For, Index, on, onCleanup, onMount, Show, untrack } from "solid-js";
63
65
  import { Dropdown } from "../actions/Dropdown";
64
66
  import { dialogHistorySettled, holdDialogHistory } from "../feedback/dialog-core";
65
67
  import { Tooltip } from "../feedback/Tooltip";
@@ -85,7 +87,17 @@ const emojiSuggestionLimit = 8;
85
87
  // Keep editor undo text within approximately 2 MiB, plus the current edit.
86
88
  const composerUndoBudgetChars = 1_000_000;
87
89
 
88
- /** An action can cancel and restore its token, or report a short completion message. */
90
+ /**
91
+ * An action can cancel and restore its token, report a short completion message, or hand back a reference chosen in a
92
+ * dialog: `mention` takes the token's place exactly as a `mention` row does, and Ctrl/⌘+Z brings the token back.
93
+ */
94
+
95
+ /** The draft as a successful `open` leaves it: without the `/…` token, with its references moved along. Save this one. */
96
+
97
+ /**
98
+ * How an `open` row ends: on success (`void`) the token leaves as for an action; `"cancelled"` changes nothing; `failed`
99
+ * keeps the list open and the draft unchanged, and its text replaces the row's description until the row runs again.
100
+ */
89
101
 
90
102
  /** A fixed place in the slash list. Sections keep the given order, also while searching. */
91
103
 
@@ -175,6 +187,17 @@ export function ChatComposer(props) {
175
187
  return `${commandListId}-c${commandIds.get(key)}`;
176
188
  };
177
189
  const [closedAt, setClosedAt] = createSignal();
190
+ /** The list opened from "+": the field's selection when "+" was pressed, and the search field's text. */
191
+ const [addSearch, setAddSearch] = createSignal();
192
+ const [addQuery, setAddQuery] = createSignal("");
193
+ let addSearchRef;
194
+ let addButtonRef;
195
+ let addComposing = false;
196
+ /** The `open` row running now, and why `open` rows failed in this opening, by row key. */
197
+ const [openingRow, setOpeningRow] = createSignal();
198
+ const [openFailures, setOpenFailures] = createSignal({});
199
+ /** Cancels the `open` row running now; `key` follows announced draft moves, `label` is its busy line. */
200
+ let openingRun;
178
201
  // Where the pending native edit starts; a selection replaced as a whole starts at its beginning.
179
202
  let inputStart;
180
203
  let inputEnd;
@@ -279,7 +302,17 @@ export function ChatComposer(props) {
279
302
  return token && index ? suggestEmoji(index, token.query, emojiSuggestionLimit) : [];
280
303
  });
281
304
  const emojiOpen = () => emojiMatches().length > 0;
282
- const caretCommandToken = createMemo(() => chatCommandQuery(props.value, caret(), selectionEnd()));
305
+ // From "+", the search field's text is the query of an empty token at the field's stored caret.
306
+ const caretCommandToken = createMemo(() => {
307
+ const search = addSearch();
308
+ if (!search) return chatCommandQuery(props.value, caret(), selectionEnd());
309
+ const at = Math.min(search.end, props.value.length);
310
+ return {
311
+ start: at,
312
+ end: at,
313
+ query: addQuery()
314
+ };
315
+ });
283
316
  const caretCommandStart = createMemo(() => caretCommandToken()?.start);
284
317
  // Retained server rows belong to one `/`: they go when it does or when another `/` starts.
285
318
  createEffect(() => {
@@ -294,6 +327,7 @@ export function ChatComposer(props) {
294
327
  });
295
328
  const commandQuery = createMemo(() => {
296
329
  const token = caretCommandToken();
330
+ if (addSearch()) return token;
297
331
  return dismissed() || composing() || token?.start === closedAt() ? null : token;
298
332
  });
299
333
  const openingStart = createMemo(() => commandQuery()?.start);
@@ -302,14 +336,44 @@ export function ChatComposer(props) {
302
336
  const start = openingStart();
303
337
  if (start !== undefined) setCommandOpening(opening => opening + 1);
304
338
  });
339
+ // A failed `open` row says so for the rest of its list opening.
340
+ createEffect(() => {
341
+ props.draftKey;
342
+ commandOpening();
343
+ setOpenFailures({});
344
+ });
305
345
  const parsedCommandQuery = createMemo(() => parseChatCommandQuery(commandQuery()?.query ?? "", props.commandScopes ?? []));
346
+ const commandFallbackRow = createMemo(() => {
347
+ const parsed = parsedCommandQuery();
348
+ const query = parsed.query.trim();
349
+ return commandQuery() && (query || parsed.scope) ? props.commandFallback?.({
350
+ query,
351
+ scope: parsed.scope?.id
352
+ }) : undefined;
353
+ });
306
354
  const currentCommandScope = createMemo(() => parsedCommandQuery().scope?.id);
307
355
  createEffect(() => {
308
356
  currentCommandScope();
309
357
  setSearchResults([]);
310
358
  setSearchResultsQuery(undefined);
311
359
  });
312
- const localCommands = createMemo(() => props.commands ?? []);
360
+ // Rows of a `fixedWhileOpen` section are the ones it had when this `/` opened the list; later ones wait for the next
361
+ // `/`. A retry row starts another opening in the same open list, so it does not count.
362
+ const fixedCommandKeys = createMemo(() => {
363
+ props.draftKey;
364
+ if (openingStart() === undefined) return undefined;
365
+ return untrack(() => {
366
+ const fixed = new Set((props.commandSections ?? []).filter(section => section.fixedWhileOpen).map(section => section.id));
367
+ return fixed.size ? new Set((props.commands ?? []).filter(command => fixed.has(command.section ?? "")).map(chatCommandKey)) : undefined;
368
+ });
369
+ });
370
+ const localCommands = createMemo(() => {
371
+ const commands = props.commands ?? [];
372
+ const keys = fixedCommandKeys();
373
+ if (!keys) return commands;
374
+ const fixed = new Set((props.commandSections ?? []).filter(section => section.fixedWhileOpen).map(section => section.id));
375
+ return commands.filter(command => !fixed.has(command.section ?? "") || keys.has(chatCommandKey(command)));
376
+ });
313
377
  const commandModel = createMemo(() => chatCommandListModel({
314
378
  query: commandQuery()?.query ?? "",
315
379
  scopes: props.commandScopes,
@@ -318,9 +382,12 @@ export function ChatComposer(props) {
318
382
  searchResults: searchResultsScope() === parsedCommandQuery().scope?.id ? searchResults() : [],
319
383
  searchResultsFresh: searchResultsQuery() === commandQuery()?.query && searchResultsScope() === parsedCommandQuery().scope?.id,
320
384
  searchSettled: searchResultsQuery() !== undefined && searchResultsScope() === parsedCommandQuery().scope?.id,
321
- searching: searching()
385
+ searching: searching(),
386
+ fallback: commandFallbackRow()
322
387
  }));
323
388
  const commandMatches = createMemo(() => commandQuery() ? commandModel().rows.map(row => row.command) : []);
389
+ /** Rows that matched; an unscoped fallback row only follows them. */
390
+ const foundCommandCount = () => commandMatches().length - (commandModel().fallback ? 1 : 0);
324
391
  const currentCommandQuery = createMemo(() => caretCommandToken()?.query);
325
392
  // Arrow marking belongs to one token in one draft; another draft or `/` starts at the top row again.
326
393
  createEffect(() => {
@@ -329,13 +396,87 @@ export function ChatComposer(props) {
329
396
  currentCommandQuery();
330
397
  setCommandMoved(false);
331
398
  });
332
- const commandsOpen = () => Boolean(!emojiOpen() && commandQuery() && (localCommands().length || props.searchCommands));
333
- const commandSheetHeld = createMemo(() => commandsOpen() && isTouchOnly());
399
+ const commandsOpen = () => Boolean(!emojiOpen() && commandQuery() && (localCommands().length || props.searchCommands || commandFallbackRow()));
400
+ // Rows that arrive for a pending section never move a visible row of the overview: until the person types, the list
401
+ // keeps the height it had with its placeholders and scrolls what does not fit. A list below its maximum height grows
402
+ // upward from the field, so a change of height alone would move its first row. While searching, the rows arrive
403
+ // with the search's own answer, which changes the list anyway.
404
+ // From "+", the whole panel keeps the height it opened with instead.
405
+ const commandsPending = createMemo(() => commandsOpen() && !addSearch() && !parsedCommandQuery().scope && !parsedCommandQuery().query.trim() && commandModel().groups.some(group => group.pendingRows > 0));
406
+ // Typing, another opening or closing the list lets it size itself again.
407
+ const commandListSizeKey = createMemo(() => commandsOpen() ? `${commandOpening()}\u0000${caretCommandToken()?.query}` : undefined);
408
+ // The list's height with its placeholders, for the size key it was measured under.
409
+ let pendingList;
410
+ createEffect(() => {
411
+ const list = commandListRef;
412
+ if (!commandsPending() || !list || typeof ResizeObserver === "undefined") return;
413
+ const measure = () => {
414
+ pendingList = {
415
+ height: list.getBoundingClientRect().height,
416
+ key: untrack(commandListSizeKey)
417
+ };
418
+ };
419
+ measure();
420
+ const observer = new ResizeObserver(measure);
421
+ observer.observe(list);
422
+ onCleanup(() => observer.disconnect());
423
+ });
424
+ createEffect(on(commandsPending, (pending, wasPending) => {
425
+ const held = pendingList;
426
+ pendingList = undefined;
427
+ // Only rows arriving hold the list; the person's typing or closing it does not.
428
+ if (pending || !wasPending || !held || held.key !== commandListSizeKey() || !commandListRef?.isConnected) return;
429
+ commandListRef.style.height = `${held.height}px`;
430
+ commandListRef.setAttribute("data-held", "");
431
+ }));
432
+ createEffect(on(commandListSizeKey, () => {
433
+ commandListRef?.style.removeProperty("height");
434
+ commandListRef?.removeAttribute("data-held");
435
+ }, {
436
+ defer: true
437
+ }));
438
+ // Escape, a press outside, or moving the caret away closes the list; while an `open` row runs, that cancels it, so
439
+ // nothing opens after the person backed out. Success ends the opening and closes the list in one step. A new draft
440
+ // cancels too, unless the opener announced that next move with `follow()`: its busy line moves to the status line,
441
+ // and Escape still cancels there. Any later unannounced draft change cancels.
442
+ createEffect(() => {
443
+ const draftKey = props.draftKey;
444
+ const open = commandsOpen();
445
+ const row = openingRow();
446
+ const run = openingRun;
447
+ if (!run || row === undefined) return;
448
+ if (draftKey !== run.key) {
449
+ if (run.follow) {
450
+ run.follow = false;
451
+ run.key = draftKey;
452
+ run.moved = true;
453
+ showCommandStatus({
454
+ tone: "busy",
455
+ text: run.label
456
+ });
457
+ } else run.controller.abort();
458
+ return;
459
+ }
460
+ if (!open && !run.moved) run.controller.abort();
461
+ });
462
+ onCleanup(() => openingRun?.controller.abort());
463
+ // An `open` row gives the sheet's Back entry up first, so it never races the navigation it starts.
464
+ const commandSheetHeld = createMemo(() => commandsOpen() && isTouchOnly() && openingRow() === undefined);
334
465
  createEffect(() => {
335
466
  if (!commandSheetHeld()) return;
336
- onCleanup(holdDialogHistory(() => setClosedAt(commandQuery()?.start)));
467
+ onCleanup(holdDialogHistory(() => closeCommandList()));
337
468
  });
338
469
  const suggestionsOpen = () => commandsOpen() || emojiOpen();
470
+ const fieldOwnsList = () => suggestionsOpen() && !addSearch();
471
+ // From "+", the panel keeps the height it opened with while the person types or rows arrive, so neither the search
472
+ // field nor the first row moves; what does not fit scrolls. The space above the field still bounds it.
473
+ const addPanelOpen = createMemo(() => addSearch() !== undefined && commandsOpen());
474
+ createEffect(() => {
475
+ const accessory = addPanelOpen() ? commandListRef?.parentElement : undefined;
476
+ if (!accessory) return;
477
+ const frame = requestAnimationFrame(() => accessory.style.setProperty("--k2b-chat-command-held", `${accessory.getBoundingClientRect().height}px`));
478
+ onCleanup(() => cancelAnimationFrame(frame));
479
+ });
339
480
  createEffect(() => {
340
481
  if (!suggestionsOpen()) return;
341
482
  let disposed = false;
@@ -363,10 +504,13 @@ export function ChatComposer(props) {
363
504
  const left = Math.max(0, column?.left ?? 0);
364
505
  const right = Math.min(page, column?.right ?? page);
365
506
  const slot = accessory.parentElement.getBoundingClientRect();
366
- const bottom = accessory.getBoundingClientRect().bottom;
367
- commandListRef.style.setProperty("--k2b-chat-command-space", `${Math.max(40, bottom - top - 8)}px`);
507
+ // From its place in the slot, not its box: the sheet opened from "+" rises into place, and a box measured during
508
+ // that animation would include its offset.
509
+ const bottom = slot.bottom - (Number.parseFloat(window.getComputedStyle(accessory).bottom) || 0);
510
+ // On the accessory, so a panel opened from "+" is bounded as a whole, with its search field.
511
+ accessory.style.setProperty("--k2b-chat-command-space", `${Math.max(40, bottom - top - 8)}px`);
368
512
  // Only a list that reaches the screen's top edge keeps clear of a notch or the status bar.
369
- commandListRef.style.setProperty("--k2b-chat-command-safe-top", top === viewportTop ? "env(safe-area-inset-top, 0px)" : "0px");
513
+ accessory.style.setProperty("--k2b-chat-command-safe-top", top === viewportTop ? "env(safe-area-inset-top, 0px)" : "0px");
370
514
  accessory.style.setProperty("--k2b-chat-command-reach-left", `${Math.max(0, slot.left - left)}px`);
371
515
  accessory.style.setProperty("--k2b-chat-command-reach-right", `${Math.max(0, right - slot.right)}px`);
372
516
  };
@@ -384,11 +528,29 @@ export function ChatComposer(props) {
384
528
  // A press outside the command list and the field closes the list, as Escape does; the text stays. With a mouse or a
385
529
  // trackpad the press then acts as usual. On a touch-only device a tap outside the composer closes only the list: it
386
530
  // reaches nothing beneath, and the field keeps focus, so the keyboard stays open.
531
+ // A list opened from "+" is a menu: any press outside it closes only the list, with every pointer, and the field gets
532
+ // its focus back. "+" itself toggles with its click; a press in the field closes the list and lands there as usual.
387
533
  createEffect(() => {
388
534
  if (!commandsOpen()) return;
389
535
  const onPointerDown = event => {
390
536
  const target = event.target;
391
- if (!(target instanceof Node) || commandListRef?.contains(target) || textareaRef?.parentElement?.contains(target)) return;
537
+ if (!(target instanceof Node) || commandListRef?.parentElement?.contains(target)) return;
538
+ if (addSearch()) {
539
+ if (addButtonRef?.contains(target) && !addButtonRef.disabled) return;
540
+ if (textareaRef?.parentElement?.contains(target)) {
541
+ // The field takes the focus before the search field goes, so a phone keeps its keyboard; the press itself
542
+ // then places the caret.
543
+ textareaRef.focus({
544
+ preventScroll: true
545
+ });
546
+ endAddSearch(false);
547
+ return;
548
+ }
549
+ swallowTap(event);
550
+ endAddSearch(true);
551
+ return;
552
+ }
553
+ if (textareaRef?.parentElement?.contains(target)) return;
392
554
  setClosedAt(commandQuery()?.start);
393
555
  if (isTouchOnly() && !shellRef?.contains(target)) swallowTap(event);
394
556
  };
@@ -438,9 +600,10 @@ export function ChatComposer(props) {
438
600
  });
439
601
  });
440
602
  let settledEmpty;
603
+ // A space after "Nothing found" ends the `/…` as plain text; a search field opened from "+" just keeps its text.
441
604
  createEffect(() => {
442
605
  const token = commandQuery();
443
- if (!token || parsedCommandQuery().scope || searchError()) {
606
+ if (!token || addSearch() || parsedCommandQuery().scope || searchError()) {
444
607
  settledEmpty = undefined;
445
608
  return;
446
609
  }
@@ -491,6 +654,7 @@ export function ChatComposer(props) {
491
654
  history.length = 0;
492
655
  historyIndex = -1;
493
656
  finishModelSelection(null);
657
+ endAddSearch(false);
494
658
  setDismissed(true);
495
659
  setClosedAt(undefined);
496
660
  setSearchResults([]);
@@ -539,6 +703,8 @@ export function ChatComposer(props) {
539
703
  setDismissed(false);
540
704
  };
541
705
  const restoreHistory = direction => {
706
+ // A field that only stays enabled to keep focus, while an `open` row runs, is not edited by undo either.
707
+ if (editBlocked()) return;
542
708
  record();
543
709
  const next = history[historyIndex + direction];
544
710
  if (!next) return;
@@ -557,6 +723,45 @@ export function ChatComposer(props) {
557
723
  setSelectionEnd(textareaRef?.selectionEnd ?? props.value.length);
558
724
  });
559
725
  };
726
+ /** Closes the list opened from "+"; `refocus` gives the field its focus and the selection it had when "+" was pressed. */
727
+ const endAddSearch = refocus => {
728
+ const search = addSearch();
729
+ if (!search) return;
730
+ addComposing = false;
731
+ batch(() => {
732
+ setAddSearch(undefined);
733
+ setAddQuery("");
734
+ });
735
+ if (!refocus || !textareaRef) return;
736
+ const length = textareaRef.value.length;
737
+ textareaRef.focus();
738
+ textareaRef.setSelectionRange(Math.min(search.start, length), Math.min(search.end, length));
739
+ syncCaret();
740
+ };
741
+ /** Escape, Back, a press outside: the list closes and the text stays. */
742
+ const closeCommandList = (refocus = true) => {
743
+ if (addSearch()) endAddSearch(refocus);else setClosedAt(commandQuery()?.start);
744
+ };
745
+ const toggleAddSearch = () => {
746
+ if (addSearch()) {
747
+ endAddSearch(true);
748
+ return;
749
+ }
750
+ if (blocked() || !textareaRef) return;
751
+ const start = textareaRef.selectionStart;
752
+ const end = textareaRef.selectionEnd;
753
+ batch(() => {
754
+ // Emoji suggestions for a `:shortcode` at the caret give way; they would hold the list closed.
755
+ setDismissed(true);
756
+ setAddQuery("");
757
+ setAddSearch({
758
+ start,
759
+ end
760
+ });
761
+ });
762
+ // Within the press, so a phone opens its keyboard for the search field.
763
+ addSearchRef?.focus();
764
+ };
560
765
  const selectedCommand = createMemo(() => {
561
766
  const rows = commandMatches();
562
767
  return commandMoved() && rows.find(command => chatCommandKey(command) === activeCommandKey()) || rows[0];
@@ -580,6 +785,8 @@ export function ChatComposer(props) {
580
785
  const canSubmit = () => !submitting() && submittable();
581
786
  const canSelectFiles = () => Boolean(props.fileSelection && !props.fileSelection.disabled && !running() && !blocked());
582
787
  const hasAddMenu = () => Boolean(props.fileSelection || props.menuActions?.length);
788
+ /** "+" opens the slash list, as long as there is one; otherwise it stays the add menu. */
789
+ const addOpensCommands = () => Boolean(props.addOpensCommands && (props.commands?.length || props.searchCommands));
583
790
  const hasContextUsage = () => {
584
791
  if (props.contextPopupAction) return true;
585
792
  const context = props.contextUsage;
@@ -679,12 +886,78 @@ export function ChatComposer(props) {
679
886
  _$effect(() => _$setAttribute(_el$2, "title", attachment.name));
680
887
  return _el$;
681
888
  })();
682
- const chooseFiles = () => {
889
+
890
+ /** `onNothing` runs when the person closes the selection without a file. */
891
+ const chooseFiles = onNothing => {
683
892
  const selection = props.fileSelection;
684
- if (!selection?.choose) return fileInputRef?.click();
685
- selection.choose().then(
893
+ if (!selection?.choose) {
894
+ const input = fileInputRef;
895
+ if (input && onNothing) {
896
+ const done = new AbortController();
897
+ input.addEventListener("cancel", () => {
898
+ done.abort();
899
+ onNothing();
900
+ }, {
901
+ signal: done.signal
902
+ });
903
+ input.addEventListener("change", () => done.abort(), {
904
+ signal: done.signal
905
+ });
906
+ }
907
+ return input?.click();
908
+ }
909
+ const failed = error => {
910
+ onNothing?.();
911
+ (props.fileSelection?.onError ?? props.onError)?.(error);
912
+ };
913
+ let chosen;
914
+ try {
915
+ chosen = selection.choose();
916
+ } catch (error) {
917
+ failed(error);
918
+ return;
919
+ }
920
+ chosen.then(
686
921
  // A single-file composer keeps the first chosen file, as its file dialog and drops do.
687
- files => void runFiles(selection.multiple === false ? files.slice(0, 1) : files), error => (props.fileSelection?.onError ?? props.onError)?.(error));
922
+ files => {
923
+ if (files.length === 0) onNothing?.();else void runFiles(selection.multiple === false ? files.slice(0, 1) : files);
924
+ }, failed);
925
+ };
926
+
927
+ /**
928
+ * "Attach files" from the slash list: the token leaves as one edit, and the selection opens synchronously, inside the
929
+ * key or click that chose the row, because the device's file dialog needs that activation. Closing the selection
930
+ * without a file brings the token back, unless the draft changed meanwhile.
931
+ */
932
+ const attachFilesFromCommand = (token, selection) => {
933
+ if (!canSelectFiles()) return;
934
+ const key = props.draftKey;
935
+ const previous = snapshot();
936
+ const previousHistory = {
937
+ entries: [...history],
938
+ index: historyIndex
939
+ };
940
+ const nextValue = props.value.slice(0, token.start) + props.value.slice(token.end);
941
+ edit(nextValue, reconcileChatMentions(props.value, nextValue, mentions()));
942
+ setDismissed(true);
943
+ chooseFiles(() => {
944
+ if (props.draftKey !== key || props.value !== nextValue) return;
945
+ setDismissed(true);
946
+ props.onValueChange(previous.value);
947
+ props.onMentionsChange?.(previous.mentions);
948
+ history.splice(0, history.length, ...previousHistory.entries);
949
+ historyIndex = previousHistory.index;
950
+ queueMicrotask(() => {
951
+ textareaRef?.setSelectionRange(selection?.start ?? token.end, selection?.end ?? token.end);
952
+ syncCaret();
953
+ focus();
954
+ });
955
+ });
956
+ queueMicrotask(() => {
957
+ if (props.draftKey !== key || props.value !== nextValue) return;
958
+ textareaRef?.setSelectionRange(token.start, token.start);
959
+ syncCaret();
960
+ });
688
961
  };
689
962
  const runFiles = async files => {
690
963
  if (!canSelectFiles()) return;
@@ -707,7 +980,7 @@ export function ChatComposer(props) {
707
980
  setSubmitting(true);
708
981
  try {
709
982
  if (isTouchOnly()) {
710
- if (commandSheetHeld()) setClosedAt(commandQuery()?.start);
983
+ if (commandSheetHeld()) closeCommandList(false);
711
984
  // The sheet's Back entry leaves first, so a submit handler that navigates finds the history settled.
712
985
  await dialogHistorySettled();
713
986
  // A draft that another one replaced, or that may no longer go out, is not sent and keeps its text.
@@ -759,6 +1032,10 @@ export function ChatComposer(props) {
759
1032
  const word = scope?.words[0];
760
1033
  const token = commandQuery();
761
1034
  if (!word || !token || !textareaRef) return false;
1035
+ if (addSearch()) {
1036
+ setAddQuery(`${word} `);
1037
+ return true;
1038
+ }
762
1039
  replaceTextareaRange(textareaRef, token.start + 1, token.end, `${word} `);
763
1040
  syncCaret();
764
1041
  return true;
@@ -766,6 +1043,8 @@ export function ChatComposer(props) {
766
1043
  const executeCommand = async (command, tab = false) => {
767
1044
  const token = commandQuery();
768
1045
  const heldHistory = commandSheetHeld();
1046
+ const addSelection = addSearch();
1047
+ const fromAdd = addSelection !== undefined;
769
1048
  if (!token || blocked()) return;
770
1049
  if (command.disabled || command.reason) {
771
1050
  // A new object each time, so choosing the same row again inserts and announces its reason again.
@@ -779,17 +1058,35 @@ export function ChatComposer(props) {
779
1058
  setCommandOpening(opening => opening + 1);
780
1059
  return;
781
1060
  }
782
- if (command.scope && (tab || !command.action && !command.mention) && narrowCommand(command)) return;
1061
+ if (command.scope && (tab || !command.action && !command.mention && !command.attachFiles) && narrowCommand(command)) return;
1062
+ if (command.attachFiles) {
1063
+ if (!canSelectFiles()) return;
1064
+ // The field has the focus before the selection opens, so closing it without a file comes back there.
1065
+ endAddSearch(true);
1066
+ attachFilesFromCommand(token, addSelection);
1067
+ return;
1068
+ }
1069
+ if (command.open) {
1070
+ await openFromCommand(command, command.open, token);
1071
+ return;
1072
+ }
1073
+ // The field has the focus again before an action opens a dialog, so the dialog gives it back there.
1074
+ endAddSearch(true);
1075
+ // From "+" a reference joins the text at the caret, apart from a word right before it.
1076
+ const lead = value => fromAdd && token.start > 0 && !/\s/.test(value[token.start - 1] ?? "") ? " " : "";
783
1077
  const previous = snapshot();
784
1078
  const key = props.draftKey;
785
- const replacement = command.mention ? command.mention.name + " " : "";
1079
+ const replacement = command.mention ? lead(props.value) + command.mention.name + " " : "";
786
1080
  const nextValue = props.value.slice(0, token.start) + replacement + props.value.slice(token.end);
787
1081
  const nextMentions = reconcileChatMentions(props.value, nextValue, mentions());
788
- if (command.mention) nextMentions.push({
789
- start: token.start,
790
- end: token.start + command.mention.name.length,
791
- attachment: command.mention
792
- });
1082
+ if (command.mention) {
1083
+ const start = token.start + lead(props.value).length;
1084
+ nextMentions.push({
1085
+ start,
1086
+ end: start + command.mention.name.length,
1087
+ attachment: command.mention
1088
+ });
1089
+ }
793
1090
  // A cancelled or failed command leaves no undo step behind: restoring puts the history back as well.
794
1091
  const previousHistory = {
795
1092
  entries: [...history],
@@ -800,6 +1097,7 @@ export function ChatComposer(props) {
800
1097
  setExecuting(true);
801
1098
  let submitRequested = false;
802
1099
  let restored = false;
1100
+ let mentioned;
803
1101
  const restore = () => {
804
1102
  if (props.draftKey !== key || props.value !== nextValue) return;
805
1103
  setDismissed(true);
@@ -832,6 +1130,33 @@ export function ChatComposer(props) {
832
1130
  submitRequested = false;
833
1131
  restore();
834
1132
  showCommandStatus();
1133
+ } else if (result && "mention" in result) {
1134
+ // One undo step from the token to the reference, as if the row had been a reference itself.
1135
+ if (props.draftKey === key && props.value === nextValue) {
1136
+ restore();
1137
+ restored = false;
1138
+ const name = result.mention.name;
1139
+ const start = token.start + lead(previous.value).length;
1140
+ const withMention = previous.value.slice(0, token.start) + lead(previous.value) + name + " " + previous.value.slice(token.end);
1141
+ edit(withMention, [...reconcileChatMentions(previous.value, withMention, previous.mentions), {
1142
+ start,
1143
+ end: start + name.length,
1144
+ attachment: result.mention
1145
+ }]);
1146
+ setDismissed(true);
1147
+ mentioned = {
1148
+ value: withMention,
1149
+ caret: start + name.length + 1
1150
+ };
1151
+ showCommandStatus();
1152
+ } else {
1153
+ // The pick is lost; say so, also when the draft moved to another key meanwhile (such as a new chat saved
1154
+ // while the dialog was open), so it never ends in silence.
1155
+ showCommandStatus({
1156
+ tone: "error",
1157
+ text: chatMessages().commandDraftChanged
1158
+ });
1159
+ }
835
1160
  } else if (result) {
836
1161
  showCommandStatus({
837
1162
  tone: "done",
@@ -853,9 +1178,9 @@ export function ChatComposer(props) {
853
1178
  if (submitRequested && props.draftKey === key) await submit();
854
1179
  queueMicrotask(() => {
855
1180
  if (props.draftKey !== key) return;
856
- if (restored || props.value === nextValue) {
857
- const position = restored ? token.end : token.start + replacement.length;
858
- textareaRef?.setSelectionRange(position, position);
1181
+ if (restored || props.value === nextValue || mentioned && props.value === mentioned.value) {
1182
+ const position = restored ? token.end : mentioned?.caret ?? token.start + replacement.length;
1183
+ textareaRef?.setSelectionRange(restored && addSelection ? addSelection.start : position, restored && addSelection ? addSelection.end : position);
859
1184
  }
860
1185
  syncCaret();
861
1186
  autoResize();
@@ -863,6 +1188,110 @@ export function ChatComposer(props) {
863
1188
  });
864
1189
  };
865
1190
 
1191
+ /**
1192
+ * Runs an `open` row with the token and the list in place. Success removes the token in one undo step; `failed`
1193
+ * stays in the row while the list is still there, otherwise the status line says it, so it never ends in silence.
1194
+ */
1195
+ const openFromCommand = async (command, open, token) => {
1196
+ const key = props.draftKey;
1197
+ const row = chatCommandKey(command);
1198
+ const value = props.value;
1199
+ const nextValue = value.slice(0, token.start) + value.slice(token.end);
1200
+ const nextMentions = reconcileChatMentions(value, nextValue, mentions());
1201
+ // Still the same draft and `/…`, so the row is where the person chose it.
1202
+ const inPlace = () => !disposed && props.draftKey === key && props.value === value && commandQuery()?.start === token.start;
1203
+ const heldHistory = commandSheetHeld();
1204
+ // Closing the list or leaving the composer cancels the opening; the row ends at once, without waiting for it.
1205
+ const controller = new AbortController();
1206
+ const run = {
1207
+ controller,
1208
+ key,
1209
+ label: command.busyLabel ?? chatMessages().commandOpening,
1210
+ follow: false,
1211
+ moved: false
1212
+ };
1213
+ openingRun = run;
1214
+ const cancelled = new Promise(resolve => controller.signal.addEventListener("abort", () => resolve("cancelled"), {
1215
+ once: true
1216
+ }));
1217
+ setOpenFailures(({
1218
+ [row]: _,
1219
+ ...rest
1220
+ }) => rest);
1221
+ setOpeningRow(row);
1222
+ setExecuting(true);
1223
+ // An opening that ends without leaving, by failure, rejection or cancelling, also aborts `signal`, so the opener
1224
+ // can put back what it saved without the token.
1225
+ const finish = (left = false) => {
1226
+ if (!left) controller.abort();
1227
+ if (openingRun === run) openingRun = undefined;
1228
+ if (commandStatus()?.tone === "busy") showCommandStatus();
1229
+ setOpeningRow(undefined);
1230
+ setExecuting(false);
1231
+ };
1232
+ let result;
1233
+ try {
1234
+ if (heldHistory) {
1235
+ await dialogHistorySettled();
1236
+ if (!inPlace()) {
1237
+ finish();
1238
+ return;
1239
+ }
1240
+ }
1241
+ result = await Promise.race([open({
1242
+ value: nextValue,
1243
+ mentions: nextMentions
1244
+ }, controller.signal, () => {
1245
+ run.follow = true;
1246
+ }), cancelled]);
1247
+ } catch (error) {
1248
+ finish();
1249
+ if (disposed) {
1250
+ props.onError?.(error);
1251
+ return;
1252
+ }
1253
+ if (inPlace()) closeCommandList();
1254
+ showCommandStatus({
1255
+ tone: "error",
1256
+ text: error instanceof Error && error.message ? error.message : chatMessages().commandFailed
1257
+ });
1258
+ return;
1259
+ }
1260
+ if (!result) {
1261
+ // Success: the token leaves and the list closes in the same step that ends the opening, so a phone sheet never
1262
+ // takes its Back entry again while the page navigates.
1263
+ batch(() => {
1264
+ if (!disposed && props.draftKey === key && props.value === value) {
1265
+ edit(nextValue, nextMentions);
1266
+ setDismissed(true);
1267
+ }
1268
+ endAddSearch(!disposed && props.draftKey === key);
1269
+ finish(true);
1270
+ });
1271
+ queueMicrotask(() => {
1272
+ if (disposed || props.draftKey !== key || props.value !== nextValue) return;
1273
+ textareaRef?.setSelectionRange(token.start, token.start);
1274
+ syncCaret();
1275
+ autoResize();
1276
+ });
1277
+ return;
1278
+ }
1279
+ finish();
1280
+ if (result === "cancelled") return;
1281
+ if (inPlace()) {
1282
+ setOpenFailures(failures => ({
1283
+ ...failures,
1284
+ [row]: result.failed
1285
+ }));
1286
+ setAnnouncement({
1287
+ text: result.failed
1288
+ });
1289
+ } else if (disposed) props.onError?.(new Error(result.failed));else showCommandStatus({
1290
+ tone: "error",
1291
+ text: result.failed
1292
+ });
1293
+ };
1294
+
866
1295
  /** Replaces `start`–`end` with the emoji through the editing path, so the browser's undo restores the shortcode. */
867
1296
  const insertEmoji = (start, end, emoji) => {
868
1297
  if (!textareaRef || editBlocked()) return;
@@ -903,9 +1332,66 @@ export function ChatComposer(props) {
903
1332
  if (untouched && textarea.matches(":focus")) convert(loaded);
904
1333
  }, () => undefined);
905
1334
  };
1335
+
1336
+ /** Moving through and choosing in the command list, from the field or from the search field opened by "+". */
1337
+ const commandListKey = event => {
1338
+ if (!commandsOpen()) return false;
1339
+ const matches = commandMatches();
1340
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
1341
+ event.preventDefault();
1342
+ const index = matches.indexOf(selectedCommand());
1343
+ const next = matches[nextChatCommandIndex(index, matches.length, event.key === "ArrowUp" ? -1 : 1)];
1344
+ setActiveCommandKey(next ? chatCommandKey(next) : undefined);
1345
+ setCommandMoved(true);
1346
+ setAnnouncement(undefined);
1347
+ return true;
1348
+ }
1349
+ // Ctrl/⌘+Enter sends, also while suggestions are open.
1350
+ const plain = !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
1351
+ if (plain && (event.key === "Tab" || event.key === "Enter") && matches.length > 0) {
1352
+ event.preventDefault();
1353
+ const command = selectedCommand();
1354
+ // A server row answering an earlier query may no longer match; wait for fresh results. Local rows match now.
1355
+ const row = commandModel().rows.find(row => chatCommandKey(row.command) === selectedCommandKey());
1356
+ const staleServerRow = row?.server && (searchResultsQuery() !== commandQuery()?.query || searchResultsScope() !== parsedCommandQuery().scope?.id);
1357
+ if (staleServerRow) return true;
1358
+ if (command) void executeCommand(command, event.key === "Tab");
1359
+ return true;
1360
+ }
1361
+ if (event.key === "Escape") {
1362
+ event.preventDefault();
1363
+ closeCommandList();
1364
+ return true;
1365
+ }
1366
+ return false;
1367
+ };
1368
+ const onAddSearchKeyDown = event => {
1369
+ // Nothing chooses while an input method composes, as in the field.
1370
+ if (event.isComposing || event.keyCode === 229 || addComposing) return;
1371
+ if (event.key === "Escape" && openingRun) {
1372
+ event.preventDefault();
1373
+ openingRun.controller.abort();
1374
+ endAddSearch(true);
1375
+ return;
1376
+ }
1377
+ if (commandListKey(event)) return;
1378
+ // Ctrl/⌘+Enter sends from the search field as from the field, with the list closed first.
1379
+ if (event.key === "Enter" && (event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {
1380
+ event.preventDefault();
1381
+ endAddSearch(true);
1382
+ void submit();
1383
+ }
1384
+ };
906
1385
  const onKeyDown = event => {
907
1386
  // WebKit ends the composition before the keydown of the Enter that confirms it; that keydown keeps keyCode 229.
908
1387
  if (event.isComposing || event.keyCode === 229 || composing()) return;
1388
+ // Escape cancels a running `open` row, also once its list is gone because the draft moved to a new chat.
1389
+ if (event.key === "Escape" && openingRun) {
1390
+ event.preventDefault();
1391
+ openingRun.controller.abort();
1392
+ if (commandsOpen()) closeCommandList();
1393
+ return;
1394
+ }
909
1395
  if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "z") {
910
1396
  event.preventDefault();
911
1397
  restoreHistory(event.shiftKey ? 1 : -1);
@@ -930,38 +1416,11 @@ export function ChatComposer(props) {
930
1416
  return;
931
1417
  }
932
1418
  }
933
- const matches = commandMatches();
934
- if (commandsOpen()) {
935
- if (event.key === "ArrowUp" || event.key === "ArrowDown") {
936
- event.preventDefault();
937
- const index = matches.indexOf(selectedCommand());
938
- const next = matches[nextChatCommandIndex(index, matches.length, event.key === "ArrowUp" ? -1 : 1)];
939
- setActiveCommandKey(next ? chatCommandKey(next) : undefined);
940
- setCommandMoved(true);
941
- setAnnouncement(undefined);
942
- return;
943
- }
944
- // Ctrl/⌘+Enter sends, also while suggestions are open.
945
- const plain = !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
946
- if (plain && (event.key === "Tab" || event.key === "Enter") && matches.length > 0) {
947
- event.preventDefault();
948
- const command = selectedCommand();
949
- // A server row answering an earlier query may no longer match; wait for fresh results. Local rows match now.
950
- const row = commandModel().rows.find(row => chatCommandKey(row.command) === selectedCommandKey());
951
- const staleServerRow = row?.server && (searchResultsQuery() !== commandQuery()?.query || searchResultsScope() !== parsedCommandQuery().scope?.id);
952
- if (staleServerRow) return;
953
- if (command) void executeCommand(command, event.key === "Tab");
954
- return;
955
- }
956
- if (event.key === "Escape") {
957
- event.preventDefault();
958
- setClosedAt(commandQuery()?.start);
959
- return;
960
- }
961
- }
1419
+ if (commandListKey(event)) return;
962
1420
  const format = props.formatting && textareaRef ? formatShortcut(event) : undefined;
963
1421
  if (format && textareaRef) {
964
1422
  event.preventDefault();
1423
+ if (editBlocked()) return;
965
1424
  format.run(textareaRef);
966
1425
  return;
967
1426
  }
@@ -1102,8 +1561,52 @@ export function ChatComposer(props) {
1102
1561
  }
1103
1562
  });
1104
1563
 
1564
+ /** "+" as the way to the slash list on keyboards without a handy "/". */
1565
+ const addSearchButton = (extraClass = "") => _$createComponent(Tooltip.Trigger, {
1566
+ ref(r$) {
1567
+ var _ref$2 = addButtonRef;
1568
+ typeof _ref$2 === "function" ? _ref$2(r$) : addButtonRef = r$;
1569
+ },
1570
+ type: "button",
1571
+ "class": `k2b-chat-composer__icon-action${extraClass}`,
1572
+ get ["aria-label"]() {
1573
+ return chatMessages().addMenu;
1574
+ },
1575
+ "aria-haspopup": "listbox",
1576
+ get ["aria-expanded"]() {
1577
+ return addSearch() !== undefined;
1578
+ },
1579
+ get ["aria-controls"]() {
1580
+ return addSearch() ? commandListId : undefined;
1581
+ },
1582
+ get content() {
1583
+ return chatMessages().addMenu;
1584
+ },
1585
+ get disabled() {
1586
+ return blocked();
1587
+ },
1588
+ onMouseDown: keepFieldFocus,
1589
+ onClick: toggleAddSearch,
1590
+ get children() {
1591
+ var _el$5 = _$getNextElement(_tmpl$3);
1592
+ _$effect(() => _$className(_el$5, addingFiles() ? "ti ti-loader-2 k2b-spin" : "ti ti-plus"));
1593
+ return _el$5;
1594
+ }
1595
+ });
1596
+
1105
1597
  /** The conversation's attach button opens the file choice directly; other actions turn it into the add menu. */
1106
1598
  const attachControl = () => _$createComponent(Show, {
1599
+ get when() {
1600
+ return !addOpensCommands();
1601
+ },
1602
+ get fallback() {
1603
+ return addSearchButton(" k2b-chat-composer__attach");
1604
+ },
1605
+ get children() {
1606
+ return attachChoice();
1607
+ }
1608
+ });
1609
+ const attachChoice = () => _$createComponent(Show, {
1107
1610
  get when() {
1108
1611
  return props.menuActions?.length;
1109
1612
  },
@@ -1124,11 +1627,11 @@ export function ChatComposer(props) {
1124
1627
  get disabled() {
1125
1628
  return !canSelectFiles();
1126
1629
  },
1127
- onClick: chooseFiles,
1630
+ onClick: () => chooseFiles(),
1128
1631
  get children() {
1129
- var _el$5 = _$getNextElement(_tmpl$3);
1130
- _$effect(() => _$className(_el$5, addingFiles() ? "ti ti-loader-2 k2b-spin" : "ti ti-plus"));
1131
- return _el$5;
1632
+ var _el$6 = _$getNextElement(_tmpl$3);
1633
+ _$effect(() => _$className(_el$6, addingFiles() ? "ti ti-loader-2 k2b-spin" : "ti ti-plus"));
1634
+ return _el$6;
1132
1635
  }
1133
1636
  })
1134
1637
  });
@@ -1172,9 +1675,9 @@ export function ChatComposer(props) {
1172
1675
  return _$memo(() => !!props.formatting)() && formattingOpen();
1173
1676
  },
1174
1677
  get children() {
1175
- var _el$7 = _$getNextElement(_tmpl$5);
1176
- _$setAttribute(_el$7, "id", formatGroupId);
1177
- _$insert(_el$7, _$createComponent(For, {
1678
+ var _el$8 = _$getNextElement(_tmpl$5);
1679
+ _$setAttribute(_el$8, "id", formatGroupId);
1680
+ _$insert(_el$8, _$createComponent(For, {
1178
1681
  each: formatTools,
1179
1682
  children: tool => _$createComponent(Tooltip.Trigger, {
1180
1683
  type: "button",
@@ -1193,14 +1696,14 @@ export function ChatComposer(props) {
1193
1696
  if (textareaRef) tool.run(textareaRef);
1194
1697
  },
1195
1698
  get children() {
1196
- var _el$8 = _$getNextElement(_tmpl$3);
1197
- _$effect(() => _$className(_el$8, tool.icon));
1198
- return _el$8;
1699
+ var _el$9 = _$getNextElement(_tmpl$3);
1700
+ _$effect(() => _$className(_el$9, tool.icon));
1701
+ return _el$9;
1199
1702
  }
1200
1703
  })
1201
1704
  }));
1202
- _$effect(() => _$setAttribute(_el$7, "aria-label", chatMessages().composerFormatting));
1203
- return _el$7;
1705
+ _$effect(() => _$setAttribute(_el$8, "aria-label", chatMessages().composerFormatting));
1706
+ return _el$8;
1204
1707
  }
1205
1708
  });
1206
1709
  const emojiButton = () => _$createComponent(Show, {
@@ -1237,14 +1740,14 @@ export function ChatComposer(props) {
1237
1740
  return _$memo(() => !!(props.microphone?.onDictate || props.microphone?.onVoiceMessage))() ? props.microphone : undefined;
1238
1741
  },
1239
1742
  children: microphone => (() => {
1240
- var _el$0 = _$getNextElement(_tmpl$8),
1241
- _el$11 = _el$0.firstChild,
1242
- [_el$12, _co$] = _$getNextMarker(_el$11.nextSibling),
1243
- _el$13 = _el$12.nextSibling,
1244
- [_el$14, _co$2] = _$getNextMarker(_el$13.nextSibling);
1245
- var _ref$2 = microphoneRef;
1246
- typeof _ref$2 === "function" ? _$use(_ref$2, _el$0) : microphoneRef = _el$0;
1247
- _$insert(_el$0, _$createComponent(Tooltip.Trigger, {
1743
+ var _el$1 = _$getNextElement(_tmpl$8),
1744
+ _el$12 = _el$1.firstChild,
1745
+ [_el$13, _co$] = _$getNextMarker(_el$12.nextSibling),
1746
+ _el$14 = _el$13.nextSibling,
1747
+ [_el$15, _co$2] = _$getNextMarker(_el$14.nextSibling);
1748
+ var _ref$3 = microphoneRef;
1749
+ typeof _ref$3 === "function" ? _$use(_ref$3, _el$1) : microphoneRef = _el$1;
1750
+ _$insert(_el$1, _$createComponent(Tooltip.Trigger, {
1248
1751
  type: "button",
1249
1752
  "class": "k2b-chat-composer__icon-action k2b-chat-composer__microphone-button",
1250
1753
  get ["data-state"]() {
@@ -1304,12 +1807,12 @@ export function ChatComposer(props) {
1304
1807
  }
1305
1808
  },
1306
1809
  get children() {
1307
- var _el$1 = _$getNextElement(_tmpl$3);
1308
- _$effect(() => _$className(_el$1, dictation() === "listening" ? "ti ti-player-stop" : dictation() === "refining" ? "ti ti-loader-2 k2b-spin" : "ti ti-microphone"));
1309
- return _el$1;
1810
+ var _el$10 = _$getNextElement(_tmpl$3);
1811
+ _$effect(() => _$className(_el$10, dictation() === "listening" ? "ti ti-player-stop" : dictation() === "refining" ? "ti ti-loader-2 k2b-spin" : "ti ti-microphone"));
1812
+ return _el$10;
1310
1813
  }
1311
- }), _el$12, _co$);
1312
- _$insert(_el$0, _$createComponent(Show, {
1814
+ }), _el$13, _co$);
1815
+ _$insert(_el$1, _$createComponent(Show, {
1313
1816
  get when() {
1314
1817
  return microphone().onVoiceMessage;
1315
1818
  },
@@ -1346,8 +1849,8 @@ export function ChatComposer(props) {
1346
1849
  }
1347
1850
  });
1348
1851
  }
1349
- }), _el$14, _co$2);
1350
- return _el$0;
1852
+ }), _el$15, _co$2);
1853
+ return _el$1;
1351
1854
  })()
1352
1855
  });
1353
1856
  const sendControl = () => _$createComponent(Show, {
@@ -1372,9 +1875,9 @@ export function ChatComposer(props) {
1372
1875
  },
1373
1876
  onClick: () => void submit(),
1374
1877
  get children() {
1375
- var _el$16 = _$getNextElement(_tmpl$3);
1376
- _$effect(() => _$className(_el$16, submitting() ? "ti ti-loader-2 k2b-spin" : conversation() ? "ti ti-send" : "ti ti-arrow-up"));
1377
- return _el$16;
1878
+ var _el$17 = _$getNextElement(_tmpl$3);
1879
+ _$effect(() => _$className(_el$17, submitting() ? "ti ti-loader-2 k2b-spin" : conversation() ? "ti ti-send" : "ti ti-arrow-up"));
1880
+ return _el$17;
1378
1881
  }
1379
1882
  });
1380
1883
  },
@@ -1393,47 +1896,47 @@ export function ChatComposer(props) {
1393
1896
  },
1394
1897
  onClick: () => reportChatFailure(() => props.onStop?.(), props.onError),
1395
1898
  get children() {
1396
- var _el$15 = _$getNextElement(_tmpl$3);
1397
- _$effect(() => _$className(_el$15, stopping() ? "ti ti-loader-2 k2b-spin" : "ti ti-player-stop"));
1398
- return _el$15;
1899
+ var _el$16 = _$getNextElement(_tmpl$3);
1900
+ _$effect(() => _$className(_el$16, stopping() ? "ti ti-loader-2 k2b-spin" : "ti ti-player-stop"));
1901
+ return _el$16;
1399
1902
  }
1400
1903
  });
1401
1904
  }
1402
1905
  });
1403
1906
  const field = () => (() => {
1404
- var _el$17 = _$getNextElement(_tmpl$1),
1405
- _el$24 = _el$17.firstChild,
1406
- [_el$25, _co$4] = _$getNextMarker(_el$24.nextSibling),
1407
- _el$22 = _el$25.nextSibling,
1408
- _el$26 = _el$22.nextSibling,
1409
- [_el$27, _co$5] = _$getNextMarker(_el$26.nextSibling);
1410
- _$insert(_el$17, _$createComponent(Show, {
1907
+ var _el$18 = _$getNextElement(_tmpl$1),
1908
+ _el$25 = _el$18.firstChild,
1909
+ [_el$26, _co$4] = _$getNextMarker(_el$25.nextSibling),
1910
+ _el$23 = _el$26.nextSibling,
1911
+ _el$27 = _el$23.nextSibling,
1912
+ [_el$28, _co$5] = _$getNextMarker(_el$27.nextSibling);
1913
+ _$insert(_el$18, _$createComponent(Show, {
1411
1914
  get when() {
1412
1915
  return mentions().length > 0;
1413
1916
  },
1414
1917
  get children() {
1415
- var _el$18 = _$getNextElement(_tmpl$9),
1416
- _el$20 = _el$18.firstChild,
1417
- [_el$21, _co$3] = _$getNextMarker(_el$20.nextSibling),
1418
- _el$19 = _el$21.nextSibling;
1419
- var _ref$3 = highlightRef;
1420
- typeof _ref$3 === "function" ? _$use(_ref$3, _el$18) : highlightRef = _el$18;
1421
- _$insert(_el$18, _$createComponent(For, {
1918
+ var _el$19 = _$getNextElement(_tmpl$9),
1919
+ _el$21 = _el$19.firstChild,
1920
+ [_el$22, _co$3] = _$getNextMarker(_el$21.nextSibling),
1921
+ _el$20 = _el$22.nextSibling;
1922
+ var _ref$4 = highlightRef;
1923
+ typeof _ref$4 === "function" ? _$use(_ref$4, _el$19) : highlightRef = _el$19;
1924
+ _$insert(_el$19, _$createComponent(For, {
1422
1925
  get each() {
1423
1926
  return chatMentionSegments(props.value, mentions());
1424
1927
  },
1425
1928
  children: part => (() => {
1426
- var _el$28 = _$getNextElement(_tmpl$10);
1427
- _$insert(_el$28, () => part.text);
1428
- _$effect(() => _el$28.classList.toggle("k2b-chat-composer__mention", !!Boolean(part.mention)));
1429
- return _el$28;
1929
+ var _el$29 = _$getNextElement(_tmpl$10);
1930
+ _$insert(_el$29, () => part.text);
1931
+ _$effect(() => _el$29.classList.toggle("k2b-chat-composer__mention", !!Boolean(part.mention)));
1932
+ return _el$29;
1430
1933
  })()
1431
- }), _el$21, _co$3);
1432
- return _el$18;
1934
+ }), _el$22, _co$3);
1935
+ return _el$19;
1433
1936
  }
1434
- }), _el$25, _co$4);
1435
- _el$22.$$keydown = onKeyDown;
1436
- _el$22.$$beforeinput = event => {
1937
+ }), _el$26, _co$4);
1938
+ _el$23.$$keydown = onKeyDown;
1939
+ _el$23.$$beforeinput = event => {
1437
1940
  inputStart = event.currentTarget.selectionStart;
1438
1941
  inputEnd = event.currentTarget.selectionEnd;
1439
1942
  if (event.inputType === "historyUndo" || event.inputType === "historyRedo") {
@@ -1441,22 +1944,27 @@ export function ChatComposer(props) {
1441
1944
  restoreHistory(event.inputType === "historyUndo" ? -1 : 1);
1442
1945
  }
1443
1946
  };
1444
- _el$22.addEventListener("scroll", () => {
1947
+ _el$23.addEventListener("scroll", () => {
1445
1948
  if (highlightRef && textareaRef) highlightRef.scrollTop = textareaRef.scrollTop;
1446
1949
  });
1447
- _el$22.addEventListener("compositionend", () => {
1950
+ _el$23.addEventListener("compositionend", () => {
1448
1951
  setComposing(false);
1449
1952
  syncCaret();
1450
1953
  });
1451
- _el$22.addEventListener("compositionstart", () => setComposing(true));
1452
- _el$22.$$keyup = syncCaret;
1453
- _el$22.$$click = () => {
1954
+ _el$23.addEventListener("compositionstart", () => setComposing(true));
1955
+ _el$23.$$keyup = syncCaret;
1956
+ _el$23.$$click = () => {
1454
1957
  setDismissed(false);
1455
1958
  syncCaret();
1456
1959
  };
1457
- _el$22.addEventListener("blur", () => setDismissed(true));
1458
- _el$22.addEventListener("select", syncCaret);
1459
- _el$22.addEventListener("paste", event => {
1960
+ _el$23.addEventListener("blur", () => setDismissed(true));
1961
+ _el$23.addEventListener("select", syncCaret);
1962
+ _el$23.addEventListener("paste", event => {
1963
+ // Read-only while an `open` row runs: nothing may join the draft after it was saved.
1964
+ if (editBlocked()) {
1965
+ event.preventDefault();
1966
+ return;
1967
+ }
1460
1968
  const clipboardData = event.clipboardData;
1461
1969
  if (canSelectFiles() && clipboardData?.files.length) {
1462
1970
  event.preventDefault();
@@ -1465,7 +1973,7 @@ export function ChatComposer(props) {
1465
1973
  }
1466
1974
  props.onPaste?.(event);
1467
1975
  });
1468
- _el$22.$$input = event => {
1976
+ _el$23.$$input = event => {
1469
1977
  batch(() => {
1470
1978
  edit(event.currentTarget.value);
1471
1979
  syncCaret();
@@ -1474,42 +1982,44 @@ export function ChatComposer(props) {
1474
1982
  const input = event;
1475
1983
  if (input.inputType === "insertText" && input.data === ":") queueMicrotask(completeShortcode);
1476
1984
  };
1477
- var _ref$4 = textareaRef;
1478
- typeof _ref$4 === "function" ? _$use(_ref$4, _el$22) : textareaRef = _el$22;
1479
- _$insert(_el$17, _$createComponent(Show, {
1985
+ var _ref$5 = textareaRef;
1986
+ typeof _ref$5 === "function" ? _$use(_ref$5, _el$23) : textareaRef = _el$23;
1987
+ _$insert(_el$18, _$createComponent(Show, {
1480
1988
  get when() {
1481
1989
  return conversation();
1482
1990
  },
1483
1991
  get children() {
1484
- var _el$23 = _$getNextElement(_tmpl$0);
1485
- var _ref$5 = measureRef;
1486
- typeof _ref$5 === "function" ? _$use(_ref$5, _el$23) : measureRef = _el$23;
1487
- return _el$23;
1992
+ var _el$24 = _$getNextElement(_tmpl$0);
1993
+ var _ref$6 = measureRef;
1994
+ typeof _ref$6 === "function" ? _$use(_ref$6, _el$24) : measureRef = _el$24;
1995
+ return _el$24;
1488
1996
  }
1489
- }), _el$27, _co$5);
1997
+ }), _el$28, _co$5);
1490
1998
  _$effect(_p$ => {
1491
1999
  var _v$3 = chatMessages().messageInput,
1492
2000
  _v$4 = !!(mentions().length > 0),
1493
- _v$5 = editBlocked(),
1494
- _v$6 = conversation() ? "enter" : undefined,
1495
- _v$7 = props.placeholder ?? (running() ? chatMessages().addGuidance : conversation() ? chatMessages().writeConversationMessage : chatMessages().writeMessage),
1496
- _v$8 = props.inputLabel ?? messages().message,
1497
- _v$9 = suggestionsOpen() ? "combobox" : undefined,
1498
- _v$0 = suggestionsOpen() ? "list" : undefined,
1499
- _v$1 = suggestionsOpen() ? commandListId : undefined,
1500
- _v$10 = suggestionsOpen() ? "true" : undefined,
1501
- _v$11 = emojiOpen() ? `${commandListId}-${selectedCommandIndex()}` : selectedCommand() ? commandOptionId(selectedCommand()) : undefined;
1502
- _v$3 !== _p$.e && _$setAttribute(_el$17, "aria-label", _p$.e = _v$3);
1503
- _v$4 !== _p$.t && _el$22.classList.toggle("k2b-chat-composer__textarea--highlighted", _p$.t = _v$4);
1504
- _v$5 !== _p$.a && _$setProperty(_el$22, "disabled", _p$.a = _v$5);
1505
- _v$6 !== _p$.o && _$setAttribute(_el$22, "enterkeyhint", _p$.o = _v$6);
1506
- _v$7 !== _p$.i && _$setAttribute(_el$22, "placeholder", _p$.i = _v$7);
1507
- _v$8 !== _p$.n && _$setAttribute(_el$22, "aria-label", _p$.n = _v$8);
1508
- _v$9 !== _p$.s && _$setAttribute(_el$22, "role", _p$.s = _v$9);
1509
- _v$0 !== _p$.h && _$setAttribute(_el$22, "aria-autocomplete", _p$.h = _v$0);
1510
- _v$1 !== _p$.r && _$setAttribute(_el$22, "aria-controls", _p$.r = _v$1);
1511
- _v$10 !== _p$.d && _$setAttribute(_el$22, "aria-expanded", _p$.d = _v$10);
1512
- _v$11 !== _p$.l && _$setAttribute(_el$22, "aria-activedescendant", _p$.l = _v$11);
2001
+ _v$5 = editBlocked() && openingRow() === undefined,
2002
+ _v$6 = openingRow() !== undefined,
2003
+ _v$7 = conversation() ? "enter" : undefined,
2004
+ _v$8 = props.placeholder ?? (running() ? chatMessages().addGuidance : conversation() ? chatMessages().writeConversationMessage : chatMessages().writeMessage),
2005
+ _v$9 = props.inputLabel ?? messages().message,
2006
+ _v$0 = fieldOwnsList() ? "combobox" : undefined,
2007
+ _v$1 = fieldOwnsList() ? "list" : undefined,
2008
+ _v$10 = fieldOwnsList() ? commandListId : undefined,
2009
+ _v$11 = fieldOwnsList() ? "true" : undefined,
2010
+ _v$12 = !fieldOwnsList() ? undefined : emojiOpen() ? `${commandListId}-${selectedCommandIndex()}` : selectedCommand() ? commandOptionId(selectedCommand()) : undefined;
2011
+ _v$3 !== _p$.e && _$setAttribute(_el$18, "aria-label", _p$.e = _v$3);
2012
+ _v$4 !== _p$.t && _el$23.classList.toggle("k2b-chat-composer__textarea--highlighted", _p$.t = _v$4);
2013
+ _v$5 !== _p$.a && _$setProperty(_el$23, "disabled", _p$.a = _v$5);
2014
+ _v$6 !== _p$.o && _$setProperty(_el$23, "readOnly", _p$.o = _v$6);
2015
+ _v$7 !== _p$.i && _$setAttribute(_el$23, "enterkeyhint", _p$.i = _v$7);
2016
+ _v$8 !== _p$.n && _$setAttribute(_el$23, "placeholder", _p$.n = _v$8);
2017
+ _v$9 !== _p$.s && _$setAttribute(_el$23, "aria-label", _p$.s = _v$9);
2018
+ _v$0 !== _p$.h && _$setAttribute(_el$23, "role", _p$.h = _v$0);
2019
+ _v$1 !== _p$.r && _$setAttribute(_el$23, "aria-autocomplete", _p$.r = _v$1);
2020
+ _v$10 !== _p$.d && _$setAttribute(_el$23, "aria-controls", _p$.d = _v$10);
2021
+ _v$11 !== _p$.l && _$setAttribute(_el$23, "aria-expanded", _p$.l = _v$11);
2022
+ _v$12 !== _p$.u && _$setAttribute(_el$23, "aria-activedescendant", _p$.u = _v$12);
1513
2023
  return _p$;
1514
2024
  }, {
1515
2025
  e: undefined,
@@ -1522,32 +2032,35 @@ export function ChatComposer(props) {
1522
2032
  h: undefined,
1523
2033
  r: undefined,
1524
2034
  d: undefined,
1525
- l: undefined
2035
+ l: undefined,
2036
+ u: undefined
1526
2037
  });
1527
- _$effect(() => _$setProperty(_el$22, "value", props.value));
2038
+ _$effect(() => _$setProperty(_el$23, "value", props.value));
1528
2039
  _$runHydrationEvents();
1529
- return _el$17;
2040
+ return _el$18;
1530
2041
  })();
1531
2042
  const commandRowMap = createMemo(() => new Map(commandModel().rows.map(row => [row.command, row])));
1532
2043
  const commandGroupKey = group => group.scopeTitle ? "scope" : group.section ? `section:${group.section.id}` : "flat";
1533
2044
  const renderCommandRow = command => {
1534
2045
  const highlight = () => commandRowMap().get(command)?.highlight;
1535
2046
  const title = () => command.label ?? command.name;
2047
+ const opening = () => openingRow() === chatCommandKey(command);
2048
+ const failure = () => openFailures()[chatCommandKey(command)];
1536
2049
  return (() => {
1537
- var _el$29 = _$getNextElement(_tmpl$13),
1538
- _el$30 = _el$29.firstChild,
1539
- _el$31 = _el$30.nextSibling,
1540
- _el$32 = _el$31.firstChild,
1541
- _el$34 = _el$32.nextSibling,
1542
- [_el$35, _co$6] = _$getNextMarker(_el$34.nextSibling),
1543
- _el$39 = _el$31.nextSibling,
1544
- [_el$40, _co$7] = _$getNextMarker(_el$39.nextSibling);
1545
- _el$29.$$click = event => {
2050
+ var _el$30 = _$getNextElement(_tmpl$13),
2051
+ _el$31 = _el$30.firstChild,
2052
+ _el$32 = _el$31.nextSibling,
2053
+ _el$33 = _el$32.firstChild,
2054
+ _el$40 = _el$33.nextSibling,
2055
+ [_el$41, _co$7] = _$getNextMarker(_el$40.nextSibling),
2056
+ _el$45 = _el$32.nextSibling,
2057
+ [_el$46, _co$8] = _$getNextMarker(_el$45.nextSibling);
2058
+ _el$30.$$click = event => {
1546
2059
  event.preventDefault();
1547
2060
  void executeCommand(command);
1548
2061
  };
1549
- _el$29.$$mousedown = keepFieldFocus;
1550
- _$insert(_el$32, _$createComponent(Show, {
2062
+ _el$30.$$mousedown = keepFieldFocus;
2063
+ _$insert(_el$33, _$createComponent(Show, {
1551
2064
  get when() {
1552
2065
  return highlight();
1553
2066
  },
@@ -1555,49 +2068,82 @@ export function ChatComposer(props) {
1555
2068
  return title();
1556
2069
  },
1557
2070
  children: range => [_$memo(() => title().slice(0, range()[0])), (() => {
1558
- var _el$41 = _$getNextElement(_tmpl$14);
1559
- _$insert(_el$41, () => title().slice(range()[0], range()[1]));
1560
- return _el$41;
2071
+ var _el$47 = _$getNextElement(_tmpl$14);
2072
+ _$insert(_el$47, () => title().slice(range()[0], range()[1]));
2073
+ return _el$47;
1561
2074
  })(), _$memo(() => title().slice(range()[1]))]
1562
2075
  }));
1563
- _$insert(_el$31, _$createComponent(Show, {
2076
+ _$insert(_el$32, _$createComponent(Show, {
1564
2077
  get when() {
1565
- return command.reason ?? command.description;
2078
+ return _$memo(() => !!command.open)() && !command.reason;
2079
+ },
2080
+ get fallback() {
2081
+ return _$createComponent(Show, {
2082
+ get when() {
2083
+ return command.reason ?? command.description;
2084
+ },
2085
+ get children() {
2086
+ var _el$48 = _$getNextElement(_tmpl$15);
2087
+ _$insert(_el$48, () => command.reason ?? command.description);
2088
+ _$effect(() => _$setAttribute(_el$48, "id", command.reason ? `${commandOptionId(command)}-reason` : undefined));
2089
+ return _el$48;
2090
+ }
2091
+ });
1566
2092
  },
1567
2093
  get children() {
1568
- var _el$33 = _$getNextElement(_tmpl$11);
1569
- _$insert(_el$33, () => command.reason ?? command.description);
1570
- _$effect(() => _$setAttribute(_el$33, "id", command.reason ? `${commandOptionId(command)}-reason` : undefined));
1571
- return _el$33;
2094
+ var _el$34 = _$getNextElement(_tmpl$11),
2095
+ _el$35 = _el$34.firstChild,
2096
+ _el$36 = _el$35.nextSibling,
2097
+ _el$37 = _el$36.firstChild,
2098
+ _el$38 = _el$37.nextSibling,
2099
+ [_el$39, _co$6] = _$getNextMarker(_el$38.nextSibling);
2100
+ _$insert(_el$35, () => failure() ?? command.description);
2101
+ _$insert(_el$36, () => command.busyLabel ?? chatMessages().commandOpening, _el$39, _co$6);
2102
+ _$effect(_p$ => {
2103
+ var _v$13 = opening() ? "busy" : failure() ? "failed" : undefined,
2104
+ _v$14 = opening() ? "true" : undefined,
2105
+ _v$15 = opening() ? undefined : "true";
2106
+ _v$13 !== _p$.e && _$setAttribute(_el$34, "data-state", _p$.e = _v$13);
2107
+ _v$14 !== _p$.t && _$setAttribute(_el$35, "aria-hidden", _p$.t = _v$14);
2108
+ _v$15 !== _p$.a && _$setAttribute(_el$36, "aria-hidden", _p$.a = _v$15);
2109
+ return _p$;
2110
+ }, {
2111
+ e: undefined,
2112
+ t: undefined,
2113
+ a: undefined
2114
+ });
2115
+ return _el$34;
1572
2116
  }
1573
- }), _el$35, _co$6);
1574
- _$insert(_el$29, _$createComponent(Show, {
2117
+ }), _el$41, _co$7);
2118
+ _$insert(_el$30, _$createComponent(Show, {
1575
2119
  get when() {
1576
2120
  return command.selected;
1577
2121
  },
1578
2122
  get children() {
1579
- var _el$36 = _$getNextElement(_tmpl$12),
1580
- _el$37 = _el$36.firstChild,
1581
- _el$38 = _el$37.nextSibling;
1582
- _$insert(_el$38, () => chatMessages().commandSelected);
1583
- return _el$36;
2123
+ var _el$42 = _$getNextElement(_tmpl$12),
2124
+ _el$43 = _el$42.firstChild,
2125
+ _el$44 = _el$43.nextSibling;
2126
+ _$insert(_el$44, () => chatMessages().commandSelected);
2127
+ return _el$42;
1584
2128
  }
1585
- }), _el$40, _co$7);
2129
+ }), _el$46, _co$8);
1586
2130
  _$effect(_p$ => {
1587
- var _v$12 = commandOptionId(command),
1588
- _v$13 = selectedCommand() === command,
1589
- _v$14 = Boolean(command.disabled || command.reason),
1590
- _v$15 = command.reason ? `${commandOptionId(command)}-reason` : undefined,
1591
- _v$16 = command.reason ? "true" : undefined,
1592
- _v$17 = selectedCommand() === command ? "true" : undefined,
1593
- _v$18 = command.icon ?? "ti ti-slash";
1594
- _v$12 !== _p$.e && _$setAttribute(_el$29, "id", _p$.e = _v$12);
1595
- _v$13 !== _p$.t && _$setAttribute(_el$29, "aria-selected", _p$.t = _v$13);
1596
- _v$14 !== _p$.a && _$setAttribute(_el$29, "aria-disabled", _p$.a = _v$14);
1597
- _v$15 !== _p$.o && _$setAttribute(_el$29, "aria-describedby", _p$.o = _v$15);
1598
- _v$16 !== _p$.i && _$setAttribute(_el$29, "data-reason", _p$.i = _v$16);
1599
- _v$17 !== _p$.n && _$setAttribute(_el$29, "data-active", _p$.n = _v$17);
1600
- _v$18 !== _p$.s && _$className(_el$30, _p$.s = _v$18);
2131
+ var _v$16 = commandOptionId(command),
2132
+ _v$17 = selectedCommand() === command,
2133
+ _v$18 = Boolean(command.disabled || command.reason),
2134
+ _v$19 = opening() ? "true" : undefined,
2135
+ _v$20 = command.reason ? `${commandOptionId(command)}-reason` : undefined,
2136
+ _v$21 = command.reason ? "true" : undefined,
2137
+ _v$22 = selectedCommand() === command ? "true" : undefined,
2138
+ _v$23 = command.icon ?? "ti ti-slash";
2139
+ _v$16 !== _p$.e && _$setAttribute(_el$30, "id", _p$.e = _v$16);
2140
+ _v$17 !== _p$.t && _$setAttribute(_el$30, "aria-selected", _p$.t = _v$17);
2141
+ _v$18 !== _p$.a && _$setAttribute(_el$30, "aria-disabled", _p$.a = _v$18);
2142
+ _v$19 !== _p$.o && _$setAttribute(_el$30, "aria-busy", _p$.o = _v$19);
2143
+ _v$20 !== _p$.i && _$setAttribute(_el$30, "aria-describedby", _p$.i = _v$20);
2144
+ _v$21 !== _p$.n && _$setAttribute(_el$30, "data-reason", _p$.n = _v$21);
2145
+ _v$22 !== _p$.s && _$setAttribute(_el$30, "data-active", _p$.s = _v$22);
2146
+ _v$23 !== _p$.h && _$className(_el$31, _p$.h = _v$23);
1601
2147
  return _p$;
1602
2148
  }, {
1603
2149
  e: undefined,
@@ -1606,92 +2152,93 @@ export function ChatComposer(props) {
1606
2152
  o: undefined,
1607
2153
  i: undefined,
1608
2154
  n: undefined,
1609
- s: undefined
2155
+ s: undefined,
2156
+ h: undefined
1610
2157
  });
1611
2158
  _$runHydrationEvents();
1612
- return _el$29;
2159
+ return _el$30;
1613
2160
  })();
1614
2161
  };
1615
2162
  return (() => {
1616
- var _el$42 = _$getNextElement(_tmpl$25),
1617
- _el$108 = _el$42.firstChild,
1618
- [_el$109, _co$27] = _$getNextMarker(_el$108.nextSibling),
1619
- _el$70 = _el$109.nextSibling,
1620
- _el$94 = _el$70.firstChild,
1621
- [_el$95, _co$21] = _$getNextMarker(_el$94.nextSibling),
1622
- _el$96 = _el$95.nextSibling,
1623
- [_el$97, _co$22] = _$getNextMarker(_el$96.nextSibling),
1624
- _el$98 = _el$97.nextSibling,
1625
- [_el$99, _co$23] = _$getNextMarker(_el$98.nextSibling),
1626
- _el$100 = _el$99.nextSibling,
1627
- [_el$101, _co$24] = _$getNextMarker(_el$100.nextSibling),
1628
- _el$102 = _el$70.nextSibling,
1629
- _el$103 = _el$102.nextSibling,
1630
- _el$104 = _el$103.firstChild,
1631
- [_el$105, _co$25] = _$getNextMarker(_el$104.nextSibling),
1632
- _el$106 = _el$105.nextSibling,
1633
- [_el$107, _co$26] = _$getNextMarker(_el$106.nextSibling);
1634
- var _ref$6 = shellRef;
1635
- typeof _ref$6 === "function" ? _$use(_ref$6, _el$42) : shellRef = _el$42;
1636
- _$insert(_el$42, _$createComponent(Show, {
2163
+ var _el$49 = _$getNextElement(_tmpl$27),
2164
+ _el$122 = _el$49.firstChild,
2165
+ [_el$123, _co$30] = _$getNextMarker(_el$122.nextSibling),
2166
+ _el$84 = _el$123.nextSibling,
2167
+ _el$108 = _el$84.firstChild,
2168
+ [_el$109, _co$24] = _$getNextMarker(_el$108.nextSibling),
2169
+ _el$110 = _el$109.nextSibling,
2170
+ [_el$111, _co$25] = _$getNextMarker(_el$110.nextSibling),
2171
+ _el$112 = _el$111.nextSibling,
2172
+ [_el$113, _co$26] = _$getNextMarker(_el$112.nextSibling),
2173
+ _el$114 = _el$113.nextSibling,
2174
+ [_el$115, _co$27] = _$getNextMarker(_el$114.nextSibling),
2175
+ _el$116 = _el$84.nextSibling,
2176
+ _el$117 = _el$116.nextSibling,
2177
+ _el$118 = _el$117.firstChild,
2178
+ [_el$119, _co$28] = _$getNextMarker(_el$118.nextSibling),
2179
+ _el$120 = _el$119.nextSibling,
2180
+ [_el$121, _co$29] = _$getNextMarker(_el$120.nextSibling);
2181
+ var _ref$7 = shellRef;
2182
+ typeof _ref$7 === "function" ? _$use(_ref$7, _el$49) : shellRef = _el$49;
2183
+ _$insert(_el$49, _$createComponent(Show, {
1637
2184
  get when() {
1638
2185
  return suggestionsOpen() || hasAccessory();
1639
2186
  },
1640
2187
  get children() {
1641
- var _el$43 = _$getNextElement(_tmpl$20),
1642
- _el$44 = _el$43.firstChild,
1643
- _el$66 = _el$44.nextSibling,
1644
- [_el$67, _co$11] = _$getNextMarker(_el$66.nextSibling),
1645
- _el$68 = _el$67.nextSibling,
1646
- [_el$69, _co$12] = _$getNextMarker(_el$68.nextSibling);
1647
- _$insert(_el$44, accessory);
1648
- _$insert(_el$43, _$createComponent(Show, {
2188
+ var _el$50 = _$getNextElement(_tmpl$22),
2189
+ _el$51 = _el$50.firstChild,
2190
+ _el$80 = _el$51.nextSibling,
2191
+ [_el$81, _co$14] = _$getNextMarker(_el$80.nextSibling),
2192
+ _el$82 = _el$81.nextSibling,
2193
+ [_el$83, _co$15] = _$getNextMarker(_el$82.nextSibling);
2194
+ _$insert(_el$51, accessory);
2195
+ _$insert(_el$50, _$createComponent(Show, {
1649
2196
  get when() {
1650
2197
  return emojiOpen();
1651
2198
  },
1652
2199
  get children() {
1653
- var _el$45 = _$getNextElement(_tmpl$15),
1654
- _el$46 = _el$45.firstChild;
1655
- var _ref$7 = commandListRef;
1656
- typeof _ref$7 === "function" ? _$use(_ref$7, _el$46) : commandListRef = _el$46;
1657
- _$setAttribute(_el$46, "id", commandListId);
1658
- _$insert(_el$46, _$createComponent(For, {
2200
+ var _el$52 = _$getNextElement(_tmpl$16),
2201
+ _el$53 = _el$52.firstChild;
2202
+ var _ref$8 = commandListRef;
2203
+ typeof _ref$8 === "function" ? _$use(_ref$8, _el$53) : commandListRef = _el$53;
2204
+ _$setAttribute(_el$53, "id", commandListId);
2205
+ _$insert(_el$53, _$createComponent(For, {
1659
2206
  get each() {
1660
2207
  return emojiMatches();
1661
2208
  },
1662
2209
  children: (entry, index) => (() => {
1663
- var _el$110 = _$getNextElement(_tmpl$26),
1664
- _el$111 = _el$110.firstChild,
1665
- _el$112 = _el$111.nextSibling,
1666
- _el$113 = _el$112.nextSibling,
1667
- [_el$114, _co$28] = _$getNextMarker(_el$113.nextSibling);
1668
- _el$110.$$click = () => pickEmojiSuggestion(index());
1669
- _el$110.$$mousedown = keepFieldFocus;
1670
- _$insert(_el$111, () => emojiInTone(entry, props.emoji?.skinTone ?? 0));
1671
- _$insert(_el$112, () => emojiName(entry, locale()));
1672
- _$insert(_el$110, _$createComponent(Show, {
2210
+ var _el$124 = _$getNextElement(_tmpl$28),
2211
+ _el$125 = _el$124.firstChild,
2212
+ _el$126 = _el$125.nextSibling,
2213
+ _el$127 = _el$126.nextSibling,
2214
+ [_el$128, _co$31] = _$getNextMarker(_el$127.nextSibling);
2215
+ _el$124.$$click = () => pickEmojiSuggestion(index());
2216
+ _el$124.$$mousedown = keepFieldFocus;
2217
+ _$insert(_el$125, () => emojiInTone(entry, props.emoji?.skinTone ?? 0));
2218
+ _$insert(_el$126, () => emojiName(entry, locale()));
2219
+ _$insert(_el$124, _$createComponent(Show, {
1673
2220
  get when() {
1674
2221
  return entry.shortcodes[0];
1675
2222
  },
1676
2223
  children: code => (() => {
1677
- var _el$115 = _$getNextElement(_tmpl$27),
1678
- _el$116 = _el$115.firstChild,
1679
- _el$118 = _el$116.nextSibling,
1680
- [_el$119, _co$29] = _$getNextMarker(_el$118.nextSibling),
1681
- _el$117 = _el$119.nextSibling;
1682
- _$insert(_el$115, code, _el$119, _co$29);
1683
- return _el$115;
2224
+ var _el$129 = _$getNextElement(_tmpl$29),
2225
+ _el$130 = _el$129.firstChild,
2226
+ _el$132 = _el$130.nextSibling,
2227
+ [_el$133, _co$32] = _$getNextMarker(_el$132.nextSibling),
2228
+ _el$131 = _el$133.nextSibling;
2229
+ _$insert(_el$129, code, _el$133, _co$32);
2230
+ return _el$129;
1684
2231
  })()
1685
- }), _el$114, _co$28);
2232
+ }), _el$128, _co$31);
1686
2233
  _$effect(_p$ => {
1687
- var _v$28 = `${commandListId}-${index()}`,
1688
- _v$29 = index() === selectedCommandIndex(),
1689
- _v$30 = emojiName(entry, locale()),
1690
- _v$31 = index() === selectedCommandIndex() ? "true" : undefined;
1691
- _v$28 !== _p$.e && _$setAttribute(_el$110, "id", _p$.e = _v$28);
1692
- _v$29 !== _p$.t && _$setAttribute(_el$110, "aria-selected", _p$.t = _v$29);
1693
- _v$30 !== _p$.a && _$setAttribute(_el$110, "aria-label", _p$.a = _v$30);
1694
- _v$31 !== _p$.o && _$setAttribute(_el$110, "data-active", _p$.o = _v$31);
2234
+ var _v$38 = `${commandListId}-${index()}`,
2235
+ _v$39 = index() === selectedCommandIndex(),
2236
+ _v$40 = emojiName(entry, locale()),
2237
+ _v$41 = index() === selectedCommandIndex() ? "true" : undefined;
2238
+ _v$38 !== _p$.e && _$setAttribute(_el$124, "id", _p$.e = _v$38);
2239
+ _v$39 !== _p$.t && _$setAttribute(_el$124, "aria-selected", _p$.t = _v$39);
2240
+ _v$40 !== _p$.a && _$setAttribute(_el$124, "aria-label", _p$.a = _v$40);
2241
+ _v$41 !== _p$.o && _$setAttribute(_el$124, "data-active", _p$.o = _v$41);
1695
2242
  return _p$;
1696
2243
  }, {
1697
2244
  e: undefined,
@@ -1700,32 +2247,88 @@ export function ChatComposer(props) {
1700
2247
  o: undefined
1701
2248
  });
1702
2249
  _$runHydrationEvents();
1703
- return _el$110;
2250
+ return _el$124;
1704
2251
  })()
1705
2252
  }));
1706
- _$effect(() => _$setAttribute(_el$46, "aria-label", chatMessages().emojiSuggestions));
1707
- return _el$45;
2253
+ _$effect(() => _$setAttribute(_el$53, "aria-label", chatMessages().emojiSuggestions));
2254
+ return _el$52;
1708
2255
  }
1709
- }), _el$67, _co$11);
1710
- _$insert(_el$43, _$createComponent(Show, {
2256
+ }), _el$81, _co$14);
2257
+ _$insert(_el$50, _$createComponent(Show, {
1711
2258
  get when() {
1712
2259
  return commandsOpen();
1713
2260
  },
1714
2261
  get children() {
1715
- var _el$47 = _$getNextElement(_tmpl$19),
1716
- _el$48 = _el$47.firstChild,
1717
- _el$58 = _el$48.firstChild,
1718
- [_el$59, _co$9] = _$getNextMarker(_el$58.nextSibling),
1719
- _el$60 = _el$59.nextSibling,
1720
- [_el$61, _co$0] = _$getNextMarker(_el$60.nextSibling),
1721
- _el$62 = _el$61.nextSibling,
1722
- [_el$63, _co$1] = _$getNextMarker(_el$62.nextSibling),
1723
- _el$64 = _el$63.nextSibling,
1724
- [_el$65, _co$10] = _$getNextMarker(_el$64.nextSibling);
1725
- var _ref$8 = commandListRef;
1726
- typeof _ref$8 === "function" ? _$use(_ref$8, _el$48) : commandListRef = _el$48;
1727
- _$setAttribute(_el$48, "id", commandListId);
1728
- _$insert(_el$48, _$createComponent(For, {
2262
+ var _el$54 = _$getNextElement(_tmpl$21),
2263
+ _el$78 = _el$54.firstChild,
2264
+ [_el$79, _co$13] = _$getNextMarker(_el$78.nextSibling),
2265
+ _el$58 = _el$79.nextSibling,
2266
+ _el$68 = _el$58.firstChild,
2267
+ [_el$69, _co$0] = _$getNextMarker(_el$68.nextSibling),
2268
+ _el$70 = _el$69.nextSibling,
2269
+ [_el$71, _co$1] = _$getNextMarker(_el$70.nextSibling),
2270
+ _el$72 = _el$71.nextSibling,
2271
+ [_el$73, _co$10] = _$getNextMarker(_el$72.nextSibling),
2272
+ _el$74 = _el$73.nextSibling,
2273
+ [_el$75, _co$11] = _$getNextMarker(_el$74.nextSibling),
2274
+ _el$76 = _el$75.nextSibling,
2275
+ [_el$77, _co$12] = _$getNextMarker(_el$76.nextSibling);
2276
+ _el$54.$$mousedown = event => {
2277
+ if (addSearch() && event.target !== addSearchRef) event.preventDefault();
2278
+ };
2279
+ _$insert(_el$54, _$createComponent(Show, {
2280
+ get when() {
2281
+ return addSearch();
2282
+ },
2283
+ get children() {
2284
+ var _el$55 = _$getNextElement(_tmpl$17),
2285
+ _el$56 = _el$55.firstChild,
2286
+ _el$57 = _el$56.nextSibling;
2287
+ _el$57.$$focusout = event => {
2288
+ const next = event.relatedTarget;
2289
+ if (next instanceof Node && commandListRef?.parentElement?.contains(next)) return;
2290
+ // Focus that leaves another way, such as with Shift+Tab, closes the list and stays where it went.
2291
+ queueMicrotask(() => {
2292
+ if (addSearch() && document.activeElement !== addSearchRef) endAddSearch(false);
2293
+ });
2294
+ };
2295
+ _el$57.addEventListener("compositionend", () => {
2296
+ addComposing = false;
2297
+ });
2298
+ _el$57.addEventListener("compositionstart", () => {
2299
+ addComposing = true;
2300
+ });
2301
+ _el$57.$$keydown = onAddSearchKeyDown;
2302
+ _el$57.$$input = event => setAddQuery(event.currentTarget.value);
2303
+ var _ref$9 = addSearchRef;
2304
+ typeof _ref$9 === "function" ? _$use(_ref$9, _el$57) : addSearchRef = _el$57;
2305
+ _$setAttribute(_el$57, "aria-controls", commandListId);
2306
+ _$setAttribute(_el$57, "spellcheck", false);
2307
+ _$effect(_p$ => {
2308
+ var _v$24 = chatMessages().commandSearch,
2309
+ _v$25 = chatMessages().commandSearchLabel,
2310
+ _v$26 = selectedCommand() ? commandOptionId(selectedCommand()) : undefined,
2311
+ _v$27 = openingRow() !== undefined;
2312
+ _v$24 !== _p$.e && _$setAttribute(_el$57, "placeholder", _p$.e = _v$24);
2313
+ _v$25 !== _p$.t && _$setAttribute(_el$57, "aria-label", _p$.t = _v$25);
2314
+ _v$26 !== _p$.a && _$setAttribute(_el$57, "aria-activedescendant", _p$.a = _v$26);
2315
+ _v$27 !== _p$.o && _$setProperty(_el$57, "readOnly", _p$.o = _v$27);
2316
+ return _p$;
2317
+ }, {
2318
+ e: undefined,
2319
+ t: undefined,
2320
+ a: undefined,
2321
+ o: undefined
2322
+ });
2323
+ _$effect(() => _$setProperty(_el$57, "value", addQuery()));
2324
+ _$runHydrationEvents();
2325
+ return _el$55;
2326
+ }
2327
+ }), _el$79, _co$13);
2328
+ var _ref$0 = commandListRef;
2329
+ typeof _ref$0 === "function" ? _$use(_ref$0, _el$58) : commandListRef = _el$58;
2330
+ _$setAttribute(_el$58, "id", commandListId);
2331
+ _$insert(_el$58, _$createComponent(For, {
1729
2332
  get each() {
1730
2333
  return commandModel().groups.map(commandGroupKey);
1731
2334
  },
@@ -1744,343 +2347,354 @@ export function ChatComposer(props) {
1744
2347
  });
1745
2348
  },
1746
2349
  get children() {
1747
- var _el$120 = _$getNextElement(_tmpl$30),
1748
- _el$121 = _el$120.firstChild,
1749
- _el$122 = _el$121.firstChild,
1750
- _el$124 = _el$122.nextSibling,
1751
- [_el$125, _co$30] = _$getNextMarker(_el$124.nextSibling),
1752
- _el$127 = _el$121.nextSibling,
1753
- [_el$128, _co$31] = _$getNextMarker(_el$127.nextSibling),
1754
- _el$129 = _el$128.nextSibling,
1755
- [_el$130, _co$32] = _$getNextMarker(_el$129.nextSibling);
1756
- _$insert(_el$122, () => group()?.scopeTitle ?? group()?.section?.label);
1757
- _$insert(_el$121, _$createComponent(Show, {
2350
+ var _el$134 = _$getNextElement(_tmpl$31),
2351
+ _el$135 = _el$134.firstChild,
2352
+ _el$136 = _el$135.firstChild,
2353
+ _el$138 = _el$136.nextSibling,
2354
+ [_el$139, _co$33] = _$getNextMarker(_el$138.nextSibling),
2355
+ _el$140 = _el$135.nextSibling,
2356
+ [_el$141, _co$34] = _$getNextMarker(_el$140.nextSibling),
2357
+ _el$142 = _el$141.nextSibling,
2358
+ [_el$143, _co$35] = _$getNextMarker(_el$142.nextSibling);
2359
+ _$insert(_el$136, () => group()?.scopeTitle ?? group()?.section?.label);
2360
+ _$insert(_el$135, _$createComponent(Show, {
1758
2361
  get when() {
1759
2362
  return group()?.loading;
1760
2363
  },
1761
2364
  get children() {
1762
- return _$getNextElement(_tmpl$28);
2365
+ return _$getNextElement(_tmpl$30);
1763
2366
  }
1764
- }), _el$125, _co$30);
1765
- _$insert(_el$120, _$createComponent(For, {
2367
+ }), _el$139, _co$33);
2368
+ _$insert(_el$134, _$createComponent(For, {
1766
2369
  get each() {
1767
2370
  return rows();
1768
2371
  },
1769
2372
  children: renderCommandRow
1770
- }), _el$128, _co$31);
1771
- _$insert(_el$120, _$createComponent(Show, {
1772
- get when() {
1773
- return group()?.placeholder;
2373
+ }), _el$141, _co$34);
2374
+ _$insert(_el$134, _$createComponent(Index, {
2375
+ get each() {
2376
+ return Array.from({
2377
+ length: Math.max(group()?.placeholder ? 1 : 0, group()?.pendingRows ?? 0)
2378
+ });
1774
2379
  },
1775
- get children() {
1776
- return _$getNextElement(_tmpl$29);
1777
- }
1778
- }), _el$130, _co$32);
2380
+ children: () => _$getNextElement(_tmpl$32)
2381
+ }), _el$143, _co$35);
1779
2382
  _$effect(_p$ => {
1780
- var _v$32 = headingId(),
1781
- _v$33 = headingId();
1782
- _v$32 !== _p$.e && _$setAttribute(_el$120, "aria-labelledby", _p$.e = _v$32);
1783
- _v$33 !== _p$.t && _$setAttribute(_el$121, "id", _p$.t = _v$33);
2383
+ var _v$42 = headingId(),
2384
+ _v$43 = headingId();
2385
+ _v$42 !== _p$.e && _$setAttribute(_el$134, "aria-labelledby", _p$.e = _v$42);
2386
+ _v$43 !== _p$.t && _$setAttribute(_el$135, "id", _p$.t = _v$43);
1784
2387
  return _p$;
1785
2388
  }, {
1786
2389
  e: undefined,
1787
2390
  t: undefined
1788
2391
  });
1789
- return _el$120;
2392
+ return _el$134;
1790
2393
  }
1791
2394
  });
1792
2395
  }
1793
- }), _el$59, _co$9);
1794
- _$insert(_el$48, _$createComponent(Show, {
2396
+ }), _el$69, _co$0);
2397
+ _$insert(_el$58, _$createComponent(Show, {
1795
2398
  get when() {
1796
- return _$memo(() => !!(searching() && commandMatches().length === 0))() && !commandModel().groups.some(group => group.section || group.scopeTitle);
2399
+ return _$memo(() => !!(searching() && foundCommandCount() === 0))() && !commandModel().groups.some(group => group.section || group.scopeTitle);
1797
2400
  },
1798
2401
  get children() {
1799
- var _el$49 = _$getNextElement(_tmpl$16),
1800
- _el$50 = _el$49.firstChild,
1801
- _el$51 = _el$50.nextSibling;
1802
- _$insert(_el$51, () => messages().loading);
1803
- return _el$49;
2402
+ var _el$59 = _$getNextElement(_tmpl$18),
2403
+ _el$60 = _el$59.firstChild,
2404
+ _el$61 = _el$60.nextSibling;
2405
+ _$insert(_el$61, () => messages().loading);
2406
+ return _el$59;
1804
2407
  }
1805
- }), _el$61, _co$0);
1806
- _$insert(_el$48, _$createComponent(Show, {
2408
+ }), _el$71, _co$1);
2409
+ _$insert(_el$58, _$createComponent(Show, {
1807
2410
  get when() {
1808
2411
  return searchError();
1809
2412
  },
1810
2413
  get children() {
1811
- var _el$52 = _$getNextElement(_tmpl$17),
1812
- _el$53 = _el$52.firstChild,
1813
- _el$54 = _el$53.nextSibling,
1814
- _el$55 = _el$54.nextSibling,
1815
- [_el$56, _co$8] = _$getNextMarker(_el$55.nextSibling);
1816
- _$insert(_el$52, () => messages().error, _el$56, _co$8);
1817
- return _el$52;
2414
+ var _el$62 = _$getNextElement(_tmpl$19),
2415
+ _el$63 = _el$62.firstChild,
2416
+ _el$64 = _el$63.nextSibling,
2417
+ _el$65 = _el$64.nextSibling,
2418
+ [_el$66, _co$9] = _$getNextMarker(_el$65.nextSibling);
2419
+ _$insert(_el$62, () => messages().error, _el$66, _co$9);
2420
+ return _el$62;
1818
2421
  }
1819
- }), _el$63, _co$1);
1820
- _$insert(_el$48, _$createComponent(Show, {
2422
+ }), _el$73, _co$10);
2423
+ _$insert(_el$58, _$createComponent(Show, {
1821
2424
  get when() {
1822
- return _$memo(() => !!(!searching() && !searchError()))() && commandMatches().length === 0;
2425
+ return _$memo(() => !!(!searching() && !searchError() && foundCommandCount() === 0))() && !commandModel().groups.some(group => group.pendingRows);
1823
2426
  },
1824
2427
  get children() {
1825
- var _el$57 = _$getNextElement(_tmpl$18);
1826
- _$insert(_el$57, (() => {
2428
+ var _el$67 = _$getNextElement(_tmpl$20);
2429
+ _$insert(_el$67, (() => {
1827
2430
  var _c$ = _$memo(() => !!!parsedCommandQuery().query.trim());
1828
2431
  return () => _c$() ? messages().noResults : chatMessages().commandsNothingFound({
1829
2432
  query: parsedCommandQuery().query.trim()
1830
2433
  });
1831
2434
  })());
1832
- return _el$57;
2435
+ return _el$67;
1833
2436
  }
1834
- }), _el$65, _co$10);
2437
+ }), _el$75, _co$11);
2438
+ _$insert(_el$58, _$createComponent(Show, {
2439
+ get when() {
2440
+ return commandModel().fallback?.command;
2441
+ },
2442
+ keyed: true,
2443
+ children: command => renderCommandRow(command)
2444
+ }), _el$77, _co$12);
1835
2445
  _$effect(_p$ => {
1836
- var _v$19 = chatMessages().commands,
1837
- _v$20 = searching() ? "true" : undefined;
1838
- _v$19 !== _p$.e && _$setAttribute(_el$48, "aria-label", _p$.e = _v$19);
1839
- _v$20 !== _p$.t && _$setAttribute(_el$48, "aria-busy", _p$.t = _v$20);
2446
+ var _v$28 = addSearch() ? "" : undefined,
2447
+ _v$29 = chatMessages().commands,
2448
+ _v$30 = searching() ? "true" : undefined;
2449
+ _v$28 !== _p$.e && _$setAttribute(_el$54, "data-search", _p$.e = _v$28);
2450
+ _v$29 !== _p$.t && _$setAttribute(_el$58, "aria-label", _p$.t = _v$29);
2451
+ _v$30 !== _p$.a && _$setAttribute(_el$58, "aria-busy", _p$.a = _v$30);
1840
2452
  return _p$;
1841
2453
  }, {
1842
2454
  e: undefined,
1843
- t: undefined
2455
+ t: undefined,
2456
+ a: undefined
1844
2457
  });
1845
- return _el$47;
2458
+ _$runHydrationEvents();
2459
+ return _el$54;
1846
2460
  }
1847
- }), _el$69, _co$12);
2461
+ }), _el$83, _co$15);
1848
2462
  _$effect(_p$ => {
1849
- var _v$21 = hasAccessory() ? undefined : "true",
1850
- _v$22 = suggestionsOpen() ? "hidden" : undefined,
1851
- _v$23 = suggestionsOpen();
1852
- _v$21 !== _p$.e && _$setAttribute(_el$43, "data-overlay", _p$.e = _v$21);
1853
- _v$22 !== _p$.t && _$setStyleProperty(_el$44, "visibility", _p$.t = _v$22);
1854
- _v$23 !== _p$.a && _$setProperty(_el$44, "inert", _p$.a = _v$23);
2463
+ var _v$31 = hasAccessory() ? undefined : "true",
2464
+ _v$32 = suggestionsOpen() ? "hidden" : undefined,
2465
+ _v$33 = suggestionsOpen();
2466
+ _v$31 !== _p$.e && _$setAttribute(_el$50, "data-overlay", _p$.e = _v$31);
2467
+ _v$32 !== _p$.t && _$setStyleProperty(_el$51, "visibility", _p$.t = _v$32);
2468
+ _v$33 !== _p$.a && _$setProperty(_el$51, "inert", _p$.a = _v$33);
1855
2469
  return _p$;
1856
2470
  }, {
1857
2471
  e: undefined,
1858
2472
  t: undefined,
1859
2473
  a: undefined
1860
2474
  });
1861
- return _el$43;
2475
+ return _el$50;
1862
2476
  }
1863
- }), _el$109, _co$27);
1864
- var _ref$9 = composerRef;
1865
- typeof _ref$9 === "function" ? _$use(_ref$9, _el$70) : composerRef = _el$70;
1866
- _$insert(_el$70, _$createComponent(Show, {
2477
+ }), _el$123, _co$30);
2478
+ var _ref$1 = composerRef;
2479
+ typeof _ref$1 === "function" ? _$use(_ref$1, _el$84) : composerRef = _el$84;
2480
+ _$insert(_el$84, _$createComponent(Show, {
1867
2481
  get when() {
1868
2482
  return showHint();
1869
2483
  },
1870
2484
  get children() {
1871
- var _el$71 = _$getNextElement(_tmpl$21);
1872
- _$insert(_el$71, _$createComponent(Show, {
2485
+ var _el$85 = _$getNextElement(_tmpl$23);
2486
+ _$insert(_el$85, _$createComponent(Show, {
1873
2487
  get when() {
1874
2488
  return dictationStatus();
1875
2489
  },
1876
2490
  get fallback() {
1877
2491
  return (() => {
1878
- var _el$131 = _$getNextElement(_tmpl$31);
1879
- _$insert(_el$131, hint);
1880
- return _el$131;
2492
+ var _el$145 = _$getNextElement(_tmpl$33);
2493
+ _$insert(_el$145, hint);
2494
+ return _el$145;
1881
2495
  })();
1882
2496
  },
1883
2497
  children: status => [(() => {
1884
- var _el$132 = _$getNextElement(_tmpl$32),
1885
- _el$133 = _el$132.firstChild,
1886
- _el$134 = _el$133.nextSibling;
1887
- _$insert(_el$134, () => status().text);
2498
+ var _el$146 = _$getNextElement(_tmpl$34),
2499
+ _el$147 = _el$146.firstChild,
2500
+ _el$148 = _el$147.nextSibling;
2501
+ _$insert(_el$148, () => status().text);
1888
2502
  _$effect(_p$ => {
1889
- var _v$34 = dictation() ?? undefined,
1890
- _v$35 = status().icon;
1891
- _v$34 !== _p$.e && _$setAttribute(_el$132, "data-state", _p$.e = _v$34);
1892
- _v$35 !== _p$.t && _$className(_el$133, _p$.t = _v$35);
2503
+ var _v$44 = dictation() ?? undefined,
2504
+ _v$45 = status().icon;
2505
+ _v$44 !== _p$.e && _$setAttribute(_el$146, "data-state", _p$.e = _v$44);
2506
+ _v$45 !== _p$.t && _$className(_el$147, _p$.t = _v$45);
1893
2507
  return _p$;
1894
2508
  }, {
1895
2509
  e: undefined,
1896
2510
  t: undefined
1897
2511
  });
1898
- return _el$132;
2512
+ return _el$146;
1899
2513
  })(), _$createComponent(Show, {
1900
2514
  get when() {
1901
2515
  return _$memo(() => dictation() === "refined")() ? props.microphone?.onRestoreOriginal : undefined;
1902
2516
  },
1903
2517
  children: restore => (() => {
1904
- var _el$135 = _$getNextElement(_tmpl$33);
1905
- _el$135.$$click = () => reportChatFailure(restore(), props.onError);
1906
- _el$135.$$mousedown = keepFieldFocus;
1907
- _$insert(_el$135, () => chatMessages().restoreOriginal);
1908
- _$effect(() => _$setProperty(_el$135, "disabled", microphoneDisabled()));
2518
+ var _el$149 = _$getNextElement(_tmpl$35);
2519
+ _el$149.$$click = () => reportChatFailure(restore(), props.onError);
2520
+ _el$149.$$mousedown = keepFieldFocus;
2521
+ _$insert(_el$149, () => chatMessages().restoreOriginal);
2522
+ _$effect(() => _$setProperty(_el$149, "disabled", microphoneDisabled()));
1909
2523
  _$runHydrationEvents();
1910
- return _el$135;
2524
+ return _el$149;
1911
2525
  })()
1912
2526
  })]
1913
2527
  }));
1914
- return _el$71;
2528
+ return _el$85;
1915
2529
  }
1916
- }), _el$95, _co$21);
1917
- _$insert(_el$70, _$createComponent(Show, {
2530
+ }), _el$109, _co$24);
2531
+ _$insert(_el$84, _$createComponent(Show, {
1918
2532
  get when() {
1919
2533
  return attachments().length > 0;
1920
2534
  },
1921
2535
  get children() {
1922
- var _el$72 = _$getNextElement(_tmpl$22);
1923
- _$insert(_el$72, _$createComponent(For, {
2536
+ var _el$86 = _$getNextElement(_tmpl$24);
2537
+ _$insert(_el$86, _$createComponent(For, {
1924
2538
  get each() {
1925
2539
  return attachments();
1926
2540
  },
1927
2541
  children: attachment => (() => {
1928
- var _el$136 = _$getNextElement(_tmpl$35),
1929
- _el$137 = _el$136.firstChild,
1930
- _el$138 = _el$137.firstChild,
1931
- [_el$139, _co$33] = _$getNextMarker(_el$138.nextSibling),
1932
- _el$140 = _el$139.nextSibling,
1933
- [_el$141, _co$34] = _$getNextMarker(_el$140.nextSibling),
1934
- _el$143 = _el$137.nextSibling,
1935
- [_el$144, _co$35] = _$getNextMarker(_el$143.nextSibling);
1936
- _$insert(_el$137, _$createComponent(Show, {
2542
+ var _el$150 = _$getNextElement(_tmpl$37),
2543
+ _el$151 = _el$150.firstChild,
2544
+ _el$152 = _el$151.firstChild,
2545
+ [_el$153, _co$36] = _$getNextMarker(_el$152.nextSibling),
2546
+ _el$154 = _el$153.nextSibling,
2547
+ [_el$155, _co$37] = _$getNextMarker(_el$154.nextSibling),
2548
+ _el$157 = _el$151.nextSibling,
2549
+ [_el$158, _co$38] = _$getNextMarker(_el$157.nextSibling);
2550
+ _$insert(_el$151, _$createComponent(Show, {
1937
2551
  get when() {
1938
2552
  return attachment.href;
1939
2553
  },
1940
2554
  get fallback() {
1941
2555
  return (() => {
1942
- var _el$145 = _$getNextElement(_tmpl$37),
1943
- _el$147 = _el$145.firstChild,
1944
- [_el$148, _co$36] = _$getNextMarker(_el$147.nextSibling),
1945
- _el$149 = _el$148.nextSibling,
1946
- [_el$150, _co$37] = _$getNextMarker(_el$149.nextSibling);
1947
- _$insert(_el$145, _$createComponent(Show, {
2556
+ var _el$159 = _$getNextElement(_tmpl$39),
2557
+ _el$161 = _el$159.firstChild,
2558
+ [_el$162, _co$39] = _$getNextMarker(_el$161.nextSibling),
2559
+ _el$163 = _el$162.nextSibling,
2560
+ [_el$164, _co$40] = _$getNextMarker(_el$163.nextSibling);
2561
+ _$insert(_el$159, _$createComponent(Show, {
1948
2562
  get when() {
1949
2563
  return _$memo(() => attachment.kind === "image")() && attachment.previewUrl;
1950
2564
  },
1951
2565
  get fallback() {
1952
2566
  return (() => {
1953
- var _el$151 = _$getNextElement(_tmpl$3);
1954
- _$effect(() => _$className(_el$151, attachmentIcon(attachment)));
1955
- return _el$151;
2567
+ var _el$165 = _$getNextElement(_tmpl$3);
2568
+ _$effect(() => _$className(_el$165, attachmentIcon(attachment)));
2569
+ return _el$165;
1956
2570
  })();
1957
2571
  },
1958
2572
  get children() {
1959
- var _el$146 = _$getNextElement(_tmpl$36);
2573
+ var _el$160 = _$getNextElement(_tmpl$38);
1960
2574
  _$effect(_p$ => {
1961
- var _v$38 = attachment.previewUrl,
1962
- _v$39 = attachment.alt ?? "";
1963
- _v$38 !== _p$.e && _$setAttribute(_el$146, "src", _p$.e = _v$38);
1964
- _v$39 !== _p$.t && _$setAttribute(_el$146, "alt", _p$.t = _v$39);
2575
+ var _v$48 = attachment.previewUrl,
2576
+ _v$49 = attachment.alt ?? "";
2577
+ _v$48 !== _p$.e && _$setAttribute(_el$160, "src", _p$.e = _v$48);
2578
+ _v$49 !== _p$.t && _$setAttribute(_el$160, "alt", _p$.t = _v$49);
1965
2579
  return _p$;
1966
2580
  }, {
1967
2581
  e: undefined,
1968
2582
  t: undefined
1969
2583
  });
1970
- return _el$146;
2584
+ return _el$160;
1971
2585
  }
1972
- }), _el$148, _co$36);
1973
- _$insert(_el$145, () => renderAttachmentCopy(attachment), _el$150, _co$37);
1974
- return _el$145;
2586
+ }), _el$162, _co$39);
2587
+ _$insert(_el$159, () => renderAttachmentCopy(attachment), _el$164, _co$40);
2588
+ return _el$159;
1975
2589
  })();
1976
2590
  },
1977
2591
  children: href => (() => {
1978
- var _el$152 = _$getNextElement(_tmpl$38),
1979
- _el$154 = _el$152.firstChild,
1980
- [_el$155, _co$38] = _$getNextMarker(_el$154.nextSibling),
1981
- _el$156 = _el$155.nextSibling,
1982
- [_el$157, _co$39] = _$getNextMarker(_el$156.nextSibling);
1983
- _$insert(_el$152, _$createComponent(Show, {
2592
+ var _el$166 = _$getNextElement(_tmpl$40),
2593
+ _el$168 = _el$166.firstChild,
2594
+ [_el$169, _co$41] = _$getNextMarker(_el$168.nextSibling),
2595
+ _el$170 = _el$169.nextSibling,
2596
+ [_el$171, _co$42] = _$getNextMarker(_el$170.nextSibling);
2597
+ _$insert(_el$166, _$createComponent(Show, {
1984
2598
  get when() {
1985
2599
  return _$memo(() => attachment.kind === "image")() && attachment.previewUrl;
1986
2600
  },
1987
2601
  get fallback() {
1988
2602
  return (() => {
1989
- var _el$158 = _$getNextElement(_tmpl$3);
1990
- _$effect(() => _$className(_el$158, attachmentIcon(attachment)));
1991
- return _el$158;
2603
+ var _el$172 = _$getNextElement(_tmpl$3);
2604
+ _$effect(() => _$className(_el$172, attachmentIcon(attachment)));
2605
+ return _el$172;
1992
2606
  })();
1993
2607
  },
1994
2608
  get children() {
1995
- var _el$153 = _$getNextElement(_tmpl$36);
2609
+ var _el$167 = _$getNextElement(_tmpl$38);
1996
2610
  _$effect(_p$ => {
1997
- var _v$40 = attachment.previewUrl,
1998
- _v$41 = attachment.alt ?? "";
1999
- _v$40 !== _p$.e && _$setAttribute(_el$153, "src", _p$.e = _v$40);
2000
- _v$41 !== _p$.t && _$setAttribute(_el$153, "alt", _p$.t = _v$41);
2611
+ var _v$50 = attachment.previewUrl,
2612
+ _v$51 = attachment.alt ?? "";
2613
+ _v$50 !== _p$.e && _$setAttribute(_el$167, "src", _p$.e = _v$50);
2614
+ _v$51 !== _p$.t && _$setAttribute(_el$167, "alt", _p$.t = _v$51);
2001
2615
  return _p$;
2002
2616
  }, {
2003
2617
  e: undefined,
2004
2618
  t: undefined
2005
2619
  });
2006
- return _el$153;
2620
+ return _el$167;
2007
2621
  }
2008
- }), _el$155, _co$38);
2009
- _$insert(_el$152, () => renderAttachmentCopy(attachment), _el$157, _co$39);
2622
+ }), _el$169, _co$41);
2623
+ _$insert(_el$166, () => renderAttachmentCopy(attachment), _el$171, _co$42);
2010
2624
  _$effect(_p$ => {
2011
- var _v$42 = href(),
2012
- _v$43 = chatMessages().openInNewTab({
2625
+ var _v$52 = href(),
2626
+ _v$53 = chatMessages().openInNewTab({
2013
2627
  name: attachment.name
2014
2628
  });
2015
- _v$42 !== _p$.e && _$setAttribute(_el$152, "href", _p$.e = _v$42);
2016
- _v$43 !== _p$.t && _$setAttribute(_el$152, "aria-label", _p$.t = _v$43);
2629
+ _v$52 !== _p$.e && _$setAttribute(_el$166, "href", _p$.e = _v$52);
2630
+ _v$53 !== _p$.t && _$setAttribute(_el$166, "aria-label", _p$.t = _v$53);
2017
2631
  return _p$;
2018
2632
  }, {
2019
2633
  e: undefined,
2020
2634
  t: undefined
2021
2635
  });
2022
- return _el$152;
2636
+ return _el$166;
2023
2637
  })()
2024
- }), _el$139, _co$33);
2025
- _$insert(_el$137, _$createComponent(Show, {
2638
+ }), _el$153, _co$36);
2639
+ _$insert(_el$151, _$createComponent(Show, {
2026
2640
  get when() {
2027
2641
  return attachment.action;
2028
2642
  },
2029
2643
  children: action => (() => {
2030
- var _el$159 = _$getNextElement(_tmpl$39),
2031
- _el$160 = _el$159.firstChild,
2032
- [_el$161, _co$40] = _$getNextMarker(_el$160.nextSibling),
2033
- _el$162 = _el$161.nextSibling,
2034
- [_el$163, _co$41] = _$getNextMarker(_el$162.nextSibling);
2035
- _el$159.$$click = () => reportChatFailure(() => executeChatAction(action()), props.onError);
2036
- _$insert(_el$159, _$createComponent(Show, {
2644
+ var _el$173 = _$getNextElement(_tmpl$41),
2645
+ _el$174 = _el$173.firstChild,
2646
+ [_el$175, _co$43] = _$getNextMarker(_el$174.nextSibling),
2647
+ _el$176 = _el$175.nextSibling,
2648
+ [_el$177, _co$44] = _$getNextMarker(_el$176.nextSibling);
2649
+ _el$173.$$click = () => reportChatFailure(() => executeChatAction(action()), props.onError);
2650
+ _$insert(_el$173, _$createComponent(Show, {
2037
2651
  get when() {
2038
2652
  return action().icon;
2039
2653
  },
2040
2654
  children: icon => (() => {
2041
- var _el$164 = _$getNextElement(_tmpl$3);
2042
- _$effect(() => _$className(_el$164, icon()));
2043
- return _el$164;
2655
+ var _el$178 = _$getNextElement(_tmpl$3);
2656
+ _$effect(() => _$className(_el$178, icon()));
2657
+ return _el$178;
2044
2658
  })()
2045
- }), _el$161, _co$40);
2046
- _$insert(_el$159, () => action().label, _el$163, _co$41);
2047
- _$effect(() => _$setProperty(_el$159, "disabled", blocked() || action().disabled));
2659
+ }), _el$175, _co$43);
2660
+ _$insert(_el$173, () => action().label, _el$177, _co$44);
2661
+ _$effect(() => _$setProperty(_el$173, "disabled", blocked() || action().disabled));
2048
2662
  _$runHydrationEvents();
2049
- return _el$159;
2663
+ return _el$173;
2050
2664
  })()
2051
- }), _el$141, _co$34);
2052
- _$insert(_el$136, _$createComponent(Show, {
2665
+ }), _el$155, _co$37);
2666
+ _$insert(_el$150, _$createComponent(Show, {
2053
2667
  get when() {
2054
2668
  return props.onAttachmentsChange;
2055
2669
  },
2056
2670
  get children() {
2057
- var _el$142 = _$getNextElement(_tmpl$34);
2058
- _el$142.$$click = () => setAttachments(attachments().filter(candidate => candidate.id !== attachment.id));
2671
+ var _el$156 = _$getNextElement(_tmpl$36);
2672
+ _el$156.$$click = () => setAttachments(attachments().filter(candidate => candidate.id !== attachment.id));
2059
2673
  _$effect(_p$ => {
2060
- var _v$36 = selectMessages().removeNamed({
2674
+ var _v$46 = selectMessages().removeNamed({
2061
2675
  name: attachment.name
2062
2676
  }),
2063
- _v$37 = blocked();
2064
- _v$36 !== _p$.e && _$setAttribute(_el$142, "aria-label", _p$.e = _v$36);
2065
- _v$37 !== _p$.t && _$setProperty(_el$142, "disabled", _p$.t = _v$37);
2677
+ _v$47 = blocked();
2678
+ _v$46 !== _p$.e && _$setAttribute(_el$156, "aria-label", _p$.e = _v$46);
2679
+ _v$47 !== _p$.t && _$setProperty(_el$156, "disabled", _p$.t = _v$47);
2066
2680
  return _p$;
2067
2681
  }, {
2068
2682
  e: undefined,
2069
2683
  t: undefined
2070
2684
  });
2071
2685
  _$runHydrationEvents();
2072
- return _el$142;
2686
+ return _el$156;
2073
2687
  }
2074
- }), _el$144, _co$35);
2075
- _$effect(() => _el$137.classList.toggle("k2b-chat-composer__attachment-content--action", !!Boolean(attachment.action)));
2076
- return _el$136;
2688
+ }), _el$158, _co$38);
2689
+ _$effect(() => _el$151.classList.toggle("k2b-chat-composer__attachment-content--action", !!Boolean(attachment.action)));
2690
+ return _el$150;
2077
2691
  })()
2078
2692
  }));
2079
- _$effect(() => _$setAttribute(_el$72, "aria-label", chatMessages().attachments));
2080
- return _el$72;
2693
+ _$effect(() => _$setAttribute(_el$86, "aria-label", chatMessages().attachments));
2694
+ return _el$86;
2081
2695
  }
2082
- }), _el$97, _co$22);
2083
- _$insert(_el$70, _$createComponent(Show, {
2696
+ }), _el$111, _co$25);
2697
+ _$insert(_el$84, _$createComponent(Show, {
2084
2698
  get when() {
2085
2699
  return conversation();
2086
2700
  },
@@ -2090,49 +2704,59 @@ export function ChatComposer(props) {
2090
2704
  return props.error;
2091
2705
  },
2092
2706
  get children() {
2093
- var _el$165 = _$getNextElement(_tmpl$23),
2094
- _el$166 = _el$165.firstChild,
2095
- _el$167 = _el$166.nextSibling,
2096
- [_el$168, _co$42] = _$getNextMarker(_el$167.nextSibling);
2097
- _$insert(_el$165, () => props.error, _el$168, _co$42);
2098
- return _el$165;
2707
+ var _el$179 = _$getNextElement(_tmpl$25),
2708
+ _el$180 = _el$179.firstChild,
2709
+ _el$181 = _el$180.nextSibling,
2710
+ [_el$182, _co$45] = _$getNextMarker(_el$181.nextSibling);
2711
+ _$insert(_el$179, () => props.error, _el$182, _co$45);
2712
+ return _el$179;
2099
2713
  }
2100
2714
  }), _$memo(formatRow), (() => {
2101
- var _el$169 = _$getNextElement(_tmpl$40);
2102
- _$insert(_el$169, _$createComponent(Show, {
2715
+ var _el$183 = _$getNextElement(_tmpl$42);
2716
+ _$insert(_el$183, _$createComponent(Show, {
2103
2717
  get when() {
2104
2718
  return footer();
2105
2719
  },
2106
2720
  get fallback() {
2107
2721
  return [(() => {
2108
- var _el$170 = _$getNextElement(_tmpl$41),
2109
- _el$171 = _el$170.firstChild,
2110
- [_el$172, _co$43] = _$getNextMarker(_el$171.nextSibling),
2111
- _el$173 = _el$172.nextSibling,
2112
- [_el$174, _co$44] = _$getNextMarker(_el$173.nextSibling),
2113
- _el$175 = _el$174.nextSibling,
2114
- [_el$176, _co$45] = _$getNextMarker(_el$175.nextSibling),
2115
- _el$177 = _el$176.nextSibling,
2116
- [_el$178, _co$46] = _$getNextMarker(_el$177.nextSibling),
2117
- _el$179 = _el$178.nextSibling,
2118
- [_el$180, _co$47] = _$getNextMarker(_el$179.nextSibling),
2119
- _el$181 = _el$180.nextSibling,
2120
- [_el$182, _co$48] = _$getNextMarker(_el$181.nextSibling),
2121
- _el$183 = _el$182.nextSibling,
2122
- [_el$184, _co$49] = _$getNextMarker(_el$183.nextSibling);
2123
- _$insert(_el$170, () => props.footerTools, _el$172, _co$43);
2124
- _$insert(_el$170, _$createComponent(Show, {
2722
+ var _el$184 = _$getNextElement(_tmpl$43),
2723
+ _el$185 = _el$184.firstChild,
2724
+ [_el$186, _co$46] = _$getNextMarker(_el$185.nextSibling),
2725
+ _el$187 = _el$186.nextSibling,
2726
+ [_el$188, _co$47] = _$getNextMarker(_el$187.nextSibling),
2727
+ _el$189 = _el$188.nextSibling,
2728
+ [_el$190, _co$48] = _$getNextMarker(_el$189.nextSibling),
2729
+ _el$191 = _el$190.nextSibling,
2730
+ [_el$192, _co$49] = _$getNextMarker(_el$191.nextSibling),
2731
+ _el$193 = _el$192.nextSibling,
2732
+ [_el$194, _co$50] = _$getNextMarker(_el$193.nextSibling),
2733
+ _el$195 = _el$194.nextSibling,
2734
+ [_el$196, _co$51] = _$getNextMarker(_el$195.nextSibling),
2735
+ _el$197 = _el$196.nextSibling,
2736
+ [_el$198, _co$52] = _$getNextMarker(_el$197.nextSibling);
2737
+ _$insert(_el$184, () => props.footerTools, _el$186, _co$46);
2738
+ _$insert(_el$184, _$createComponent(Show, {
2125
2739
  get when() {
2126
- return hasAddMenu();
2740
+ return addOpensCommands();
2741
+ },
2742
+ get fallback() {
2743
+ return _$createComponent(Show, {
2744
+ get when() {
2745
+ return hasAddMenu();
2746
+ },
2747
+ get children() {
2748
+ return addMenu("ti ti-plus");
2749
+ }
2750
+ });
2127
2751
  },
2128
2752
  get children() {
2129
- return addMenu("ti ti-plus");
2753
+ return addSearchButton();
2130
2754
  }
2131
- }), _el$174, _co$44);
2132
- _$insert(_el$170, fileInput, _el$176, _co$45);
2133
- _$insert(_el$170, formatToggle, _el$178, _co$46);
2134
- _$insert(_el$170, emojiButton, _el$180, _co$47);
2135
- _$insert(_el$170, _$createComponent(Show, {
2755
+ }), _el$188, _co$47);
2756
+ _$insert(_el$184, fileInput, _el$190, _co$48);
2757
+ _$insert(_el$184, formatToggle, _el$192, _co$49);
2758
+ _$insert(_el$184, emojiButton, _el$194, _co$50);
2759
+ _$insert(_el$184, _$createComponent(Show, {
2136
2760
  get when() {
2137
2761
  return (props.models?.length ?? 0) > 0;
2138
2762
  },
@@ -2178,22 +2802,22 @@ export function ChatComposer(props) {
2178
2802
  }
2179
2803
  });
2180
2804
  }
2181
- }), _el$182, _co$48);
2182
- _$insert(_el$170, () => props.modelDetails, _el$184, _co$49);
2183
- return _el$170;
2805
+ }), _el$196, _co$51);
2806
+ _$insert(_el$184, () => props.modelDetails, _el$198, _co$52);
2807
+ return _el$184;
2184
2808
  })(), (() => {
2185
- var _el$185 = _$getNextElement(_tmpl$42),
2186
- _el$186 = _el$185.firstChild,
2187
- [_el$187, _co$50] = _$getNextMarker(_el$186.nextSibling),
2188
- _el$188 = _el$187.nextSibling,
2189
- [_el$189, _co$51] = _$getNextMarker(_el$188.nextSibling),
2190
- _el$190 = _el$189.nextSibling,
2191
- [_el$191, _co$52] = _$getNextMarker(_el$190.nextSibling),
2192
- _el$192 = _el$191.nextSibling,
2193
- [_el$193, _co$53] = _$getNextMarker(_el$192.nextSibling),
2194
- _el$194 = _el$193.nextSibling,
2195
- [_el$195, _co$54] = _$getNextMarker(_el$194.nextSibling);
2196
- _$insert(_el$185, _$createComponent(For, {
2809
+ var _el$199 = _$getNextElement(_tmpl$44),
2810
+ _el$200 = _el$199.firstChild,
2811
+ [_el$201, _co$53] = _$getNextMarker(_el$200.nextSibling),
2812
+ _el$202 = _el$201.nextSibling,
2813
+ [_el$203, _co$54] = _$getNextMarker(_el$202.nextSibling),
2814
+ _el$204 = _el$203.nextSibling,
2815
+ [_el$205, _co$55] = _$getNextMarker(_el$204.nextSibling),
2816
+ _el$206 = _el$205.nextSibling,
2817
+ [_el$207, _co$56] = _$getNextMarker(_el$206.nextSibling),
2818
+ _el$208 = _el$207.nextSibling,
2819
+ [_el$209, _co$57] = _$getNextMarker(_el$208.nextSibling);
2820
+ _$insert(_el$199, _$createComponent(For, {
2197
2821
  get each() {
2198
2822
  return props.contextActions;
2199
2823
  },
@@ -2217,13 +2841,13 @@ export function ChatComposer(props) {
2217
2841
  },
2218
2842
  onClick: () => reportChatFailure(() => executeChatAction(action), props.onError),
2219
2843
  get children() {
2220
- var _el$196 = _$getNextElement(_tmpl$3);
2221
- _$effect(() => _$className(_el$196, action.icon ?? "ti ti-dots"));
2222
- return _el$196;
2844
+ var _el$210 = _$getNextElement(_tmpl$3);
2845
+ _$effect(() => _$className(_el$210, action.icon ?? "ti ti-dots"));
2846
+ return _el$210;
2223
2847
  }
2224
2848
  })
2225
- }), _el$187, _co$50);
2226
- _$insert(_el$185, _$createComponent(Show, {
2849
+ }), _el$201, _co$53);
2850
+ _$insert(_el$199, _$createComponent(Show, {
2227
2851
  get when() {
2228
2852
  return _$memo(() => !!hasContextUsage())() ? props.contextUsage ?? {} : undefined;
2229
2853
  },
@@ -2235,18 +2859,18 @@ export function ChatComposer(props) {
2235
2859
  return props.onError;
2236
2860
  }
2237
2861
  }))
2238
- }), _el$189, _co$51);
2239
- _$insert(_el$185, () => props.submitTools, _el$191, _co$52);
2240
- _$insert(_el$185, microphoneControl, _el$193, _co$53);
2241
- _$insert(_el$185, sendControl, _el$195, _co$54);
2242
- return _el$185;
2862
+ }), _el$203, _co$54);
2863
+ _$insert(_el$199, () => props.submitTools, _el$205, _co$55);
2864
+ _$insert(_el$199, microphoneControl, _el$207, _co$56);
2865
+ _$insert(_el$199, sendControl, _el$209, _co$57);
2866
+ return _el$199;
2243
2867
  })()];
2244
2868
  },
2245
2869
  get children() {
2246
2870
  return footer();
2247
2871
  }
2248
2872
  }));
2249
- return _el$169;
2873
+ return _el$183;
2250
2874
  })()];
2251
2875
  },
2252
2876
  get children() {
@@ -2255,43 +2879,43 @@ export function ChatComposer(props) {
2255
2879
  return props.error;
2256
2880
  },
2257
2881
  get children() {
2258
- var _el$73 = _$getNextElement(_tmpl$23),
2259
- _el$74 = _el$73.firstChild,
2260
- _el$75 = _el$74.nextSibling,
2261
- [_el$76, _co$13] = _$getNextMarker(_el$75.nextSibling);
2262
- _$insert(_el$73, () => props.error, _el$76, _co$13);
2263
- return _el$73;
2882
+ var _el$87 = _$getNextElement(_tmpl$25),
2883
+ _el$88 = _el$87.firstChild,
2884
+ _el$89 = _el$88.nextSibling,
2885
+ [_el$90, _co$16] = _$getNextMarker(_el$89.nextSibling);
2886
+ _$insert(_el$87, () => props.error, _el$90, _co$16);
2887
+ return _el$87;
2264
2888
  }
2265
2889
  }), _$memo(() => formatRow()), (() => {
2266
- var _el$77 = _$getNextElement(_tmpl$24),
2267
- _el$88 = _el$77.firstChild,
2268
- [_el$89, _co$18] = _$getNextMarker(_el$88.nextSibling),
2269
- _el$90 = _el$89.nextSibling,
2270
- [_el$91, _co$19] = _$getNextMarker(_el$90.nextSibling),
2271
- _el$78 = _el$91.nextSibling,
2272
- _el$86 = _el$78.firstChild,
2273
- [_el$87, _co$17] = _$getNextMarker(_el$86.nextSibling),
2274
- _el$79 = _el$87.nextSibling,
2275
- _el$80 = _el$79.firstChild,
2276
- [_el$81, _co$14] = _$getNextMarker(_el$80.nextSibling),
2277
- _el$82 = _el$81.nextSibling,
2278
- [_el$83, _co$15] = _$getNextMarker(_el$82.nextSibling),
2279
- _el$84 = _el$83.nextSibling,
2280
- [_el$85, _co$16] = _$getNextMarker(_el$84.nextSibling),
2281
- _el$92 = _el$78.nextSibling,
2282
- [_el$93, _co$20] = _$getNextMarker(_el$92.nextSibling);
2283
- _$insert(_el$77, attachControl, _el$89, _co$18);
2284
- _$insert(_el$77, fileInput, _el$91, _co$19);
2285
- _$insert(_el$78, field, _el$87, _co$17);
2286
- _$insert(_el$79, formatToggle, _el$81, _co$14);
2287
- _$insert(_el$79, emojiButton, _el$83, _co$15);
2288
- _$insert(_el$79, microphoneControl, _el$85, _co$16);
2289
- _$insert(_el$77, sendControl, _el$93, _co$20);
2290
- return _el$77;
2890
+ var _el$91 = _$getNextElement(_tmpl$26),
2891
+ _el$102 = _el$91.firstChild,
2892
+ [_el$103, _co$21] = _$getNextMarker(_el$102.nextSibling),
2893
+ _el$104 = _el$103.nextSibling,
2894
+ [_el$105, _co$22] = _$getNextMarker(_el$104.nextSibling),
2895
+ _el$92 = _el$105.nextSibling,
2896
+ _el$100 = _el$92.firstChild,
2897
+ [_el$101, _co$20] = _$getNextMarker(_el$100.nextSibling),
2898
+ _el$93 = _el$101.nextSibling,
2899
+ _el$94 = _el$93.firstChild,
2900
+ [_el$95, _co$17] = _$getNextMarker(_el$94.nextSibling),
2901
+ _el$96 = _el$95.nextSibling,
2902
+ [_el$97, _co$18] = _$getNextMarker(_el$96.nextSibling),
2903
+ _el$98 = _el$97.nextSibling,
2904
+ [_el$99, _co$19] = _$getNextMarker(_el$98.nextSibling),
2905
+ _el$106 = _el$92.nextSibling,
2906
+ [_el$107, _co$23] = _$getNextMarker(_el$106.nextSibling);
2907
+ _$insert(_el$91, attachControl, _el$103, _co$21);
2908
+ _$insert(_el$91, fileInput, _el$105, _co$22);
2909
+ _$insert(_el$92, field, _el$101, _co$20);
2910
+ _$insert(_el$93, formatToggle, _el$95, _co$17);
2911
+ _$insert(_el$93, emojiButton, _el$97, _co$18);
2912
+ _$insert(_el$93, microphoneControl, _el$99, _co$19);
2913
+ _$insert(_el$91, sendControl, _el$107, _co$23);
2914
+ return _el$91;
2291
2915
  })()];
2292
2916
  }
2293
- }), _el$99, _co$23);
2294
- _$insert(_el$70, _$createComponent(Show, {
2917
+ }), _el$113, _co$26);
2918
+ _$insert(_el$84, _$createComponent(Show, {
2295
2919
  get when() {
2296
2920
  return props.fileSelection;
2297
2921
  },
@@ -2310,60 +2934,60 @@ export function ChatComposer(props) {
2310
2934
  },
2311
2935
  onDrop: files => void runFiles(files)
2312
2936
  })
2313
- }), _el$101, _co$24);
2314
- _$insert(_el$102, _$createComponent(Show, {
2937
+ }), _el$115, _co$27);
2938
+ _$insert(_el$116, _$createComponent(Show, {
2315
2939
  get when() {
2316
2940
  return suggestionAnnouncement();
2317
2941
  },
2318
2942
  keyed: true,
2319
2943
  children: announced => (() => {
2320
- var _el$197 = _$getNextElement(_tmpl$10);
2321
- _$insert(_el$197, () => announced.text);
2322
- return _el$197;
2944
+ var _el$211 = _$getNextElement(_tmpl$10);
2945
+ _$insert(_el$211, () => announced.text);
2946
+ return _el$211;
2323
2947
  })()
2324
2948
  }));
2325
- _$insert(_el$103, _$createComponent(Show, {
2949
+ _$insert(_el$117, _$createComponent(Show, {
2326
2950
  get when() {
2327
2951
  return _$memo(() => !!!suggestionsOpen())() && commandStatus();
2328
2952
  },
2329
2953
  children: status => (() => {
2330
- var _el$198 = _$getNextElement(_tmpl$43),
2331
- _el$199 = _el$198.firstChild,
2332
- _el$200 = _el$199.nextSibling;
2333
- _$insert(_el$200, () => status().text);
2954
+ var _el$212 = _$getNextElement(_tmpl$45),
2955
+ _el$213 = _el$212.firstChild,
2956
+ _el$214 = _el$213.nextSibling;
2957
+ _$insert(_el$214, () => status().text);
2334
2958
  _$effect(_p$ => {
2335
- var _v$44 = status().tone,
2336
- _v$45 = status().tone === "busy" ? "ti ti-loader-2 k2b-spin" : status().tone === "done" ? "ti ti-check" : "ti ti-alert-circle";
2337
- _v$44 !== _p$.e && _$setAttribute(_el$198, "data-tone", _p$.e = _v$44);
2338
- _v$45 !== _p$.t && _$className(_el$199, _p$.t = _v$45);
2959
+ var _v$54 = status().tone,
2960
+ _v$55 = status().tone === "busy" ? "ti ti-loader-2 k2b-spin" : status().tone === "done" ? "ti ti-check" : "ti ti-alert-circle";
2961
+ _v$54 !== _p$.e && _$setAttribute(_el$212, "data-tone", _p$.e = _v$54);
2962
+ _v$55 !== _p$.t && _$className(_el$213, _p$.t = _v$55);
2339
2963
  return _p$;
2340
2964
  }, {
2341
2965
  e: undefined,
2342
2966
  t: undefined
2343
2967
  });
2344
- return _el$198;
2968
+ return _el$212;
2345
2969
  })()
2346
- }), _el$105, _co$25);
2347
- _$insert(_el$103, _$createComponent(Show, {
2970
+ }), _el$119, _co$28);
2971
+ _$insert(_el$117, _$createComponent(Show, {
2348
2972
  get when() {
2349
2973
  return _$memo(() => !!suggestionsOpen())() && announcement();
2350
2974
  },
2351
2975
  keyed: true,
2352
2976
  children: announced => (() => {
2353
- var _el$201 = _$getNextElement(_tmpl$44);
2354
- _$insert(_el$201, () => announced.text);
2355
- return _el$201;
2977
+ var _el$215 = _$getNextElement(_tmpl$46);
2978
+ _$insert(_el$215, () => announced.text);
2979
+ return _el$215;
2356
2980
  })()
2357
- }), _el$107, _co$26);
2981
+ }), _el$121, _co$29);
2358
2982
  _$effect(_p$ => {
2359
- var _v$24 = `k2b-chat-composer ${props.class ?? ""}`,
2360
- _v$25 = running() ? "true" : undefined,
2361
- _v$26 = conversation() ? "conversation" : undefined,
2362
- _v$27 = props.label ?? chatMessages().messageComposer;
2363
- _v$24 !== _p$.e && _$className(_el$70, _p$.e = _v$24);
2364
- _v$25 !== _p$.t && _$setAttribute(_el$70, "data-running", _p$.t = _v$25);
2365
- _v$26 !== _p$.a && _$setAttribute(_el$70, "data-variant", _p$.a = _v$26);
2366
- _v$27 !== _p$.o && _$setAttribute(_el$70, "aria-label", _p$.o = _v$27);
2983
+ var _v$34 = `k2b-chat-composer ${props.class ?? ""}`,
2984
+ _v$35 = running() ? "true" : undefined,
2985
+ _v$36 = conversation() ? "conversation" : undefined,
2986
+ _v$37 = props.label ?? chatMessages().messageComposer;
2987
+ _v$34 !== _p$.e && _$className(_el$84, _p$.e = _v$34);
2988
+ _v$35 !== _p$.t && _$setAttribute(_el$84, "data-running", _p$.t = _v$35);
2989
+ _v$36 !== _p$.a && _$setAttribute(_el$84, "data-variant", _p$.a = _v$36);
2990
+ _v$37 !== _p$.o && _$setAttribute(_el$84, "aria-label", _p$.o = _v$37);
2367
2991
  return _p$;
2368
2992
  }, {
2369
2993
  e: undefined,
@@ -2371,8 +2995,8 @@ export function ChatComposer(props) {
2371
2995
  a: undefined,
2372
2996
  o: undefined
2373
2997
  });
2374
- return _el$42;
2998
+ return _el$49;
2375
2999
  })();
2376
3000
  }
2377
- _$delegateEvents(["input", "click", "keyup", "beforeinput", "keydown", "mousedown"]);
3001
+ _$delegateEvents(["input", "click", "keyup", "beforeinput", "keydown", "mousedown", "focusout"]);
2378
3002
  //# sourceMappingURL=ChatComposer.js.map