@oxy.so/bloom 5.1.0 → 5.2.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 (502) hide show
  1. package/docs/adoption-matrix.mdx +9 -9
  2. package/docs/app-shell.mdx +3 -1
  3. package/docs/button.mdx +2 -0
  4. package/docs/card-form.mdx +2 -0
  5. package/docs/chat-composer.mdx +1 -1
  6. package/docs/chat-people.mdx +8 -0
  7. package/docs/earnings.mdx +2 -0
  8. package/docs/field.mdx +2 -0
  9. package/docs/label.mdx +2 -0
  10. package/docs/payment-method.mdx +2 -0
  11. package/docs/place-details.mdx +2 -2
  12. package/docs/proof-of-delivery.mdx +4 -0
  13. package/docs/select.mdx +2 -0
  14. package/docs/settings-modal.mdx +15 -0
  15. package/lib/commonjs/ai-chat/AiChatResizeHandle.js +166 -0
  16. package/lib/commonjs/ai-chat/AiChatResizeHandle.js.map +1 -0
  17. package/lib/commonjs/ai-chat/AiChatShell.js +6 -154
  18. package/lib/commonjs/ai-chat/AiChatShell.js.map +1 -1
  19. package/lib/commonjs/ai-chat/index.js +2 -1
  20. package/lib/commonjs/ai-chat/index.js.map +1 -1
  21. package/lib/commonjs/ai-chat/index.web.js +2 -1
  22. package/lib/commonjs/ai-chat/index.web.js.map +1 -1
  23. package/lib/commonjs/ai-chat/messages.js +15 -30
  24. package/lib/commonjs/ai-chat/messages.js.map +1 -1
  25. package/lib/commonjs/app-shell/AppShellSplit.js +2 -2
  26. package/lib/commonjs/app-shell/AppShellSplit.js.map +1 -1
  27. package/lib/commonjs/button/Button.js +36 -3
  28. package/lib/commonjs/button/Button.js.map +1 -1
  29. package/lib/commonjs/button/GlyphButton.js +7 -3
  30. package/lib/commonjs/button/GlyphButton.js.map +1 -1
  31. package/lib/commonjs/card-form/shared.js +3 -2
  32. package/lib/commonjs/card-form/shared.js.map +1 -1
  33. package/lib/commonjs/chat-composer/AttachmentMenu.js +8 -227
  34. package/lib/commonjs/chat-composer/AttachmentMenu.js.map +1 -1
  35. package/lib/commonjs/chat-composer/AttachmentMenu.web.js +16 -0
  36. package/lib/commonjs/chat-composer/AttachmentMenu.web.js.map +1 -0
  37. package/lib/commonjs/chat-composer/ChatComposer.js +9 -388
  38. package/lib/commonjs/chat-composer/ChatComposer.js.map +1 -1
  39. package/lib/commonjs/chat-composer/ChatComposer.web.js +16 -0
  40. package/lib/commonjs/chat-composer/ChatComposer.web.js.map +1 -0
  41. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.js +5 -200
  42. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.js.map +1 -1
  43. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.web.js +12 -0
  44. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.web.js.map +1 -0
  45. package/lib/commonjs/chat-composer/ComposerBanner.js +5 -163
  46. package/lib/commonjs/chat-composer/ComposerBanner.js.map +1 -1
  47. package/lib/commonjs/chat-composer/ComposerBanner.web.js +12 -0
  48. package/lib/commonjs/chat-composer/ComposerBanner.web.js.map +1 -0
  49. package/lib/commonjs/chat-composer/EmojiPicker.js +6 -443
  50. package/lib/commonjs/chat-composer/EmojiPicker.js.map +1 -1
  51. package/lib/commonjs/chat-composer/EmojiPicker.web.js +14 -0
  52. package/lib/commonjs/chat-composer/EmojiPicker.web.js.map +1 -0
  53. package/lib/commonjs/chat-composer/MessageContextMenu.js +12 -102
  54. package/lib/commonjs/chat-composer/MessageContextMenu.js.map +1 -1
  55. package/lib/commonjs/chat-composer/MessageContextMenu.web.js +19 -0
  56. package/lib/commonjs/chat-composer/MessageContextMenu.web.js.map +1 -0
  57. package/lib/commonjs/chat-composer/ReactionPicker.js +6 -107
  58. package/lib/commonjs/chat-composer/ReactionPicker.js.map +1 -1
  59. package/lib/commonjs/chat-composer/ReactionPicker.web.js +14 -0
  60. package/lib/commonjs/chat-composer/ReactionPicker.web.js.map +1 -0
  61. package/lib/commonjs/chat-composer/SuggestionList.js +5 -222
  62. package/lib/commonjs/chat-composer/SuggestionList.js.map +1 -1
  63. package/lib/commonjs/chat-composer/SuggestionList.web.js +12 -0
  64. package/lib/commonjs/chat-composer/SuggestionList.web.js.map +1 -0
  65. package/lib/commonjs/chat-composer/VoiceRecorder.js +7 -263
  66. package/lib/commonjs/chat-composer/VoiceRecorder.js.map +1 -1
  67. package/lib/commonjs/chat-composer/VoiceRecorder.web.js +16 -0
  68. package/lib/commonjs/chat-composer/VoiceRecorder.web.js.map +1 -0
  69. package/lib/commonjs/chat-composer/create-attachment-menu.js +243 -0
  70. package/lib/commonjs/chat-composer/create-attachment-menu.js.map +1 -0
  71. package/lib/commonjs/chat-composer/create-chat-composer.js +400 -0
  72. package/lib/commonjs/chat-composer/create-chat-composer.js.map +1 -0
  73. package/lib/commonjs/chat-composer/create-composer-attachment-strip.js +212 -0
  74. package/lib/commonjs/chat-composer/create-composer-attachment-strip.js.map +1 -0
  75. package/lib/commonjs/chat-composer/create-composer-banner.js +176 -0
  76. package/lib/commonjs/chat-composer/create-composer-banner.js.map +1 -0
  77. package/lib/commonjs/chat-composer/create-emoji-picker.js +456 -0
  78. package/lib/commonjs/chat-composer/create-emoji-picker.js.map +1 -0
  79. package/lib/commonjs/chat-composer/create-message-context-menu.js +119 -0
  80. package/lib/commonjs/chat-composer/create-message-context-menu.js.map +1 -0
  81. package/lib/commonjs/chat-composer/create-reaction-picker.js +120 -0
  82. package/lib/commonjs/chat-composer/create-reaction-picker.js.map +1 -0
  83. package/lib/commonjs/chat-composer/create-suggestion-list.js +234 -0
  84. package/lib/commonjs/chat-composer/create-suggestion-list.js.map +1 -0
  85. package/lib/commonjs/chat-composer/create-voice-recorder.js +277 -0
  86. package/lib/commonjs/chat-composer/create-voice-recorder.js.map +1 -0
  87. package/lib/commonjs/chat-composer/index.js +9 -9
  88. package/lib/commonjs/chat-composer/index.web.js +18 -18
  89. package/lib/commonjs/chat-composer/index.web.js.map +1 -1
  90. package/lib/commonjs/chat-people/contact-row.js +13 -0
  91. package/lib/commonjs/chat-people/contact-row.js.map +1 -0
  92. package/lib/commonjs/chat-screen/ChatSplitLayout.js +2 -2
  93. package/lib/commonjs/chat-screen/ChatSplitLayout.js.map +1 -1
  94. package/lib/commonjs/earnings/EarningsSummary.js +12 -2
  95. package/lib/commonjs/earnings/EarningsSummary.js.map +1 -1
  96. package/lib/commonjs/field/Field.js +2 -0
  97. package/lib/commonjs/field/Field.js.map +1 -1
  98. package/lib/commonjs/item/Item.js +16 -8
  99. package/lib/commonjs/item/Item.js.map +1 -1
  100. package/lib/commonjs/job-board/JobCard.js +6 -2
  101. package/lib/commonjs/job-board/JobCard.js.map +1 -1
  102. package/lib/commonjs/label/Label.js +2 -1
  103. package/lib/commonjs/label/Label.js.map +1 -1
  104. package/lib/commonjs/listing-details/AmenityList.js +4 -3
  105. package/lib/commonjs/listing-details/AmenityList.js.map +1 -1
  106. package/lib/commonjs/locale/common-messages.js +30 -15
  107. package/lib/commonjs/locale/common-messages.js.map +1 -1
  108. package/lib/commonjs/mail-compose/MailComposeSurface.js +1 -1
  109. package/lib/commonjs/overlay/InteractionBoundary.js +28 -0
  110. package/lib/commonjs/overlay/InteractionBoundary.js.map +1 -0
  111. package/lib/commonjs/payment-method/PaymentMethodList.js +3 -2
  112. package/lib/commonjs/payment-method/PaymentMethodList.js.map +1 -1
  113. package/lib/commonjs/place-details/PlaceAmenities.js +17 -6
  114. package/lib/commonjs/place-details/PlaceAmenities.js.map +1 -1
  115. package/lib/commonjs/place-details/PlacePopularTimes.js +7 -1
  116. package/lib/commonjs/place-details/PlacePopularTimes.js.map +1 -1
  117. package/lib/commonjs/proof-of-delivery/ProofOfDelivery.js +10 -1
  118. package/lib/commonjs/proof-of-delivery/ProofOfDelivery.js.map +1 -1
  119. package/lib/commonjs/proof-of-delivery/shared.js +1 -1
  120. package/lib/commonjs/proof-of-delivery/shared.js.map +1 -1
  121. package/lib/commonjs/select/Select.js +7 -4
  122. package/lib/commonjs/select/Select.js.map +1 -1
  123. package/lib/commonjs/select/Select.web.js +7 -4
  124. package/lib/commonjs/select/Select.web.js.map +1 -1
  125. package/lib/commonjs/select/use-required-description.js +37 -0
  126. package/lib/commonjs/select/use-required-description.js.map +1 -0
  127. package/lib/commonjs/settings-modal/rows.js +37 -0
  128. package/lib/commonjs/settings-modal/rows.js.map +1 -0
  129. package/lib/module/ai-chat/AiChatResizeHandle.js +160 -0
  130. package/lib/module/ai-chat/AiChatResizeHandle.js.map +1 -0
  131. package/lib/module/ai-chat/AiChatShell.js +5 -152
  132. package/lib/module/ai-chat/AiChatShell.js.map +1 -1
  133. package/lib/module/ai-chat/index.js +2 -1
  134. package/lib/module/ai-chat/index.js.map +1 -1
  135. package/lib/module/ai-chat/index.web.js +2 -1
  136. package/lib/module/ai-chat/index.web.js.map +1 -1
  137. package/lib/module/ai-chat/messages.js +15 -30
  138. package/lib/module/ai-chat/messages.js.map +1 -1
  139. package/lib/module/app-shell/AppShellSplit.js +1 -1
  140. package/lib/module/app-shell/AppShellSplit.js.map +1 -1
  141. package/lib/module/button/Button.js +36 -3
  142. package/lib/module/button/Button.js.map +1 -1
  143. package/lib/module/button/GlyphButton.js +7 -3
  144. package/lib/module/button/GlyphButton.js.map +1 -1
  145. package/lib/module/card-form/shared.js +3 -2
  146. package/lib/module/card-form/shared.js.map +1 -1
  147. package/lib/module/chat-composer/AttachmentMenu.js +7 -226
  148. package/lib/module/chat-composer/AttachmentMenu.js.map +1 -1
  149. package/lib/module/chat-composer/AttachmentMenu.web.js +12 -0
  150. package/lib/module/chat-composer/AttachmentMenu.web.js.map +1 -0
  151. package/lib/module/chat-composer/ChatComposer.js +8 -385
  152. package/lib/module/chat-composer/ChatComposer.js.map +1 -1
  153. package/lib/module/chat-composer/ChatComposer.web.js +12 -0
  154. package/lib/module/chat-composer/ChatComposer.web.js.map +1 -0
  155. package/lib/module/chat-composer/ComposerAttachmentStrip.js +4 -196
  156. package/lib/module/chat-composer/ComposerAttachmentStrip.js.map +1 -1
  157. package/lib/module/chat-composer/ComposerAttachmentStrip.web.js +8 -0
  158. package/lib/module/chat-composer/ComposerAttachmentStrip.web.js.map +1 -0
  159. package/lib/module/chat-composer/ComposerBanner.js +4 -162
  160. package/lib/module/chat-composer/ComposerBanner.js.map +1 -1
  161. package/lib/module/chat-composer/ComposerBanner.web.js +8 -0
  162. package/lib/module/chat-composer/ComposerBanner.web.js.map +1 -0
  163. package/lib/module/chat-composer/EmojiPicker.js +5 -440
  164. package/lib/module/chat-composer/EmojiPicker.js.map +1 -1
  165. package/lib/module/chat-composer/EmojiPicker.web.js +10 -0
  166. package/lib/module/chat-composer/EmojiPicker.web.js.map +1 -0
  167. package/lib/module/chat-composer/MessageContextMenu.js +11 -99
  168. package/lib/module/chat-composer/MessageContextMenu.js.map +1 -1
  169. package/lib/module/chat-composer/MessageContextMenu.web.js +15 -0
  170. package/lib/module/chat-composer/MessageContextMenu.web.js.map +1 -0
  171. package/lib/module/chat-composer/ReactionPicker.js +5 -104
  172. package/lib/module/chat-composer/ReactionPicker.js.map +1 -1
  173. package/lib/module/chat-composer/ReactionPicker.web.js +10 -0
  174. package/lib/module/chat-composer/ReactionPicker.web.js.map +1 -0
  175. package/lib/module/chat-composer/SuggestionList.js +4 -219
  176. package/lib/module/chat-composer/SuggestionList.js.map +1 -1
  177. package/lib/module/chat-composer/SuggestionList.web.js +8 -0
  178. package/lib/module/chat-composer/SuggestionList.web.js.map +1 -0
  179. package/lib/module/chat-composer/VoiceRecorder.js +6 -260
  180. package/lib/module/chat-composer/VoiceRecorder.js.map +1 -1
  181. package/lib/module/chat-composer/VoiceRecorder.web.js +12 -0
  182. package/lib/module/chat-composer/VoiceRecorder.web.js.map +1 -0
  183. package/lib/module/chat-composer/create-attachment-menu.js +238 -0
  184. package/lib/module/chat-composer/create-attachment-menu.js.map +1 -0
  185. package/lib/module/chat-composer/create-chat-composer.js +395 -0
  186. package/lib/module/chat-composer/create-chat-composer.js.map +1 -0
  187. package/lib/module/chat-composer/create-composer-attachment-strip.js +206 -0
  188. package/lib/module/chat-composer/create-composer-attachment-strip.js.map +1 -0
  189. package/lib/module/chat-composer/create-composer-banner.js +171 -0
  190. package/lib/module/chat-composer/create-composer-banner.js.map +1 -0
  191. package/lib/module/chat-composer/create-emoji-picker.js +451 -0
  192. package/lib/module/chat-composer/create-emoji-picker.js.map +1 -0
  193. package/lib/module/chat-composer/create-message-context-menu.js +114 -0
  194. package/lib/module/chat-composer/create-message-context-menu.js.map +1 -0
  195. package/lib/module/chat-composer/create-reaction-picker.js +115 -0
  196. package/lib/module/chat-composer/create-reaction-picker.js.map +1 -0
  197. package/lib/module/chat-composer/create-suggestion-list.js +229 -0
  198. package/lib/module/chat-composer/create-suggestion-list.js.map +1 -0
  199. package/lib/module/chat-composer/create-voice-recorder.js +272 -0
  200. package/lib/module/chat-composer/create-voice-recorder.js.map +1 -0
  201. package/lib/module/chat-composer/index.js +9 -9
  202. package/lib/module/chat-composer/index.js.map +1 -1
  203. package/lib/module/chat-composer/index.web.js +9 -9
  204. package/lib/module/chat-composer/index.web.js.map +1 -1
  205. package/lib/module/chat-people/contact-row.js +10 -0
  206. package/lib/module/chat-people/contact-row.js.map +1 -0
  207. package/lib/module/chat-screen/ChatSplitLayout.js +1 -1
  208. package/lib/module/chat-screen/ChatSplitLayout.js.map +1 -1
  209. package/lib/module/earnings/EarningsSummary.js +12 -2
  210. package/lib/module/earnings/EarningsSummary.js.map +1 -1
  211. package/lib/module/field/Field.js +2 -0
  212. package/lib/module/field/Field.js.map +1 -1
  213. package/lib/module/item/Item.js +16 -8
  214. package/lib/module/item/Item.js.map +1 -1
  215. package/lib/module/job-board/JobCard.js +6 -2
  216. package/lib/module/job-board/JobCard.js.map +1 -1
  217. package/lib/module/label/Label.js +2 -1
  218. package/lib/module/label/Label.js.map +1 -1
  219. package/lib/module/listing-details/AmenityList.js +4 -3
  220. package/lib/module/listing-details/AmenityList.js.map +1 -1
  221. package/lib/module/locale/common-messages.js +30 -15
  222. package/lib/module/locale/common-messages.js.map +1 -1
  223. package/lib/module/mail-compose/MailComposeSurface.js +1 -1
  224. package/lib/module/mail-compose/MailComposeSurface.js.map +1 -1
  225. package/lib/module/overlay/InteractionBoundary.js +25 -0
  226. package/lib/module/overlay/InteractionBoundary.js.map +1 -0
  227. package/lib/module/payment-method/PaymentMethodList.js +3 -2
  228. package/lib/module/payment-method/PaymentMethodList.js.map +1 -1
  229. package/lib/module/place-details/PlaceAmenities.js +15 -4
  230. package/lib/module/place-details/PlaceAmenities.js.map +1 -1
  231. package/lib/module/place-details/PlacePopularTimes.js +7 -1
  232. package/lib/module/place-details/PlacePopularTimes.js.map +1 -1
  233. package/lib/module/proof-of-delivery/ProofOfDelivery.js +10 -1
  234. package/lib/module/proof-of-delivery/ProofOfDelivery.js.map +1 -1
  235. package/lib/module/proof-of-delivery/shared.js +1 -1
  236. package/lib/module/proof-of-delivery/shared.js.map +1 -1
  237. package/lib/module/select/Select.js +7 -4
  238. package/lib/module/select/Select.js.map +1 -1
  239. package/lib/module/select/Select.web.js +7 -4
  240. package/lib/module/select/Select.web.js.map +1 -1
  241. package/lib/module/select/use-required-description.js +33 -0
  242. package/lib/module/select/use-required-description.js.map +1 -0
  243. package/lib/module/settings-modal/rows.js +10 -0
  244. package/lib/module/settings-modal/rows.js.map +1 -0
  245. package/lib/typescript/commonjs/ai-chat/AiChatResizeHandle.d.ts +11 -0
  246. package/lib/typescript/commonjs/ai-chat/AiChatResizeHandle.d.ts.map +1 -0
  247. package/lib/typescript/commonjs/ai-chat/AiChatShell.d.ts +1 -10
  248. package/lib/typescript/commonjs/ai-chat/AiChatShell.d.ts.map +1 -1
  249. package/lib/typescript/commonjs/ai-chat/index.d.ts +2 -1
  250. package/lib/typescript/commonjs/ai-chat/index.d.ts.map +1 -1
  251. package/lib/typescript/commonjs/ai-chat/index.web.d.ts +2 -1
  252. package/lib/typescript/commonjs/ai-chat/index.web.d.ts.map +1 -1
  253. package/lib/typescript/commonjs/ai-chat/messages.d.ts +0 -1
  254. package/lib/typescript/commonjs/ai-chat/messages.d.ts.map +1 -1
  255. package/lib/typescript/commonjs/button/Button.d.ts.map +1 -1
  256. package/lib/typescript/commonjs/card-form/shared.d.ts +2 -1
  257. package/lib/typescript/commonjs/card-form/shared.d.ts.map +1 -1
  258. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.d.ts +1 -2
  259. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.d.ts.map +1 -1
  260. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.web.d.ts +2 -0
  261. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.web.d.ts.map +1 -0
  262. package/lib/typescript/commonjs/chat-composer/ChatComposer.d.ts +1 -2
  263. package/lib/typescript/commonjs/chat-composer/ChatComposer.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/chat-composer/ChatComposer.web.d.ts +2 -0
  265. package/lib/typescript/commonjs/chat-composer/ChatComposer.web.d.ts.map +1 -0
  266. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.d.ts +1 -2
  267. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.web.d.ts +2 -0
  269. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.web.d.ts.map +1 -0
  270. package/lib/typescript/commonjs/chat-composer/ComposerBanner.d.ts +1 -2
  271. package/lib/typescript/commonjs/chat-composer/ComposerBanner.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/chat-composer/ComposerBanner.web.d.ts +2 -0
  273. package/lib/typescript/commonjs/chat-composer/ComposerBanner.web.d.ts.map +1 -0
  274. package/lib/typescript/commonjs/chat-composer/EmojiPicker.d.ts +1 -2
  275. package/lib/typescript/commonjs/chat-composer/EmojiPicker.d.ts.map +1 -1
  276. package/lib/typescript/commonjs/chat-composer/EmojiPicker.web.d.ts +2 -0
  277. package/lib/typescript/commonjs/chat-composer/EmojiPicker.web.d.ts.map +1 -0
  278. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.d.ts +1 -2
  279. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.d.ts.map +1 -1
  280. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.web.d.ts +2 -0
  281. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.web.d.ts.map +1 -0
  282. package/lib/typescript/commonjs/chat-composer/ReactionPicker.d.ts +1 -2
  283. package/lib/typescript/commonjs/chat-composer/ReactionPicker.d.ts.map +1 -1
  284. package/lib/typescript/commonjs/chat-composer/ReactionPicker.web.d.ts +2 -0
  285. package/lib/typescript/commonjs/chat-composer/ReactionPicker.web.d.ts.map +1 -0
  286. package/lib/typescript/commonjs/chat-composer/SuggestionList.d.ts +1 -2
  287. package/lib/typescript/commonjs/chat-composer/SuggestionList.d.ts.map +1 -1
  288. package/lib/typescript/commonjs/chat-composer/SuggestionList.web.d.ts +2 -0
  289. package/lib/typescript/commonjs/chat-composer/SuggestionList.web.d.ts.map +1 -0
  290. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.d.ts +1 -2
  291. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.d.ts.map +1 -1
  292. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.web.d.ts +2 -0
  293. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.web.d.ts.map +1 -0
  294. package/lib/typescript/commonjs/chat-composer/create-attachment-menu.d.ts +11 -0
  295. package/lib/typescript/commonjs/chat-composer/create-attachment-menu.d.ts.map +1 -0
  296. package/lib/typescript/commonjs/chat-composer/create-chat-composer.d.ts +11 -0
  297. package/lib/typescript/commonjs/chat-composer/create-chat-composer.d.ts.map +1 -0
  298. package/lib/typescript/commonjs/chat-composer/create-composer-attachment-strip.d.ts +7 -0
  299. package/lib/typescript/commonjs/chat-composer/create-composer-attachment-strip.d.ts.map +1 -0
  300. package/lib/typescript/commonjs/chat-composer/create-composer-banner.d.ts +7 -0
  301. package/lib/typescript/commonjs/chat-composer/create-composer-banner.d.ts.map +1 -0
  302. package/lib/typescript/commonjs/chat-composer/create-emoji-picker.d.ts +9 -0
  303. package/lib/typescript/commonjs/chat-composer/create-emoji-picker.d.ts.map +1 -0
  304. package/lib/typescript/commonjs/chat-composer/create-message-context-menu.d.ts +14 -0
  305. package/lib/typescript/commonjs/chat-composer/create-message-context-menu.d.ts.map +1 -0
  306. package/lib/typescript/commonjs/chat-composer/create-reaction-picker.d.ts +9 -0
  307. package/lib/typescript/commonjs/chat-composer/create-reaction-picker.d.ts.map +1 -0
  308. package/lib/typescript/commonjs/chat-composer/create-suggestion-list.d.ts +7 -0
  309. package/lib/typescript/commonjs/chat-composer/create-suggestion-list.d.ts.map +1 -0
  310. package/lib/typescript/commonjs/chat-composer/create-voice-recorder.d.ts +11 -0
  311. package/lib/typescript/commonjs/chat-composer/create-voice-recorder.d.ts.map +1 -0
  312. package/lib/typescript/commonjs/chat-composer/index.web.d.ts +9 -9
  313. package/lib/typescript/commonjs/chat-composer/index.web.d.ts.map +1 -1
  314. package/lib/typescript/commonjs/chat-people/contact-row.d.ts +9 -0
  315. package/lib/typescript/commonjs/chat-people/contact-row.d.ts.map +1 -0
  316. package/lib/typescript/commonjs/earnings/EarningsSummary.d.ts.map +1 -1
  317. package/lib/typescript/commonjs/field/Field.d.ts +1 -1
  318. package/lib/typescript/commonjs/field/Field.d.ts.map +1 -1
  319. package/lib/typescript/commonjs/field/types.d.ts +2 -0
  320. package/lib/typescript/commonjs/field/types.d.ts.map +1 -1
  321. package/lib/typescript/commonjs/floating/types.d.ts +1 -0
  322. package/lib/typescript/commonjs/floating/types.d.ts.map +1 -1
  323. package/lib/typescript/commonjs/item/Item.d.ts.map +1 -1
  324. package/lib/typescript/commonjs/job-board/JobCard.d.ts.map +1 -1
  325. package/lib/typescript/commonjs/label/Label.d.ts +1 -1
  326. package/lib/typescript/commonjs/label/Label.d.ts.map +1 -1
  327. package/lib/typescript/commonjs/label/types.d.ts +2 -0
  328. package/lib/typescript/commonjs/label/types.d.ts.map +1 -1
  329. package/lib/typescript/commonjs/listing-details/AmenityList.d.ts.map +1 -1
  330. package/lib/typescript/commonjs/locale/common-messages.d.ts +2 -0
  331. package/lib/typescript/commonjs/locale/common-messages.d.ts.map +1 -1
  332. package/lib/typescript/commonjs/overlay/InteractionBoundary.d.ts +7 -0
  333. package/lib/typescript/commonjs/overlay/InteractionBoundary.d.ts.map +1 -0
  334. package/lib/typescript/commonjs/payment-method/PaymentMethodList.d.ts.map +1 -1
  335. package/lib/typescript/commonjs/place-details/PlaceAmenities.d.ts.map +1 -1
  336. package/lib/typescript/commonjs/place-details/PlacePopularTimes.d.ts.map +1 -1
  337. package/lib/typescript/commonjs/proof-of-delivery/ProofOfDelivery.d.ts.map +1 -1
  338. package/lib/typescript/commonjs/select/Select.d.ts.map +1 -1
  339. package/lib/typescript/commonjs/select/Select.web.d.ts.map +1 -1
  340. package/lib/typescript/commonjs/select/use-required-description.d.ts +7 -0
  341. package/lib/typescript/commonjs/select/use-required-description.d.ts.map +1 -0
  342. package/lib/typescript/commonjs/settings-modal/rows.d.ts +9 -0
  343. package/lib/typescript/commonjs/settings-modal/rows.d.ts.map +1 -0
  344. package/lib/typescript/module/ai-chat/AiChatResizeHandle.d.ts +11 -0
  345. package/lib/typescript/module/ai-chat/AiChatResizeHandle.d.ts.map +1 -0
  346. package/lib/typescript/module/ai-chat/AiChatShell.d.ts +1 -10
  347. package/lib/typescript/module/ai-chat/AiChatShell.d.ts.map +1 -1
  348. package/lib/typescript/module/ai-chat/index.d.ts +2 -1
  349. package/lib/typescript/module/ai-chat/index.d.ts.map +1 -1
  350. package/lib/typescript/module/ai-chat/index.web.d.ts +2 -1
  351. package/lib/typescript/module/ai-chat/index.web.d.ts.map +1 -1
  352. package/lib/typescript/module/ai-chat/messages.d.ts +0 -1
  353. package/lib/typescript/module/ai-chat/messages.d.ts.map +1 -1
  354. package/lib/typescript/module/button/Button.d.ts.map +1 -1
  355. package/lib/typescript/module/card-form/shared.d.ts +2 -1
  356. package/lib/typescript/module/card-form/shared.d.ts.map +1 -1
  357. package/lib/typescript/module/chat-composer/AttachmentMenu.d.ts +1 -2
  358. package/lib/typescript/module/chat-composer/AttachmentMenu.d.ts.map +1 -1
  359. package/lib/typescript/module/chat-composer/AttachmentMenu.web.d.ts +2 -0
  360. package/lib/typescript/module/chat-composer/AttachmentMenu.web.d.ts.map +1 -0
  361. package/lib/typescript/module/chat-composer/ChatComposer.d.ts +1 -2
  362. package/lib/typescript/module/chat-composer/ChatComposer.d.ts.map +1 -1
  363. package/lib/typescript/module/chat-composer/ChatComposer.web.d.ts +2 -0
  364. package/lib/typescript/module/chat-composer/ChatComposer.web.d.ts.map +1 -0
  365. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.d.ts +1 -2
  366. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.d.ts.map +1 -1
  367. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.web.d.ts +2 -0
  368. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.web.d.ts.map +1 -0
  369. package/lib/typescript/module/chat-composer/ComposerBanner.d.ts +1 -2
  370. package/lib/typescript/module/chat-composer/ComposerBanner.d.ts.map +1 -1
  371. package/lib/typescript/module/chat-composer/ComposerBanner.web.d.ts +2 -0
  372. package/lib/typescript/module/chat-composer/ComposerBanner.web.d.ts.map +1 -0
  373. package/lib/typescript/module/chat-composer/EmojiPicker.d.ts +1 -2
  374. package/lib/typescript/module/chat-composer/EmojiPicker.d.ts.map +1 -1
  375. package/lib/typescript/module/chat-composer/EmojiPicker.web.d.ts +2 -0
  376. package/lib/typescript/module/chat-composer/EmojiPicker.web.d.ts.map +1 -0
  377. package/lib/typescript/module/chat-composer/MessageContextMenu.d.ts +1 -2
  378. package/lib/typescript/module/chat-composer/MessageContextMenu.d.ts.map +1 -1
  379. package/lib/typescript/module/chat-composer/MessageContextMenu.web.d.ts +2 -0
  380. package/lib/typescript/module/chat-composer/MessageContextMenu.web.d.ts.map +1 -0
  381. package/lib/typescript/module/chat-composer/ReactionPicker.d.ts +1 -2
  382. package/lib/typescript/module/chat-composer/ReactionPicker.d.ts.map +1 -1
  383. package/lib/typescript/module/chat-composer/ReactionPicker.web.d.ts +2 -0
  384. package/lib/typescript/module/chat-composer/ReactionPicker.web.d.ts.map +1 -0
  385. package/lib/typescript/module/chat-composer/SuggestionList.d.ts +1 -2
  386. package/lib/typescript/module/chat-composer/SuggestionList.d.ts.map +1 -1
  387. package/lib/typescript/module/chat-composer/SuggestionList.web.d.ts +2 -0
  388. package/lib/typescript/module/chat-composer/SuggestionList.web.d.ts.map +1 -0
  389. package/lib/typescript/module/chat-composer/VoiceRecorder.d.ts +1 -2
  390. package/lib/typescript/module/chat-composer/VoiceRecorder.d.ts.map +1 -1
  391. package/lib/typescript/module/chat-composer/VoiceRecorder.web.d.ts +2 -0
  392. package/lib/typescript/module/chat-composer/VoiceRecorder.web.d.ts.map +1 -0
  393. package/lib/typescript/module/chat-composer/create-attachment-menu.d.ts +11 -0
  394. package/lib/typescript/module/chat-composer/create-attachment-menu.d.ts.map +1 -0
  395. package/lib/typescript/module/chat-composer/create-chat-composer.d.ts +11 -0
  396. package/lib/typescript/module/chat-composer/create-chat-composer.d.ts.map +1 -0
  397. package/lib/typescript/module/chat-composer/create-composer-attachment-strip.d.ts +7 -0
  398. package/lib/typescript/module/chat-composer/create-composer-attachment-strip.d.ts.map +1 -0
  399. package/lib/typescript/module/chat-composer/create-composer-banner.d.ts +7 -0
  400. package/lib/typescript/module/chat-composer/create-composer-banner.d.ts.map +1 -0
  401. package/lib/typescript/module/chat-composer/create-emoji-picker.d.ts +9 -0
  402. package/lib/typescript/module/chat-composer/create-emoji-picker.d.ts.map +1 -0
  403. package/lib/typescript/module/chat-composer/create-message-context-menu.d.ts +14 -0
  404. package/lib/typescript/module/chat-composer/create-message-context-menu.d.ts.map +1 -0
  405. package/lib/typescript/module/chat-composer/create-reaction-picker.d.ts +9 -0
  406. package/lib/typescript/module/chat-composer/create-reaction-picker.d.ts.map +1 -0
  407. package/lib/typescript/module/chat-composer/create-suggestion-list.d.ts +7 -0
  408. package/lib/typescript/module/chat-composer/create-suggestion-list.d.ts.map +1 -0
  409. package/lib/typescript/module/chat-composer/create-voice-recorder.d.ts +11 -0
  410. package/lib/typescript/module/chat-composer/create-voice-recorder.d.ts.map +1 -0
  411. package/lib/typescript/module/chat-composer/index.web.d.ts +9 -9
  412. package/lib/typescript/module/chat-composer/index.web.d.ts.map +1 -1
  413. package/lib/typescript/module/chat-people/contact-row.d.ts +9 -0
  414. package/lib/typescript/module/chat-people/contact-row.d.ts.map +1 -0
  415. package/lib/typescript/module/earnings/EarningsSummary.d.ts.map +1 -1
  416. package/lib/typescript/module/field/Field.d.ts +1 -1
  417. package/lib/typescript/module/field/Field.d.ts.map +1 -1
  418. package/lib/typescript/module/field/types.d.ts +2 -0
  419. package/lib/typescript/module/field/types.d.ts.map +1 -1
  420. package/lib/typescript/module/floating/types.d.ts +1 -0
  421. package/lib/typescript/module/floating/types.d.ts.map +1 -1
  422. package/lib/typescript/module/item/Item.d.ts.map +1 -1
  423. package/lib/typescript/module/job-board/JobCard.d.ts.map +1 -1
  424. package/lib/typescript/module/label/Label.d.ts +1 -1
  425. package/lib/typescript/module/label/Label.d.ts.map +1 -1
  426. package/lib/typescript/module/label/types.d.ts +2 -0
  427. package/lib/typescript/module/label/types.d.ts.map +1 -1
  428. package/lib/typescript/module/listing-details/AmenityList.d.ts.map +1 -1
  429. package/lib/typescript/module/locale/common-messages.d.ts +2 -0
  430. package/lib/typescript/module/locale/common-messages.d.ts.map +1 -1
  431. package/lib/typescript/module/overlay/InteractionBoundary.d.ts +7 -0
  432. package/lib/typescript/module/overlay/InteractionBoundary.d.ts.map +1 -0
  433. package/lib/typescript/module/payment-method/PaymentMethodList.d.ts.map +1 -1
  434. package/lib/typescript/module/place-details/PlaceAmenities.d.ts.map +1 -1
  435. package/lib/typescript/module/place-details/PlacePopularTimes.d.ts.map +1 -1
  436. package/lib/typescript/module/proof-of-delivery/ProofOfDelivery.d.ts.map +1 -1
  437. package/lib/typescript/module/select/Select.d.ts.map +1 -1
  438. package/lib/typescript/module/select/Select.web.d.ts.map +1 -1
  439. package/lib/typescript/module/select/use-required-description.d.ts +7 -0
  440. package/lib/typescript/module/select/use-required-description.d.ts.map +1 -0
  441. package/lib/typescript/module/settings-modal/rows.d.ts +9 -0
  442. package/lib/typescript/module/settings-modal/rows.d.ts.map +1 -0
  443. package/package.json +35 -1
  444. package/src/ai-chat/AiChatResizeHandle.tsx +151 -0
  445. package/src/ai-chat/AiChatShell.tsx +8 -143
  446. package/src/ai-chat/index.ts +2 -1
  447. package/src/ai-chat/index.web.ts +2 -1
  448. package/src/ai-chat/messages.ts +0 -16
  449. package/src/app-shell/AppShellSplit.tsx +1 -1
  450. package/src/button/Button.tsx +35 -10
  451. package/src/button/GlyphButton.tsx +3 -3
  452. package/src/card-form/shared.ts +3 -2
  453. package/src/chat-composer/AttachmentMenu.tsx +2 -214
  454. package/src/chat-composer/AttachmentMenu.web.tsx +5 -0
  455. package/src/chat-composer/ChatComposer.tsx +2 -459
  456. package/src/chat-composer/ChatComposer.web.tsx +6 -0
  457. package/src/chat-composer/ComposerAttachmentStrip.tsx +2 -202
  458. package/src/chat-composer/ComposerAttachmentStrip.web.tsx +4 -0
  459. package/src/chat-composer/ComposerBanner.tsx +2 -157
  460. package/src/chat-composer/ComposerBanner.web.tsx +4 -0
  461. package/src/chat-composer/EmojiPicker.tsx +2 -402
  462. package/src/chat-composer/EmojiPicker.web.tsx +5 -0
  463. package/src/chat-composer/MessageContextMenu.tsx +2 -88
  464. package/src/chat-composer/MessageContextMenu.web.tsx +12 -0
  465. package/src/chat-composer/ReactionPicker.tsx +2 -100
  466. package/src/chat-composer/ReactionPicker.web.tsx +5 -0
  467. package/src/chat-composer/SuggestionList.tsx +2 -209
  468. package/src/chat-composer/SuggestionList.web.tsx +4 -0
  469. package/src/chat-composer/VoiceRecorder.tsx +2 -287
  470. package/src/chat-composer/VoiceRecorder.web.tsx +6 -0
  471. package/src/chat-composer/create-attachment-menu.tsx +228 -0
  472. package/src/chat-composer/create-chat-composer.tsx +473 -0
  473. package/src/chat-composer/create-composer-attachment-strip.tsx +212 -0
  474. package/src/chat-composer/create-composer-banner.tsx +167 -0
  475. package/src/chat-composer/create-emoji-picker.tsx +414 -0
  476. package/src/chat-composer/create-message-context-menu.tsx +112 -0
  477. package/src/chat-composer/create-reaction-picker.tsx +112 -0
  478. package/src/chat-composer/create-suggestion-list.tsx +219 -0
  479. package/src/chat-composer/create-voice-recorder.tsx +301 -0
  480. package/src/chat-composer/index.web.ts +9 -9
  481. package/src/chat-people/contact-row.ts +8 -0
  482. package/src/chat-screen/ChatSplitLayout.tsx +1 -1
  483. package/src/earnings/EarningsSummary.tsx +9 -2
  484. package/src/field/Field.tsx +2 -1
  485. package/src/field/types.ts +2 -0
  486. package/src/floating/types.ts +1 -0
  487. package/src/item/Item.tsx +16 -11
  488. package/src/job-board/JobCard.tsx +4 -1
  489. package/src/label/Label.tsx +2 -1
  490. package/src/label/types.ts +2 -0
  491. package/src/listing-details/AmenityList.tsx +4 -3
  492. package/src/locale/common-messages.ts +17 -0
  493. package/src/overlay/InteractionBoundary.tsx +24 -0
  494. package/src/payment-method/PaymentMethodList.tsx +2 -1
  495. package/src/place-details/PlaceAmenities.tsx +9 -0
  496. package/src/place-details/PlacePopularTimes.tsx +7 -1
  497. package/src/proof-of-delivery/ProofOfDelivery.tsx +9 -1
  498. package/src/proof-of-delivery/shared.ts +1 -1
  499. package/src/select/Select.tsx +5 -1
  500. package/src/select/Select.web.tsx +5 -1
  501. package/src/select/use-required-description.tsx +20 -0
  502. package/src/settings-modal/rows.ts +21 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * The plus/paperclip menu.
3
+ *
4
+ * It is `Popover`, not a hand-rolled surface, and that one choice is the whole
5
+ * platform story: Bloom's popover is already an anchored panel on a pointer and
6
+ * a bottom sheet on a phone, so this family adds no platform fork of its own
7
+ * and inherits the dismissal, stacking and focus behaviour those surfaces were
8
+ * gated for.
9
+ */
10
+ import React from 'react';
11
+ import { View, type DimensionValue } from 'react-native';
12
+
13
+ import type { Button as ButtonComponent } from '../button';
14
+ import type { Popover as PopoverComponent, PopoverContent as PopoverContentComponent, PopoverTrigger as PopoverTriggerComponent } from '../popover';
15
+ import type { WebCssStyle } from '../styles/web-view-style';
16
+ import { useTheme } from '../theme/use-theme';
17
+ import { Text } from '../typography';
18
+ import { attachmentMenuItems, resolveChatComposerPalette } from './shared';
19
+ import type { AttachmentMenuItem, AttachmentMenuProps } from './types';
20
+ import { useChatComposerWebCss } from './web-hooks';
21
+ import { useMessages } from '../locale/messages';
22
+ import { CHAT_COMPOSER_MESSAGES } from './messages';
23
+
24
+ /** Platform dependencies are bound once; shared rendering adds no wrapper. */
25
+ export function createAttachmentMenu({ Button, Popover, PopoverContent, PopoverTrigger }: {
26
+ Button: typeof ButtonComponent;
27
+ Popover: typeof PopoverComponent;
28
+ PopoverContent: typeof PopoverContentComponent;
29
+ PopoverTrigger: typeof PopoverTriggerComponent;
30
+ }) {
31
+
32
+ /** A 48px tinted disc with its label under it. */
33
+ function GridCell({
34
+ item,
35
+ onPress,
36
+ width,
37
+ testID,
38
+ }: {
39
+ item: AttachmentMenuItem;
40
+ onPress: () => void;
41
+ width: DimensionValue;
42
+ testID?: string;
43
+ }) {
44
+ const theme = useTheme();
45
+ const palette = resolveChatComposerPalette(theme);
46
+ const tint = item.color ?? palette.accent;
47
+ const cell: WebCssStyle = {
48
+ width,
49
+ height: 'auto',
50
+ minHeight: 0,
51
+ minWidth: 0,
52
+ paddingLeft: 0,
53
+ paddingRight: 0,
54
+ alignItems: 'center',
55
+ gap: 6,
56
+ paddingTop: 8,
57
+ paddingBottom: 8,
58
+ borderRadius: 12,
59
+ opacity: item.disabled ? 0.45 : 1,
60
+ cursor: item.disabled ? 'auto' : 'pointer',
61
+ };
62
+ return (
63
+ <Button
64
+ appearance="plain"
65
+ tone="neutral"
66
+ accessibilityLabel={item.label}
67
+ disabled={item.disabled}
68
+ onPress={onPress}
69
+ style={cell}
70
+ testID={testID}>
71
+ <View style={{ alignItems: 'center', gap: 6 }}>
72
+ <View
73
+ style={{
74
+ width: 48,
75
+ height: 48,
76
+ borderRadius: 24,
77
+ alignItems: 'center',
78
+ justifyContent: 'center',
79
+ backgroundColor: palette.accentSoft,
80
+ }}>
81
+ <item.icon width={22} height={22} fill={tint} />
82
+ </View>
83
+ <Text variant="caption-1-regular" numberOfLines={1} style={{ color: palette.textSecondary }}>
84
+ {item.label}
85
+ </Text>
86
+ </View>
87
+ </Button>
88
+ );
89
+ }
90
+
91
+ /** A full-width row: glyph, label. */
92
+ function ListRow({
93
+ item,
94
+ onPress,
95
+ testID,
96
+ }: {
97
+ item: AttachmentMenuItem;
98
+ onPress: () => void;
99
+ testID?: string;
100
+ }) {
101
+ const theme = useTheme();
102
+ const palette = resolveChatComposerPalette(theme);
103
+ const tint = item.color ?? palette.accent;
104
+ const row: WebCssStyle = {
105
+ flexDirection: 'row',
106
+ alignItems: 'center',
107
+ gap: 12,
108
+ minHeight: 40,
109
+ height: 'auto',
110
+ minWidth: 0,
111
+ width: '100%',
112
+ borderRadius: 10,
113
+ paddingLeft: 8,
114
+ paddingRight: 8,
115
+ paddingTop: 6,
116
+ paddingBottom: 6,
117
+ opacity: item.disabled ? 0.45 : 1,
118
+ cursor: item.disabled ? 'auto' : 'pointer',
119
+ };
120
+ return (
121
+ <Button
122
+ appearance="plain"
123
+ tone="neutral"
124
+ accessibilityLabel={item.label}
125
+ disabled={item.disabled}
126
+ onPress={onPress}
127
+ style={row}
128
+ testID={testID}>
129
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12, width: '100%' }}>
130
+ <View
131
+ style={{
132
+ width: 32,
133
+ height: 32,
134
+ borderRadius: 16,
135
+ alignItems: 'center',
136
+ justifyContent: 'center',
137
+ backgroundColor: palette.accentSoft,
138
+ }}>
139
+ <item.icon width={18} height={18} fill={tint} />
140
+ </View>
141
+ <Text variant="body-medium" numberOfLines={1} style={{ color: palette.text }}>
142
+ {item.label}
143
+ </Text>
144
+ </View>
145
+ </Button>
146
+ );
147
+ }
148
+
149
+ function AttachmentMenu({
150
+ children,
151
+ open,
152
+ defaultOpen,
153
+ onOpenChange,
154
+ items: itemsProp,
155
+ layout = 'grid',
156
+ columns = 4,
157
+ onSelect,
158
+ recent,
159
+ label: labelProp,
160
+ style,
161
+ testID,
162
+ }: AttachmentMenuProps) {
163
+ useChatComposerWebCss();
164
+ const { messages } = useMessages(CHAT_COMPOSER_MESSAGES);
165
+ const localizedItems = React.useMemo(() => attachmentMenuItems(messages), [messages]);
166
+ const items = itemsProp ?? localizedItems;
167
+ const label = labelProp ?? messages.attach;
168
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen ?? false);
169
+ const isOpen = open ?? uncontrolledOpen;
170
+
171
+ const setOpen = (next: boolean) => {
172
+ if (open === undefined) setUncontrolledOpen(next);
173
+ onOpenChange?.(next);
174
+ };
175
+
176
+ // A percentage string is the only way to say "n per row" in a wrapping flex
177
+ // row that has to work on both platforms; Yoga and CSS agree on it.
178
+ const cellWidth: DimensionValue = `${100 / Math.max(1, columns)}%`;
179
+
180
+ return (
181
+ <Popover open={isOpen} onOpenChange={setOpen}>
182
+ <PopoverTrigger asChild>{children}</PopoverTrigger>
183
+ <PopoverContent
184
+ label={label}
185
+ side="top"
186
+ align="start"
187
+ minWidth={layout === 'grid' ? Math.max(264, columns * 72) : 220}
188
+ style={style}
189
+ testID={testID}>
190
+ {recent ? <View style={{ paddingBottom: 8 }}>{recent}</View> : null}
191
+ <View
192
+ style={
193
+ layout === 'grid'
194
+ ? { flexDirection: 'row', flexWrap: 'wrap', alignItems: 'flex-start' }
195
+ : { flexDirection: 'column', gap: 2 }
196
+ }>
197
+ {items.map((item) =>
198
+ layout === 'grid' ? (
199
+ <GridCell
200
+ key={item.id}
201
+ item={item}
202
+ width={cellWidth}
203
+ onPress={() => {
204
+ onSelect?.(item.id, item);
205
+ setOpen(false);
206
+ }}
207
+ testID={testID ? `${testID}-${item.id}` : undefined}
208
+ />
209
+ ) : (
210
+ <ListRow
211
+ key={item.id}
212
+ item={item}
213
+ onPress={() => {
214
+ onSelect?.(item.id, item);
215
+ setOpen(false);
216
+ }}
217
+ testID={testID ? `${testID}-${item.id}` : undefined}
218
+ />
219
+ ),
220
+ )}
221
+ </View>
222
+ </PopoverContent>
223
+ </Popover>
224
+ );
225
+ }
226
+
227
+ return AttachmentMenu;
228
+ }
@@ -0,0 +1,473 @@
1
+ /**
2
+ * The message input bar of a person-to-person chat: a radius-24 pill with a
3
+ * left attach button, an autosizing field, an emoji button and a right control
4
+ * that swaps between a mic (nothing to send) and an accent send disc (there is).
5
+ *
6
+ * Presentational. Every piece of state — the draft, the banners, the pending
7
+ * attachments, which suggestion is highlighted — arrives as a prop, because the
8
+ * app owns drafts per conversation and a composer that kept its own would lose
9
+ * them on every navigation.
10
+ */
11
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
12
+ import {
13
+ TextInput,
14
+ View,
15
+ type NativeSyntheticEvent,
16
+ type TextInputContentSizeChangeEventData,
17
+ type TextInputKeyPressEventData,
18
+ } from 'react-native';
19
+ import Animated, {
20
+ Easing,
21
+ useAnimatedStyle,
22
+ useReducedMotion,
23
+ useSharedValue,
24
+ withTiming,
25
+ } from 'react-native-reanimated';
26
+
27
+ import { RiAddLine } from '../icons/remix/RiAddLine';
28
+ import { RiCameraLine } from '../icons/remix/RiCameraLine';
29
+ import { RiEmotionLine } from '../icons/remix/RiEmotionLine';
30
+ import { RiForbidLine } from '../icons/remix/RiForbidLine';
31
+ import { RiMic2Line } from '../icons/remix/RiMic2Line';
32
+ import { RiSendPlaneLine } from '../icons/remix/RiSendPlaneLine';
33
+ import { useControllableState } from '../hooks/use-controllable-state';
34
+ import { useTextareaAutosize } from '../hooks/use-textarea-autosize';
35
+ import type { WebCssStyle } from '../styles/web-view-style';
36
+ import { useTheme } from '../theme/use-theme';
37
+ import { Text } from '../typography';
38
+ import { TYPE_SCALE } from '../typography/scale';
39
+ import type { ComposerAttachmentStrip as ComposerAttachmentStripComponent } from './ComposerAttachmentStrip';
40
+ import type { ComposerIconButton as ComposerIconButtonComponent } from './ComposerIconButton';
41
+ import {
42
+ BAR_PADDING,
43
+ BAR_RADIUS,
44
+ chatComposerLabels,
45
+ CONTROL_SIZE,
46
+ DEFAULT_MAX_LINES,
47
+ LINE_HEIGHT,
48
+ SWAP_MS,
49
+ resolveChatComposerPalette,
50
+ } from './shared';
51
+ import type { SuggestionList as SuggestionListComponent } from './SuggestionList';
52
+ import type { ChatComposerProps } from './types';
53
+ import { dataHook, IS_WEB, useChatComposerWebCss } from './web-hooks';
54
+ import { useMessages } from '../locale/messages';
55
+ import { CHAT_COMPOSER_MESSAGES } from './messages';
56
+ import { useCommonMessages } from '../locale/common-messages';
57
+
58
+ /** Platform dependencies are bound once; shared rendering adds no wrapper. */
59
+ export function createChatComposer({ ComposerAttachmentStrip, ComposerIconButton, SuggestionList }: {
60
+ ComposerAttachmentStrip: typeof ComposerAttachmentStripComponent;
61
+ ComposerIconButton: typeof ComposerIconButtonComponent;
62
+ SuggestionList: typeof SuggestionListComponent;
63
+ }) {
64
+
65
+ const EASE_OUT = Easing.bezier(0, 0, 0.2, 1);
66
+
67
+ /**
68
+ * One half of the mic ↔ send crossfade.
69
+ *
70
+ * Two things the fade must not break, neither of which the animation expresses:
71
+ *
72
+ * `pointerEvents` is a PROP, not a style entry — react-native-web drops it from
73
+ * a style object silently, and a hidden layer that still takes the press is a
74
+ * send button that fires when the field is empty.
75
+ *
76
+ * The hidden half leaves the ACCESSIBILITY TREE too. Both halves stay mounted so
77
+ * they can cross-fade, so without this every composer announces "Send" and
78
+ * "Record a voice message" side by side and only one of them does anything.
79
+ * `aria-hidden` is what react-native-web reads and
80
+ * `importantForAccessibility` is what React Native reads; a surface that sets
81
+ * one of the two is hidden on one platform only.
82
+ */
83
+ function SwapLayer({ shown, children }: { shown: boolean; children: React.ReactNode }) {
84
+ const reducedMotion = useReducedMotion();
85
+ const progress = useSharedValue(shown ? 1 : 0);
86
+ React.useEffect(() => {
87
+ progress.value = reducedMotion
88
+ ? shown
89
+ ? 1
90
+ : 0
91
+ : withTiming(shown ? 1 : 0, { duration: SWAP_MS, easing: EASE_OUT });
92
+ }, [shown, reducedMotion, progress]);
93
+ const animated = useAnimatedStyle(() => ({ opacity: progress.value }), [progress]);
94
+ return (
95
+ <Animated.View
96
+ pointerEvents={shown ? 'auto' : 'none'}
97
+ aria-hidden={!shown}
98
+ accessibilityElementsHidden={!shown}
99
+ importantForAccessibility={shown ? 'auto' : 'no-hide-descendants'}
100
+ style={[{ position: 'absolute', top: 0, left: 0 }, animated]}>
101
+ {children}
102
+ </Animated.View>
103
+ );
104
+ }
105
+
106
+ /** A DOM keyboard event as react-native-web hands it to `onKeyPress`. */
107
+ type WebKeyEvent = TextInputKeyPressEventData & {
108
+ shiftKey?: boolean;
109
+ metaKey?: boolean;
110
+ ctrlKey?: boolean;
111
+ altKey?: boolean;
112
+ isComposing?: boolean;
113
+ };
114
+
115
+ function ChatComposer({
116
+ value,
117
+ defaultValue = '',
118
+ onValueChange,
119
+ placeholder: placeholderProp,
120
+ onSend,
121
+ sendOn = 'enter',
122
+ maxLines = DEFAULT_MAX_LINES,
123
+ minLines = 1,
124
+ disabled = false,
125
+ notice,
126
+ noticeIcon,
127
+ banner,
128
+ attachments,
129
+ onRemoveAttachment,
130
+ leading,
131
+ onAttachPress,
132
+ emojiSlot,
133
+ onEmojiPress,
134
+ onCameraPress,
135
+ onMicPress,
136
+ onMicPressIn,
137
+ onMicPressOut,
138
+ canSend,
139
+ recorder,
140
+ suggestions,
141
+ suggestionKind = 'mention',
142
+ activeIndex = -1,
143
+ onActiveIndexChange,
144
+ onSelectSuggestion,
145
+ onEscape,
146
+ onEditLast,
147
+ showKeyboardHint = false,
148
+ inputRef,
149
+ onFocus,
150
+ onBlur,
151
+ labels: labelOverrides,
152
+ style,
153
+ testID,
154
+ accessibilityLabel,
155
+ }: ChatComposerProps) {
156
+ const theme = useTheme();
157
+ const { messages } = useMessages(CHAT_COMPOSER_MESSAGES);
158
+ const common = useCommonMessages();
159
+ const palette = resolveChatComposerPalette(theme);
160
+ useChatComposerWebCss();
161
+ const labels = useMemo(
162
+ () => ({ ...chatComposerLabels(messages, common.send), ...labelOverrides }),
163
+ [common.send, labelOverrides, messages],
164
+ );
165
+ const placeholder = placeholderProp ?? messages.message;
166
+
167
+ const [text, setText] = useControllableState<string>({
168
+ value,
169
+ defaultValue,
170
+ onChange: onValueChange,
171
+ });
172
+
173
+ const localRef = useRef<TextInput | null>(null);
174
+ const setFieldRef = useCallback(
175
+ (node: TextInput | null) => {
176
+ localRef.current = node;
177
+ if (inputRef) inputRef.current = node;
178
+ },
179
+ [inputRef],
180
+ );
181
+
182
+ const minHeight = Math.max(1, minLines) * LINE_HEIGHT;
183
+ const maxHeight = Math.max(minLines, maxLines) * LINE_HEIGHT;
184
+ const [contentHeight, setContentHeight] = useState(minHeight);
185
+ const height = Math.min(maxHeight, Math.max(minHeight, contentHeight));
186
+
187
+ /**
188
+ * Web autosize measures the node, native reads `onContentSizeChange`.
189
+ *
190
+ * They are not interchangeable: react-native-web reports `scrollHeight`,
191
+ * which never falls below the height already applied, so a field grown to six
192
+ * lines and then emptied would stay six lines tall. `useTextareaAutosize`
193
+ * collapses the node to measure it only when the draft may have got SHORTER —
194
+ * collapsing on every keystroke re-laid-out the whole page three times a key.
195
+ */
196
+ useTextareaAutosize(localRef, text, {
197
+ enabled: IS_WEB,
198
+ height,
199
+ minHeight,
200
+ onMeasure: setContentHeight,
201
+ });
202
+
203
+ const onContentSizeChange = useCallback(
204
+ (event: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
205
+ if (IS_WEB) return;
206
+ setContentHeight(event.nativeEvent.contentSize.height);
207
+ },
208
+ [],
209
+ );
210
+
211
+ const trimmed = text.trim();
212
+ const hasAttachments = !!attachments && attachments.length > 0;
213
+ const showSend = canSend ?? (trimmed.length > 0 || hasAttachments);
214
+
215
+ const submit = useCallback(() => {
216
+ if (disabled || !showSend) return;
217
+ onSend?.(text);
218
+ if (value === undefined) setText('');
219
+ }, [disabled, showSend, onSend, text, value, setText]);
220
+
221
+ const openSuggestions = !!suggestions && suggestions.length > 0;
222
+
223
+ const onKeyPress = useCallback(
224
+ (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
225
+ if (!IS_WEB) return;
226
+ const native = event.nativeEvent as WebKeyEvent;
227
+ // An IME candidate window is using the same keys; committing a
228
+ // composition must never send the half-written word behind it.
229
+ if (native.isComposing) return;
230
+ const mod = native.metaKey === true || native.ctrlKey === true;
231
+
232
+ if (openSuggestions && (native.key === 'ArrowDown' || native.key === 'ArrowUp')) {
233
+ event.preventDefault();
234
+ const count = suggestions?.length ?? 0;
235
+ const step = native.key === 'ArrowDown' ? 1 : -1;
236
+ const from = activeIndex < 0 ? (step > 0 ? -1 : 0) : activeIndex;
237
+ onActiveIndexChange?.((from + step + count) % count);
238
+ return;
239
+ }
240
+ if (native.key === 'Escape') {
241
+ event.preventDefault();
242
+ onEscape?.();
243
+ return;
244
+ }
245
+ if (native.key === 'ArrowUp' && text.length === 0) {
246
+ event.preventDefault();
247
+ onEditLast?.();
248
+ return;
249
+ }
250
+ if (native.key !== 'Enter') return;
251
+
252
+ if (openSuggestions && activeIndex >= 0) {
253
+ const picked = suggestions?.[activeIndex];
254
+ if (picked && !picked.disabled) {
255
+ event.preventDefault();
256
+ onSelectSuggestion?.(picked, activeIndex);
257
+ return;
258
+ }
259
+ }
260
+ if (sendOn === 'enter' ? native.shiftKey !== true && !mod : mod) {
261
+ event.preventDefault();
262
+ submit();
263
+ }
264
+ },
265
+ [
266
+ activeIndex,
267
+ onActiveIndexChange,
268
+ onEditLast,
269
+ onEscape,
270
+ onSelectSuggestion,
271
+ openSuggestions,
272
+ sendOn,
273
+ submit,
274
+ suggestions,
275
+ text.length,
276
+ ],
277
+ );
278
+
279
+ const bar: WebCssStyle = {
280
+ flexDirection: 'row',
281
+ alignItems: 'flex-end',
282
+ gap: 2,
283
+ minHeight: CONTROL_SIZE + BAR_PADDING * 2,
284
+ borderRadius: BAR_RADIUS,
285
+ borderWidth: 1,
286
+ borderColor: palette.border,
287
+ // A disabled bar changes its FILL rather than its opacity. Dimming the
288
+ // container compounds with each control's own disabled opacity — 0.55 × 0.4
289
+ // put the send disc at 0.22, which reads as a rendering fault rather than a
290
+ // state.
291
+ backgroundColor: disabled ? palette.inset : palette.surface,
292
+ paddingLeft: BAR_PADDING,
293
+ paddingRight: BAR_PADDING,
294
+ paddingTop: BAR_PADDING,
295
+ paddingBottom: BAR_PADDING,
296
+ '--bloom-chat-composer-ring': palette.focusRing,
297
+ };
298
+
299
+ const NoticeIcon = noticeIcon ?? RiForbidLine;
300
+
301
+ return (
302
+ <View
303
+ accessibilityLabel={accessibilityLabel}
304
+ style={[{ width: '100%', flexDirection: 'column', gap: 6 }, style]}
305
+ testID={testID}>
306
+ {openSuggestions ? (
307
+ <SuggestionList
308
+ kind={suggestionKind}
309
+ suggestions={suggestions ?? []}
310
+ activeIndex={activeIndex}
311
+ onActiveIndexChange={onActiveIndexChange}
312
+ onSelectSuggestion={onSelectSuggestion}
313
+ testID={testID ? `${testID}-suggestions` : undefined}
314
+ />
315
+ ) : null}
316
+
317
+ {banner}
318
+
319
+ {hasAttachments ? (
320
+ <ComposerAttachmentStrip
321
+ attachments={attachments ?? []}
322
+ onRemove={onRemoveAttachment}
323
+ testID={testID ? `${testID}-attachments` : undefined}
324
+ />
325
+ ) : null}
326
+
327
+ {recorder ?? (
328
+ <View style={bar} testID={testID ? `${testID}-bar` : undefined}>
329
+ {notice !== undefined ? (
330
+ <View
331
+ style={{
332
+ flexDirection: 'row',
333
+ alignItems: 'center',
334
+ justifyContent: 'center',
335
+ gap: 8,
336
+ flexGrow: 1,
337
+ minHeight: CONTROL_SIZE,
338
+ paddingLeft: 12,
339
+ paddingRight: 12,
340
+ }}
341
+ testID={testID ? `${testID}-notice` : undefined}>
342
+ {typeof notice === 'string' ? (
343
+ <>
344
+ <NoticeIcon width={16} height={16} fill={palette.iconSecondary} />
345
+ <Text
346
+ variant="body-2-regular"
347
+ numberOfLines={2}
348
+ style={{ color: palette.textSecondary, textAlign: 'center' }}>
349
+ {notice}
350
+ </Text>
351
+ </>
352
+ ) : (
353
+ notice
354
+ )}
355
+ </View>
356
+ ) : (
357
+ <>
358
+ {leading ??
359
+ (onAttachPress ? (
360
+ <ComposerIconButton
361
+ icon={RiAddLine}
362
+ accessibilityLabel={labels.attach}
363
+ onPress={onAttachPress}
364
+ disabled={disabled}
365
+ iconSize={22}
366
+ testID={testID ? `${testID}-attach` : undefined}
367
+ />
368
+ ) : null)}
369
+
370
+ <View
371
+ style={{
372
+ flexGrow: 1,
373
+ flexShrink: 1,
374
+ justifyContent: 'center',
375
+ minHeight: CONTROL_SIZE,
376
+ paddingLeft: 6,
377
+ paddingRight: 6,
378
+ }}>
379
+ <TextInput
380
+ ref={setFieldRef}
381
+ {...dataHook('bloomChatComposerInput')}
382
+ accessibilityLabel={labels.input}
383
+ multiline
384
+ editable={!disabled}
385
+ value={text}
386
+ onChangeText={setText}
387
+ onKeyPress={onKeyPress}
388
+ onContentSizeChange={onContentSizeChange}
389
+ onFocus={onFocus}
390
+ onBlur={onBlur}
391
+ placeholder={placeholder}
392
+ placeholderTextColor={palette.textPlaceholder}
393
+ selectionColor={palette.accent}
394
+ cursorColor={palette.accent}
395
+ scrollEnabled={height >= maxHeight}
396
+ style={{
397
+ width: '100%',
398
+ height,
399
+ maxHeight,
400
+ padding: 0,
401
+ margin: 0,
402
+ ...TYPE_SCALE['body-regular'],
403
+ fontFamily: IS_WEB ? 'var(--bloom-font-sans)' : 'Inter',
404
+ color: disabled ? palette.textSecondary : palette.text,
405
+ backgroundColor: 'transparent',
406
+ }}
407
+ testID={testID ? `${testID}-input` : undefined}
408
+ />
409
+ </View>
410
+
411
+ {onCameraPress ? (
412
+ <ComposerIconButton
413
+ icon={RiCameraLine}
414
+ accessibilityLabel={labels.camera}
415
+ onPress={onCameraPress}
416
+ disabled={disabled}
417
+ testID={testID ? `${testID}-camera` : undefined}
418
+ />
419
+ ) : null}
420
+
421
+ {emojiSlot ??
422
+ (onEmojiPress ? (
423
+ <ComposerIconButton
424
+ icon={RiEmotionLine}
425
+ accessibilityLabel={labels.emoji}
426
+ onPress={onEmojiPress}
427
+ disabled={disabled}
428
+ testID={testID ? `${testID}-emoji` : undefined}
429
+ />
430
+ ) : null)}
431
+
432
+ <View style={{ width: CONTROL_SIZE, height: CONTROL_SIZE, marginLeft: 2 }}>
433
+ <SwapLayer shown={showSend}>
434
+ <ComposerIconButton
435
+ icon={RiSendPlaneLine}
436
+ tone="accent"
437
+ accessibilityLabel={labels.send}
438
+ onPress={submit}
439
+ disabled={disabled}
440
+ iconSize={18}
441
+ testID={testID ? `${testID}-send` : undefined}
442
+ />
443
+ </SwapLayer>
444
+ <SwapLayer shown={!showSend}>
445
+ <ComposerIconButton
446
+ icon={RiMic2Line}
447
+ accessibilityLabel={labels.mic}
448
+ onPress={onMicPress}
449
+ onPressIn={onMicPressIn}
450
+ onPressOut={onMicPressOut}
451
+ disabled={disabled}
452
+ testID={testID ? `${testID}-mic` : undefined}
453
+ />
454
+ </SwapLayer>
455
+ </View>
456
+ </>
457
+ )}
458
+ </View>
459
+ )}
460
+
461
+ {showKeyboardHint && IS_WEB && notice === undefined ? (
462
+ <Text
463
+ variant="caption-2-regular"
464
+ style={{ color: palette.textPlaceholder, paddingLeft: 14 }}>
465
+ {sendOn === 'enter' ? labels.enterHint : labels.modEnterHint}
466
+ </Text>
467
+ ) : null}
468
+ </View>
469
+ );
470
+ }
471
+
472
+ return ChatComposer;
473
+ }