@oxy.so/bloom 5.1.0 → 5.1.1

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 (430) hide show
  1. package/docs/adoption-matrix.mdx +9 -9
  2. package/docs/button.mdx +2 -0
  3. package/docs/card-form.mdx +2 -0
  4. package/docs/chat-composer.mdx +1 -1
  5. package/docs/earnings.mdx +2 -0
  6. package/docs/field.mdx +2 -0
  7. package/docs/label.mdx +2 -0
  8. package/docs/payment-method.mdx +2 -0
  9. package/docs/place-details.mdx +2 -2
  10. package/docs/proof-of-delivery.mdx +4 -0
  11. package/docs/select.mdx +2 -0
  12. package/lib/commonjs/button/Button.js +36 -3
  13. package/lib/commonjs/button/Button.js.map +1 -1
  14. package/lib/commonjs/button/GlyphButton.js +7 -3
  15. package/lib/commonjs/button/GlyphButton.js.map +1 -1
  16. package/lib/commonjs/card-form/shared.js +3 -2
  17. package/lib/commonjs/card-form/shared.js.map +1 -1
  18. package/lib/commonjs/chat-composer/AttachmentMenu.js +8 -227
  19. package/lib/commonjs/chat-composer/AttachmentMenu.js.map +1 -1
  20. package/lib/commonjs/chat-composer/AttachmentMenu.web.js +16 -0
  21. package/lib/commonjs/chat-composer/AttachmentMenu.web.js.map +1 -0
  22. package/lib/commonjs/chat-composer/ChatComposer.js +9 -388
  23. package/lib/commonjs/chat-composer/ChatComposer.js.map +1 -1
  24. package/lib/commonjs/chat-composer/ChatComposer.web.js +16 -0
  25. package/lib/commonjs/chat-composer/ChatComposer.web.js.map +1 -0
  26. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.js +5 -200
  27. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.js.map +1 -1
  28. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.web.js +12 -0
  29. package/lib/commonjs/chat-composer/ComposerAttachmentStrip.web.js.map +1 -0
  30. package/lib/commonjs/chat-composer/ComposerBanner.js +5 -163
  31. package/lib/commonjs/chat-composer/ComposerBanner.js.map +1 -1
  32. package/lib/commonjs/chat-composer/ComposerBanner.web.js +12 -0
  33. package/lib/commonjs/chat-composer/ComposerBanner.web.js.map +1 -0
  34. package/lib/commonjs/chat-composer/EmojiPicker.js +6 -443
  35. package/lib/commonjs/chat-composer/EmojiPicker.js.map +1 -1
  36. package/lib/commonjs/chat-composer/EmojiPicker.web.js +14 -0
  37. package/lib/commonjs/chat-composer/EmojiPicker.web.js.map +1 -0
  38. package/lib/commonjs/chat-composer/MessageContextMenu.js +12 -102
  39. package/lib/commonjs/chat-composer/MessageContextMenu.js.map +1 -1
  40. package/lib/commonjs/chat-composer/MessageContextMenu.web.js +19 -0
  41. package/lib/commonjs/chat-composer/MessageContextMenu.web.js.map +1 -0
  42. package/lib/commonjs/chat-composer/ReactionPicker.js +6 -107
  43. package/lib/commonjs/chat-composer/ReactionPicker.js.map +1 -1
  44. package/lib/commonjs/chat-composer/ReactionPicker.web.js +14 -0
  45. package/lib/commonjs/chat-composer/ReactionPicker.web.js.map +1 -0
  46. package/lib/commonjs/chat-composer/SuggestionList.js +5 -222
  47. package/lib/commonjs/chat-composer/SuggestionList.js.map +1 -1
  48. package/lib/commonjs/chat-composer/SuggestionList.web.js +12 -0
  49. package/lib/commonjs/chat-composer/SuggestionList.web.js.map +1 -0
  50. package/lib/commonjs/chat-composer/VoiceRecorder.js +7 -263
  51. package/lib/commonjs/chat-composer/VoiceRecorder.js.map +1 -1
  52. package/lib/commonjs/chat-composer/VoiceRecorder.web.js +16 -0
  53. package/lib/commonjs/chat-composer/VoiceRecorder.web.js.map +1 -0
  54. package/lib/commonjs/chat-composer/create-attachment-menu.js +243 -0
  55. package/lib/commonjs/chat-composer/create-attachment-menu.js.map +1 -0
  56. package/lib/commonjs/chat-composer/create-chat-composer.js +400 -0
  57. package/lib/commonjs/chat-composer/create-chat-composer.js.map +1 -0
  58. package/lib/commonjs/chat-composer/create-composer-attachment-strip.js +212 -0
  59. package/lib/commonjs/chat-composer/create-composer-attachment-strip.js.map +1 -0
  60. package/lib/commonjs/chat-composer/create-composer-banner.js +176 -0
  61. package/lib/commonjs/chat-composer/create-composer-banner.js.map +1 -0
  62. package/lib/commonjs/chat-composer/create-emoji-picker.js +456 -0
  63. package/lib/commonjs/chat-composer/create-emoji-picker.js.map +1 -0
  64. package/lib/commonjs/chat-composer/create-message-context-menu.js +119 -0
  65. package/lib/commonjs/chat-composer/create-message-context-menu.js.map +1 -0
  66. package/lib/commonjs/chat-composer/create-reaction-picker.js +120 -0
  67. package/lib/commonjs/chat-composer/create-reaction-picker.js.map +1 -0
  68. package/lib/commonjs/chat-composer/create-suggestion-list.js +234 -0
  69. package/lib/commonjs/chat-composer/create-suggestion-list.js.map +1 -0
  70. package/lib/commonjs/chat-composer/create-voice-recorder.js +277 -0
  71. package/lib/commonjs/chat-composer/create-voice-recorder.js.map +1 -0
  72. package/lib/commonjs/chat-composer/index.js +9 -9
  73. package/lib/commonjs/chat-composer/index.web.js +18 -18
  74. package/lib/commonjs/chat-composer/index.web.js.map +1 -1
  75. package/lib/commonjs/earnings/EarningsSummary.js +12 -2
  76. package/lib/commonjs/earnings/EarningsSummary.js.map +1 -1
  77. package/lib/commonjs/field/Field.js +2 -0
  78. package/lib/commonjs/field/Field.js.map +1 -1
  79. package/lib/commonjs/item/Item.js +16 -8
  80. package/lib/commonjs/item/Item.js.map +1 -1
  81. package/lib/commonjs/job-board/JobCard.js +6 -2
  82. package/lib/commonjs/job-board/JobCard.js.map +1 -1
  83. package/lib/commonjs/label/Label.js +2 -1
  84. package/lib/commonjs/label/Label.js.map +1 -1
  85. package/lib/commonjs/listing-details/AmenityList.js +4 -3
  86. package/lib/commonjs/listing-details/AmenityList.js.map +1 -1
  87. package/lib/commonjs/mail-compose/MailComposeSurface.js +1 -1
  88. package/lib/commonjs/overlay/InteractionBoundary.js +28 -0
  89. package/lib/commonjs/overlay/InteractionBoundary.js.map +1 -0
  90. package/lib/commonjs/payment-method/PaymentMethodList.js +3 -2
  91. package/lib/commonjs/payment-method/PaymentMethodList.js.map +1 -1
  92. package/lib/commonjs/place-details/PlaceAmenities.js +17 -6
  93. package/lib/commonjs/place-details/PlaceAmenities.js.map +1 -1
  94. package/lib/commonjs/place-details/PlacePopularTimes.js +7 -1
  95. package/lib/commonjs/place-details/PlacePopularTimes.js.map +1 -1
  96. package/lib/commonjs/proof-of-delivery/ProofOfDelivery.js +10 -1
  97. package/lib/commonjs/proof-of-delivery/ProofOfDelivery.js.map +1 -1
  98. package/lib/commonjs/proof-of-delivery/shared.js +1 -1
  99. package/lib/commonjs/proof-of-delivery/shared.js.map +1 -1
  100. package/lib/commonjs/select/Select.js +7 -4
  101. package/lib/commonjs/select/Select.js.map +1 -1
  102. package/lib/commonjs/select/Select.web.js +7 -4
  103. package/lib/commonjs/select/Select.web.js.map +1 -1
  104. package/lib/commonjs/select/use-required-description.js +37 -0
  105. package/lib/commonjs/select/use-required-description.js.map +1 -0
  106. package/lib/module/button/Button.js +36 -3
  107. package/lib/module/button/Button.js.map +1 -1
  108. package/lib/module/button/GlyphButton.js +7 -3
  109. package/lib/module/button/GlyphButton.js.map +1 -1
  110. package/lib/module/card-form/shared.js +3 -2
  111. package/lib/module/card-form/shared.js.map +1 -1
  112. package/lib/module/chat-composer/AttachmentMenu.js +7 -226
  113. package/lib/module/chat-composer/AttachmentMenu.js.map +1 -1
  114. package/lib/module/chat-composer/AttachmentMenu.web.js +12 -0
  115. package/lib/module/chat-composer/AttachmentMenu.web.js.map +1 -0
  116. package/lib/module/chat-composer/ChatComposer.js +8 -385
  117. package/lib/module/chat-composer/ChatComposer.js.map +1 -1
  118. package/lib/module/chat-composer/ChatComposer.web.js +12 -0
  119. package/lib/module/chat-composer/ChatComposer.web.js.map +1 -0
  120. package/lib/module/chat-composer/ComposerAttachmentStrip.js +4 -196
  121. package/lib/module/chat-composer/ComposerAttachmentStrip.js.map +1 -1
  122. package/lib/module/chat-composer/ComposerAttachmentStrip.web.js +8 -0
  123. package/lib/module/chat-composer/ComposerAttachmentStrip.web.js.map +1 -0
  124. package/lib/module/chat-composer/ComposerBanner.js +4 -162
  125. package/lib/module/chat-composer/ComposerBanner.js.map +1 -1
  126. package/lib/module/chat-composer/ComposerBanner.web.js +8 -0
  127. package/lib/module/chat-composer/ComposerBanner.web.js.map +1 -0
  128. package/lib/module/chat-composer/EmojiPicker.js +5 -440
  129. package/lib/module/chat-composer/EmojiPicker.js.map +1 -1
  130. package/lib/module/chat-composer/EmojiPicker.web.js +10 -0
  131. package/lib/module/chat-composer/EmojiPicker.web.js.map +1 -0
  132. package/lib/module/chat-composer/MessageContextMenu.js +11 -99
  133. package/lib/module/chat-composer/MessageContextMenu.js.map +1 -1
  134. package/lib/module/chat-composer/MessageContextMenu.web.js +15 -0
  135. package/lib/module/chat-composer/MessageContextMenu.web.js.map +1 -0
  136. package/lib/module/chat-composer/ReactionPicker.js +5 -104
  137. package/lib/module/chat-composer/ReactionPicker.js.map +1 -1
  138. package/lib/module/chat-composer/ReactionPicker.web.js +10 -0
  139. package/lib/module/chat-composer/ReactionPicker.web.js.map +1 -0
  140. package/lib/module/chat-composer/SuggestionList.js +4 -219
  141. package/lib/module/chat-composer/SuggestionList.js.map +1 -1
  142. package/lib/module/chat-composer/SuggestionList.web.js +8 -0
  143. package/lib/module/chat-composer/SuggestionList.web.js.map +1 -0
  144. package/lib/module/chat-composer/VoiceRecorder.js +6 -260
  145. package/lib/module/chat-composer/VoiceRecorder.js.map +1 -1
  146. package/lib/module/chat-composer/VoiceRecorder.web.js +12 -0
  147. package/lib/module/chat-composer/VoiceRecorder.web.js.map +1 -0
  148. package/lib/module/chat-composer/create-attachment-menu.js +238 -0
  149. package/lib/module/chat-composer/create-attachment-menu.js.map +1 -0
  150. package/lib/module/chat-composer/create-chat-composer.js +395 -0
  151. package/lib/module/chat-composer/create-chat-composer.js.map +1 -0
  152. package/lib/module/chat-composer/create-composer-attachment-strip.js +206 -0
  153. package/lib/module/chat-composer/create-composer-attachment-strip.js.map +1 -0
  154. package/lib/module/chat-composer/create-composer-banner.js +171 -0
  155. package/lib/module/chat-composer/create-composer-banner.js.map +1 -0
  156. package/lib/module/chat-composer/create-emoji-picker.js +451 -0
  157. package/lib/module/chat-composer/create-emoji-picker.js.map +1 -0
  158. package/lib/module/chat-composer/create-message-context-menu.js +114 -0
  159. package/lib/module/chat-composer/create-message-context-menu.js.map +1 -0
  160. package/lib/module/chat-composer/create-reaction-picker.js +115 -0
  161. package/lib/module/chat-composer/create-reaction-picker.js.map +1 -0
  162. package/lib/module/chat-composer/create-suggestion-list.js +229 -0
  163. package/lib/module/chat-composer/create-suggestion-list.js.map +1 -0
  164. package/lib/module/chat-composer/create-voice-recorder.js +272 -0
  165. package/lib/module/chat-composer/create-voice-recorder.js.map +1 -0
  166. package/lib/module/chat-composer/index.js +9 -9
  167. package/lib/module/chat-composer/index.js.map +1 -1
  168. package/lib/module/chat-composer/index.web.js +9 -9
  169. package/lib/module/chat-composer/index.web.js.map +1 -1
  170. package/lib/module/earnings/EarningsSummary.js +12 -2
  171. package/lib/module/earnings/EarningsSummary.js.map +1 -1
  172. package/lib/module/field/Field.js +2 -0
  173. package/lib/module/field/Field.js.map +1 -1
  174. package/lib/module/item/Item.js +16 -8
  175. package/lib/module/item/Item.js.map +1 -1
  176. package/lib/module/job-board/JobCard.js +6 -2
  177. package/lib/module/job-board/JobCard.js.map +1 -1
  178. package/lib/module/label/Label.js +2 -1
  179. package/lib/module/label/Label.js.map +1 -1
  180. package/lib/module/listing-details/AmenityList.js +4 -3
  181. package/lib/module/listing-details/AmenityList.js.map +1 -1
  182. package/lib/module/mail-compose/MailComposeSurface.js +1 -1
  183. package/lib/module/mail-compose/MailComposeSurface.js.map +1 -1
  184. package/lib/module/overlay/InteractionBoundary.js +25 -0
  185. package/lib/module/overlay/InteractionBoundary.js.map +1 -0
  186. package/lib/module/payment-method/PaymentMethodList.js +3 -2
  187. package/lib/module/payment-method/PaymentMethodList.js.map +1 -1
  188. package/lib/module/place-details/PlaceAmenities.js +15 -4
  189. package/lib/module/place-details/PlaceAmenities.js.map +1 -1
  190. package/lib/module/place-details/PlacePopularTimes.js +7 -1
  191. package/lib/module/place-details/PlacePopularTimes.js.map +1 -1
  192. package/lib/module/proof-of-delivery/ProofOfDelivery.js +10 -1
  193. package/lib/module/proof-of-delivery/ProofOfDelivery.js.map +1 -1
  194. package/lib/module/proof-of-delivery/shared.js +1 -1
  195. package/lib/module/proof-of-delivery/shared.js.map +1 -1
  196. package/lib/module/select/Select.js +7 -4
  197. package/lib/module/select/Select.js.map +1 -1
  198. package/lib/module/select/Select.web.js +7 -4
  199. package/lib/module/select/Select.web.js.map +1 -1
  200. package/lib/module/select/use-required-description.js +33 -0
  201. package/lib/module/select/use-required-description.js.map +1 -0
  202. package/lib/typescript/commonjs/button/Button.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/card-form/shared.d.ts +2 -1
  204. package/lib/typescript/commonjs/card-form/shared.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.d.ts +1 -2
  206. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.web.d.ts +2 -0
  208. package/lib/typescript/commonjs/chat-composer/AttachmentMenu.web.d.ts.map +1 -0
  209. package/lib/typescript/commonjs/chat-composer/ChatComposer.d.ts +1 -2
  210. package/lib/typescript/commonjs/chat-composer/ChatComposer.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/chat-composer/ChatComposer.web.d.ts +2 -0
  212. package/lib/typescript/commonjs/chat-composer/ChatComposer.web.d.ts.map +1 -0
  213. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.d.ts +1 -2
  214. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.d.ts.map +1 -1
  215. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.web.d.ts +2 -0
  216. package/lib/typescript/commonjs/chat-composer/ComposerAttachmentStrip.web.d.ts.map +1 -0
  217. package/lib/typescript/commonjs/chat-composer/ComposerBanner.d.ts +1 -2
  218. package/lib/typescript/commonjs/chat-composer/ComposerBanner.d.ts.map +1 -1
  219. package/lib/typescript/commonjs/chat-composer/ComposerBanner.web.d.ts +2 -0
  220. package/lib/typescript/commonjs/chat-composer/ComposerBanner.web.d.ts.map +1 -0
  221. package/lib/typescript/commonjs/chat-composer/EmojiPicker.d.ts +1 -2
  222. package/lib/typescript/commonjs/chat-composer/EmojiPicker.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/chat-composer/EmojiPicker.web.d.ts +2 -0
  224. package/lib/typescript/commonjs/chat-composer/EmojiPicker.web.d.ts.map +1 -0
  225. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.d.ts +1 -2
  226. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.d.ts.map +1 -1
  227. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.web.d.ts +2 -0
  228. package/lib/typescript/commonjs/chat-composer/MessageContextMenu.web.d.ts.map +1 -0
  229. package/lib/typescript/commonjs/chat-composer/ReactionPicker.d.ts +1 -2
  230. package/lib/typescript/commonjs/chat-composer/ReactionPicker.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/chat-composer/ReactionPicker.web.d.ts +2 -0
  232. package/lib/typescript/commonjs/chat-composer/ReactionPicker.web.d.ts.map +1 -0
  233. package/lib/typescript/commonjs/chat-composer/SuggestionList.d.ts +1 -2
  234. package/lib/typescript/commonjs/chat-composer/SuggestionList.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/chat-composer/SuggestionList.web.d.ts +2 -0
  236. package/lib/typescript/commonjs/chat-composer/SuggestionList.web.d.ts.map +1 -0
  237. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.d.ts +1 -2
  238. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.web.d.ts +2 -0
  240. package/lib/typescript/commonjs/chat-composer/VoiceRecorder.web.d.ts.map +1 -0
  241. package/lib/typescript/commonjs/chat-composer/create-attachment-menu.d.ts +11 -0
  242. package/lib/typescript/commonjs/chat-composer/create-attachment-menu.d.ts.map +1 -0
  243. package/lib/typescript/commonjs/chat-composer/create-chat-composer.d.ts +11 -0
  244. package/lib/typescript/commonjs/chat-composer/create-chat-composer.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/chat-composer/create-composer-attachment-strip.d.ts +7 -0
  246. package/lib/typescript/commonjs/chat-composer/create-composer-attachment-strip.d.ts.map +1 -0
  247. package/lib/typescript/commonjs/chat-composer/create-composer-banner.d.ts +7 -0
  248. package/lib/typescript/commonjs/chat-composer/create-composer-banner.d.ts.map +1 -0
  249. package/lib/typescript/commonjs/chat-composer/create-emoji-picker.d.ts +9 -0
  250. package/lib/typescript/commonjs/chat-composer/create-emoji-picker.d.ts.map +1 -0
  251. package/lib/typescript/commonjs/chat-composer/create-message-context-menu.d.ts +14 -0
  252. package/lib/typescript/commonjs/chat-composer/create-message-context-menu.d.ts.map +1 -0
  253. package/lib/typescript/commonjs/chat-composer/create-reaction-picker.d.ts +9 -0
  254. package/lib/typescript/commonjs/chat-composer/create-reaction-picker.d.ts.map +1 -0
  255. package/lib/typescript/commonjs/chat-composer/create-suggestion-list.d.ts +7 -0
  256. package/lib/typescript/commonjs/chat-composer/create-suggestion-list.d.ts.map +1 -0
  257. package/lib/typescript/commonjs/chat-composer/create-voice-recorder.d.ts +11 -0
  258. package/lib/typescript/commonjs/chat-composer/create-voice-recorder.d.ts.map +1 -0
  259. package/lib/typescript/commonjs/chat-composer/index.web.d.ts +9 -9
  260. package/lib/typescript/commonjs/chat-composer/index.web.d.ts.map +1 -1
  261. package/lib/typescript/commonjs/earnings/EarningsSummary.d.ts.map +1 -1
  262. package/lib/typescript/commonjs/field/Field.d.ts +1 -1
  263. package/lib/typescript/commonjs/field/Field.d.ts.map +1 -1
  264. package/lib/typescript/commonjs/field/types.d.ts +2 -0
  265. package/lib/typescript/commonjs/field/types.d.ts.map +1 -1
  266. package/lib/typescript/commonjs/floating/types.d.ts +1 -0
  267. package/lib/typescript/commonjs/floating/types.d.ts.map +1 -1
  268. package/lib/typescript/commonjs/item/Item.d.ts.map +1 -1
  269. package/lib/typescript/commonjs/job-board/JobCard.d.ts.map +1 -1
  270. package/lib/typescript/commonjs/label/Label.d.ts +1 -1
  271. package/lib/typescript/commonjs/label/Label.d.ts.map +1 -1
  272. package/lib/typescript/commonjs/label/types.d.ts +2 -0
  273. package/lib/typescript/commonjs/label/types.d.ts.map +1 -1
  274. package/lib/typescript/commonjs/listing-details/AmenityList.d.ts.map +1 -1
  275. package/lib/typescript/commonjs/overlay/InteractionBoundary.d.ts +7 -0
  276. package/lib/typescript/commonjs/overlay/InteractionBoundary.d.ts.map +1 -0
  277. package/lib/typescript/commonjs/payment-method/PaymentMethodList.d.ts.map +1 -1
  278. package/lib/typescript/commonjs/place-details/PlaceAmenities.d.ts.map +1 -1
  279. package/lib/typescript/commonjs/place-details/PlacePopularTimes.d.ts.map +1 -1
  280. package/lib/typescript/commonjs/proof-of-delivery/ProofOfDelivery.d.ts.map +1 -1
  281. package/lib/typescript/commonjs/select/Select.d.ts.map +1 -1
  282. package/lib/typescript/commonjs/select/Select.web.d.ts.map +1 -1
  283. package/lib/typescript/commonjs/select/use-required-description.d.ts +7 -0
  284. package/lib/typescript/commonjs/select/use-required-description.d.ts.map +1 -0
  285. package/lib/typescript/module/button/Button.d.ts.map +1 -1
  286. package/lib/typescript/module/card-form/shared.d.ts +2 -1
  287. package/lib/typescript/module/card-form/shared.d.ts.map +1 -1
  288. package/lib/typescript/module/chat-composer/AttachmentMenu.d.ts +1 -2
  289. package/lib/typescript/module/chat-composer/AttachmentMenu.d.ts.map +1 -1
  290. package/lib/typescript/module/chat-composer/AttachmentMenu.web.d.ts +2 -0
  291. package/lib/typescript/module/chat-composer/AttachmentMenu.web.d.ts.map +1 -0
  292. package/lib/typescript/module/chat-composer/ChatComposer.d.ts +1 -2
  293. package/lib/typescript/module/chat-composer/ChatComposer.d.ts.map +1 -1
  294. package/lib/typescript/module/chat-composer/ChatComposer.web.d.ts +2 -0
  295. package/lib/typescript/module/chat-composer/ChatComposer.web.d.ts.map +1 -0
  296. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.d.ts +1 -2
  297. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.d.ts.map +1 -1
  298. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.web.d.ts +2 -0
  299. package/lib/typescript/module/chat-composer/ComposerAttachmentStrip.web.d.ts.map +1 -0
  300. package/lib/typescript/module/chat-composer/ComposerBanner.d.ts +1 -2
  301. package/lib/typescript/module/chat-composer/ComposerBanner.d.ts.map +1 -1
  302. package/lib/typescript/module/chat-composer/ComposerBanner.web.d.ts +2 -0
  303. package/lib/typescript/module/chat-composer/ComposerBanner.web.d.ts.map +1 -0
  304. package/lib/typescript/module/chat-composer/EmojiPicker.d.ts +1 -2
  305. package/lib/typescript/module/chat-composer/EmojiPicker.d.ts.map +1 -1
  306. package/lib/typescript/module/chat-composer/EmojiPicker.web.d.ts +2 -0
  307. package/lib/typescript/module/chat-composer/EmojiPicker.web.d.ts.map +1 -0
  308. package/lib/typescript/module/chat-composer/MessageContextMenu.d.ts +1 -2
  309. package/lib/typescript/module/chat-composer/MessageContextMenu.d.ts.map +1 -1
  310. package/lib/typescript/module/chat-composer/MessageContextMenu.web.d.ts +2 -0
  311. package/lib/typescript/module/chat-composer/MessageContextMenu.web.d.ts.map +1 -0
  312. package/lib/typescript/module/chat-composer/ReactionPicker.d.ts +1 -2
  313. package/lib/typescript/module/chat-composer/ReactionPicker.d.ts.map +1 -1
  314. package/lib/typescript/module/chat-composer/ReactionPicker.web.d.ts +2 -0
  315. package/lib/typescript/module/chat-composer/ReactionPicker.web.d.ts.map +1 -0
  316. package/lib/typescript/module/chat-composer/SuggestionList.d.ts +1 -2
  317. package/lib/typescript/module/chat-composer/SuggestionList.d.ts.map +1 -1
  318. package/lib/typescript/module/chat-composer/SuggestionList.web.d.ts +2 -0
  319. package/lib/typescript/module/chat-composer/SuggestionList.web.d.ts.map +1 -0
  320. package/lib/typescript/module/chat-composer/VoiceRecorder.d.ts +1 -2
  321. package/lib/typescript/module/chat-composer/VoiceRecorder.d.ts.map +1 -1
  322. package/lib/typescript/module/chat-composer/VoiceRecorder.web.d.ts +2 -0
  323. package/lib/typescript/module/chat-composer/VoiceRecorder.web.d.ts.map +1 -0
  324. package/lib/typescript/module/chat-composer/create-attachment-menu.d.ts +11 -0
  325. package/lib/typescript/module/chat-composer/create-attachment-menu.d.ts.map +1 -0
  326. package/lib/typescript/module/chat-composer/create-chat-composer.d.ts +11 -0
  327. package/lib/typescript/module/chat-composer/create-chat-composer.d.ts.map +1 -0
  328. package/lib/typescript/module/chat-composer/create-composer-attachment-strip.d.ts +7 -0
  329. package/lib/typescript/module/chat-composer/create-composer-attachment-strip.d.ts.map +1 -0
  330. package/lib/typescript/module/chat-composer/create-composer-banner.d.ts +7 -0
  331. package/lib/typescript/module/chat-composer/create-composer-banner.d.ts.map +1 -0
  332. package/lib/typescript/module/chat-composer/create-emoji-picker.d.ts +9 -0
  333. package/lib/typescript/module/chat-composer/create-emoji-picker.d.ts.map +1 -0
  334. package/lib/typescript/module/chat-composer/create-message-context-menu.d.ts +14 -0
  335. package/lib/typescript/module/chat-composer/create-message-context-menu.d.ts.map +1 -0
  336. package/lib/typescript/module/chat-composer/create-reaction-picker.d.ts +9 -0
  337. package/lib/typescript/module/chat-composer/create-reaction-picker.d.ts.map +1 -0
  338. package/lib/typescript/module/chat-composer/create-suggestion-list.d.ts +7 -0
  339. package/lib/typescript/module/chat-composer/create-suggestion-list.d.ts.map +1 -0
  340. package/lib/typescript/module/chat-composer/create-voice-recorder.d.ts +11 -0
  341. package/lib/typescript/module/chat-composer/create-voice-recorder.d.ts.map +1 -0
  342. package/lib/typescript/module/chat-composer/index.web.d.ts +9 -9
  343. package/lib/typescript/module/chat-composer/index.web.d.ts.map +1 -1
  344. package/lib/typescript/module/earnings/EarningsSummary.d.ts.map +1 -1
  345. package/lib/typescript/module/field/Field.d.ts +1 -1
  346. package/lib/typescript/module/field/Field.d.ts.map +1 -1
  347. package/lib/typescript/module/field/types.d.ts +2 -0
  348. package/lib/typescript/module/field/types.d.ts.map +1 -1
  349. package/lib/typescript/module/floating/types.d.ts +1 -0
  350. package/lib/typescript/module/floating/types.d.ts.map +1 -1
  351. package/lib/typescript/module/item/Item.d.ts.map +1 -1
  352. package/lib/typescript/module/job-board/JobCard.d.ts.map +1 -1
  353. package/lib/typescript/module/label/Label.d.ts +1 -1
  354. package/lib/typescript/module/label/Label.d.ts.map +1 -1
  355. package/lib/typescript/module/label/types.d.ts +2 -0
  356. package/lib/typescript/module/label/types.d.ts.map +1 -1
  357. package/lib/typescript/module/listing-details/AmenityList.d.ts.map +1 -1
  358. package/lib/typescript/module/overlay/InteractionBoundary.d.ts +7 -0
  359. package/lib/typescript/module/overlay/InteractionBoundary.d.ts.map +1 -0
  360. package/lib/typescript/module/payment-method/PaymentMethodList.d.ts.map +1 -1
  361. package/lib/typescript/module/place-details/PlaceAmenities.d.ts.map +1 -1
  362. package/lib/typescript/module/place-details/PlacePopularTimes.d.ts.map +1 -1
  363. package/lib/typescript/module/proof-of-delivery/ProofOfDelivery.d.ts.map +1 -1
  364. package/lib/typescript/module/select/Select.d.ts.map +1 -1
  365. package/lib/typescript/module/select/Select.web.d.ts.map +1 -1
  366. package/lib/typescript/module/select/use-required-description.d.ts +7 -0
  367. package/lib/typescript/module/select/use-required-description.d.ts.map +1 -0
  368. package/package.json +1 -1
  369. package/src/__tests__/support/adoption-matrix.ts +708 -0
  370. package/src/__tests__/support/card-surface.ts +17 -0
  371. package/src/__tests__/support/collision-fixture-barrel.ts +20 -0
  372. package/src/__tests__/support/commerce-harness.tsx +97 -0
  373. package/src/__tests__/support/composite.ts +68 -0
  374. package/src/__tests__/support/constructed-style-sheets.ts +68 -0
  375. package/src/__tests__/support/press-host.ts +30 -0
  376. package/src/__tests__/support/rendered-style.ts +99 -0
  377. package/src/__tests__/support/unread-hook-fixture.ts +33 -0
  378. package/src/__tests__/support/worklet-capture-fixture.tsx +28 -0
  379. package/src/button/Button.tsx +35 -10
  380. package/src/button/GlyphButton.tsx +3 -3
  381. package/src/card-form/shared.ts +3 -2
  382. package/src/chat-composer/AttachmentMenu.tsx +2 -214
  383. package/src/chat-composer/AttachmentMenu.web.tsx +5 -0
  384. package/src/chat-composer/ChatComposer.tsx +2 -459
  385. package/src/chat-composer/ChatComposer.web.tsx +6 -0
  386. package/src/chat-composer/ComposerAttachmentStrip.tsx +2 -202
  387. package/src/chat-composer/ComposerAttachmentStrip.web.tsx +4 -0
  388. package/src/chat-composer/ComposerBanner.tsx +2 -157
  389. package/src/chat-composer/ComposerBanner.web.tsx +4 -0
  390. package/src/chat-composer/EmojiPicker.tsx +2 -402
  391. package/src/chat-composer/EmojiPicker.web.tsx +5 -0
  392. package/src/chat-composer/MessageContextMenu.tsx +2 -88
  393. package/src/chat-composer/MessageContextMenu.web.tsx +12 -0
  394. package/src/chat-composer/ReactionPicker.tsx +2 -100
  395. package/src/chat-composer/ReactionPicker.web.tsx +5 -0
  396. package/src/chat-composer/SuggestionList.tsx +2 -209
  397. package/src/chat-composer/SuggestionList.web.tsx +4 -0
  398. package/src/chat-composer/VoiceRecorder.tsx +2 -287
  399. package/src/chat-composer/VoiceRecorder.web.tsx +6 -0
  400. package/src/chat-composer/create-attachment-menu.tsx +228 -0
  401. package/src/chat-composer/create-chat-composer.tsx +473 -0
  402. package/src/chat-composer/create-composer-attachment-strip.tsx +212 -0
  403. package/src/chat-composer/create-composer-banner.tsx +167 -0
  404. package/src/chat-composer/create-emoji-picker.tsx +414 -0
  405. package/src/chat-composer/create-message-context-menu.tsx +112 -0
  406. package/src/chat-composer/create-reaction-picker.tsx +112 -0
  407. package/src/chat-composer/create-suggestion-list.tsx +219 -0
  408. package/src/chat-composer/create-voice-recorder.tsx +301 -0
  409. package/src/chat-composer/index.web.ts +9 -9
  410. package/src/earnings/EarningsSummary.tsx +9 -2
  411. package/src/field/Field.tsx +2 -1
  412. package/src/field/types.ts +2 -0
  413. package/src/floating/types.ts +1 -0
  414. package/src/item/Item.tsx +16 -11
  415. package/src/job-board/JobCard.tsx +4 -1
  416. package/src/label/Label.tsx +2 -1
  417. package/src/label/types.ts +2 -0
  418. package/src/listing-details/AmenityList.tsx +4 -3
  419. package/src/overlay/InteractionBoundary.tsx +24 -0
  420. package/src/payment-method/PaymentMethodList.tsx +2 -1
  421. package/src/place-details/PlaceAmenities.tsx +9 -0
  422. package/src/place-details/PlacePopularTimes.tsx +7 -1
  423. package/src/proof-of-delivery/ProofOfDelivery.tsx +9 -1
  424. package/src/proof-of-delivery/shared.ts +1 -1
  425. package/src/select/Select.tsx +5 -1
  426. package/src/select/Select.web.tsx +5 -1
  427. package/src/select/use-required-description.tsx +20 -0
  428. package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +9346 -0
  429. package/src/theme/__tests__/__fixtures__/tonal-glass-primary-failures.json +69 -0
  430. package/src/theme/__tests__/fixtures/color-engine-golden.json +1 -0
@@ -0,0 +1,414 @@
1
+ import { useCardFill } from '../card/use-card-fill';
2
+ import type { Surface as SurfaceComponent } from '../surface';
3
+ /**
4
+ * A controlled, presentational emoji grid.
5
+ *
6
+ * BLOOM SHIPS NO EMOJI DATASET, and that is the design rather than an omission:
7
+ * a full set with names and keywords is tens of kilobytes that every app with
8
+ * its own would still pay for, and emoji names are localised. `groups` arrives
9
+ * as a prop. The object form of an entry (`{ char, name, keywords }`) is what
10
+ * the built-in search matches on; a dataset of bare glyphs still renders, it
11
+ * just only matches a pasted glyph — which is the honest behaviour, not a
12
+ * silent one.
13
+ *
14
+ * The grid is a `FlatList` on BOTH platforms, over pre-chunked ROWS rather than
15
+ * single emoji, with exact `getItemLayout` offsets. A few thousand entries is
16
+ * the normal case: at eight columns that is a few hundred rows, of which a
17
+ * dozen are mounted, and the exact offsets are what let a category tab jump
18
+ * straight to its header instead of estimating.
19
+ */
20
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
21
+ import type { Button as ButtonComponent } from '../button';
22
+ import { FlatList, Pressable, TextInput, View } from 'react-native';
23
+
24
+ import { RiEmotionLine } from '../icons/remix/RiEmotionLine';
25
+ import { RiSearchLine } from '../icons/remix/RiSearchLine';
26
+ import { useControllableState } from '../hooks/use-controllable-state';
27
+ import type { WebCssStyle } from '../styles/web-view-style';
28
+ import { useTheme } from '../theme/use-theme';
29
+ import { Text } from '../typography';
30
+ import { TYPE_SCALE } from '../typography/scale';
31
+ import {
32
+ EMOJI_CATEGORY_ICONS,
33
+ EMOJI_CATEGORY_SIZE,
34
+ EMOJI_CELL,
35
+ PANEL_RADIUS,
36
+ SKIN_TONE_SWATCHES,
37
+ applySkinTone,
38
+ emojiChar,
39
+ filterEmojiGroups,
40
+ resolveChatComposerPalette,
41
+ } from './shared';
42
+ import type { EmojiEntry, EmojiGroup, EmojiPickerProps } from './types';
43
+ import { dataHook, useChatComposerWebCss } from './web-hooks';
44
+ import { useMessages } from '../locale/messages';
45
+ import { CHAT_COMPOSER_MESSAGES } from './messages';
46
+
47
+ /** Platform dependencies are bound once; shared rendering adds no wrapper. */
48
+ export function createEmojiPicker({ Surface, Button }: {
49
+ Surface: typeof SurfaceComponent;
50
+ Button: typeof ButtonComponent;
51
+ }) {
52
+
53
+ const HEADER_HEIGHT = 26;
54
+ const EMOJI_TAB = '__emoji';
55
+
56
+ type Row =
57
+ | { kind: 'header'; key: string; label: string }
58
+ | { kind: 'emojis'; key: string; entries: EmojiEntry[] };
59
+
60
+ function chunk(entries: ReadonlyArray<EmojiEntry>, columns: number): EmojiEntry[][] {
61
+ const out: EmojiEntry[][] = [];
62
+ for (let i = 0; i < entries.length; i += columns) out.push(entries.slice(i, i + columns));
63
+ return out;
64
+ }
65
+
66
+ function entryName(entry: EmojiEntry, char: string): string {
67
+ return typeof entry === 'string' ? char : (entry.name ?? char);
68
+ }
69
+
70
+ function EmojiPicker({
71
+ groups,
72
+ onSelectEmoji,
73
+ activeGroup,
74
+ defaultActiveGroup,
75
+ onActiveGroupChange,
76
+ query,
77
+ defaultQuery = '',
78
+ onQueryChange,
79
+ filter = true,
80
+ frequentlyUsed,
81
+ skinTone,
82
+ defaultSkinTone = 0,
83
+ onSkinToneChange,
84
+ columns = 8,
85
+ height = 288,
86
+ tabs,
87
+ activeTab,
88
+ onActiveTabChange,
89
+ labels: labelOverrides,
90
+ style,
91
+ testID,
92
+ accessibilityLabel: accessibilityLabelProp,
93
+ }: EmojiPickerProps) {
94
+ const theme = useTheme();
95
+ const palette = resolveChatComposerPalette(theme, useCardFill(style));
96
+ useChatComposerWebCss();
97
+ const { messages } = useMessages(CHAT_COMPOSER_MESSAGES);
98
+ const accessibilityLabel = accessibilityLabelProp ?? messages.emojiPicker;
99
+ const labels = {
100
+ search: messages.searchEmoji,
101
+ empty: messages.noEmoji,
102
+ frequent: messages.frequentlyUsed,
103
+ skinTone: messages.skinTone,
104
+ emojiTab: messages.emoji,
105
+ ...labelOverrides,
106
+ };
107
+
108
+ const [search, setSearch] = useControllableState<string>({
109
+ value: query,
110
+ defaultValue: defaultQuery,
111
+ onChange: onQueryChange,
112
+ });
113
+ const [tone, setTone] = useControllableState<number>({
114
+ value: skinTone,
115
+ defaultValue: defaultSkinTone,
116
+ onChange: onSkinToneChange,
117
+ });
118
+ const [category, setCategory] = useControllableState<string>({
119
+ value: activeGroup,
120
+ defaultValue: defaultActiveGroup ?? groups[0]?.key ?? '',
121
+ onChange: onActiveGroupChange,
122
+ });
123
+ const [tab, setTab] = useControllableState<string>({
124
+ value: activeTab,
125
+ defaultValue: EMOJI_TAB,
126
+ onChange: onActiveTabChange,
127
+ });
128
+ const [toneOpen, setToneOpen] = useState(false);
129
+ const listRef = useRef<FlatList<Row> | null>(null);
130
+
131
+ const visible = useMemo(
132
+ () => (filter ? filterEmojiGroups(groups, search) : groups),
133
+ [filter, groups, search],
134
+ );
135
+
136
+ const { rows, offsets, heights, headerIndex } = useMemo(() => {
137
+ const all: EmojiGroup[] = [];
138
+ if (frequentlyUsed && frequentlyUsed.length > 0 && !search.trim()) {
139
+ all.push({ key: 'frequent', label: labels.frequent, emojis: frequentlyUsed });
140
+ }
141
+ all.push(...visible);
142
+
143
+ const built: Row[] = [];
144
+ const index: Record<string, number> = {};
145
+ for (const group of all) {
146
+ index[group.key] = built.length;
147
+ built.push({ kind: 'header', key: `h-${group.key}`, label: group.label });
148
+ chunk(group.emojis, columns).forEach((entries, i) =>
149
+ built.push({ kind: 'emojis', key: `${group.key}-${i}`, entries }),
150
+ );
151
+ }
152
+ const rowHeights = built.map((row) => (row.kind === 'header' ? HEADER_HEIGHT : EMOJI_CELL));
153
+ const rowOffsets: number[] = [];
154
+ let running = 0;
155
+ for (const h of rowHeights) {
156
+ rowOffsets.push(running);
157
+ running += h;
158
+ }
159
+ return { rows: built, offsets: rowOffsets, heights: rowHeights, headerIndex: index };
160
+ }, [columns, frequentlyUsed, labels.frequent, search, visible]);
161
+
162
+ const jumpTo = useCallback(
163
+ (key: string) => {
164
+ setCategory(key);
165
+ const at = headerIndex[key];
166
+ if (at === undefined) return;
167
+ listRef.current?.scrollToOffset({ offset: offsets[at] ?? 0, animated: true });
168
+ },
169
+ [headerIndex, offsets, setCategory],
170
+ );
171
+
172
+ const renderRow = useCallback(
173
+ ({ item }: { item: Row }) => {
174
+ if (item.kind === 'header') {
175
+ return (
176
+ <View style={{ height: HEADER_HEIGHT, justifyContent: 'flex-end', paddingLeft: 6 }}>
177
+ <Text variant="caption-1-medium" style={{ color: palette.textSecondary }}>
178
+ {item.label}
179
+ </Text>
180
+ </View>
181
+ );
182
+ }
183
+ return (
184
+ <View style={{ flexDirection: 'row', height: EMOJI_CELL }}>
185
+ {item.entries.map((entry, i) => {
186
+ const base = emojiChar(entry);
187
+ const char = applySkinTone(base, tone);
188
+ return (
189
+ <Button appearance="plain" tone="neutral"
190
+ key={`${base}-${i}`}
191
+ accessibilityLabel={entryName(entry, char)}
192
+ onPress={() => onSelectEmoji?.(char)}
193
+ style={{ padding: 0, minWidth: 0, minHeight: 0, flexShrink: 0,
194
+ width: EMOJI_CELL,
195
+ height: EMOJI_CELL,
196
+ alignItems: 'center',
197
+ justifyContent: 'center',
198
+ borderRadius: 8,
199
+ }}
200
+ testID={testID ? `${testID}-emoji-${base}` : undefined}>
201
+ <Text variant="title-2-regular">{char}</Text>
202
+ </Button>
203
+ );
204
+ })}
205
+ </View>
206
+ );
207
+ },
208
+ [onSelectEmoji, palette.textSecondary, testID, tone],
209
+ );
210
+
211
+ const panel: WebCssStyle = {
212
+ borderRadius: PANEL_RADIUS,
213
+ paddingTop: 8,
214
+ paddingBottom: 8,
215
+ paddingLeft: 8,
216
+ paddingRight: 8,
217
+ gap: 8,
218
+ '--bloom-chat-composer-ring': palette.focusRing,
219
+ };
220
+
221
+ const topTabs = [{ key: EMOJI_TAB, label: labels.emojiTab, icon: RiEmotionLine }, ...(tabs ?? [])];
222
+ const activeCustom = tabs?.find((t) => t.key === tab);
223
+
224
+ return (
225
+ <Surface accessibilityLabel={accessibilityLabel} style={[panel, style]} testID={testID}>
226
+ {tabs && tabs.length > 0 ? (
227
+ <View
228
+ accessibilityRole="tablist"
229
+ style={{ flexDirection: 'row', gap: 4 }}
230
+ testID={testID ? `${testID}-tabs` : undefined}>
231
+ {topTabs.map((entry) => {
232
+ const selected = entry.key === tab;
233
+ return (
234
+ <Pressable
235
+ key={entry.key}
236
+ {...dataHook('bloomChatComposerRow')}
237
+ accessibilityRole="tab"
238
+ accessibilityLabel={entry.label}
239
+ aria-selected={selected}
240
+ accessibilityState={{ selected }}
241
+ onPress={() => setTab(entry.key)}
242
+ style={{
243
+ flexGrow: 1,
244
+ alignItems: 'center',
245
+ justifyContent: 'center',
246
+ height: 30,
247
+ borderRadius: 9999,
248
+ backgroundColor: selected ? palette.accentSoft : 'transparent',
249
+ }}
250
+ testID={testID ? `${testID}-tab-${entry.key}` : undefined}>
251
+ <Text
252
+ variant="body-2-medium"
253
+ style={{ color: selected ? palette.accentStrong : palette.textSecondary }}>
254
+ {entry.label}
255
+ </Text>
256
+ </Pressable>
257
+ );
258
+ })}
259
+ </View>
260
+ ) : null}
261
+
262
+ {activeCustom ? (
263
+ <View style={{ height }}>{activeCustom.content}</View>
264
+ ) : (
265
+ <>
266
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
267
+ <View
268
+ style={{
269
+ flexGrow: 1,
270
+ flexShrink: 1,
271
+ flexDirection: 'row',
272
+ alignItems: 'center',
273
+ gap: 6,
274
+ height: 32,
275
+ borderRadius: 10,
276
+ backgroundColor: palette.inset,
277
+ paddingLeft: 8,
278
+ paddingRight: 8,
279
+ }}>
280
+ <RiSearchLine width={16} height={16} fill={palette.iconSecondary} />
281
+ <TextInput
282
+ {...dataHook('bloomChatComposerInput')}
283
+ accessibilityLabel={labels.search}
284
+ placeholder={labels.search}
285
+ placeholderTextColor={palette.textPlaceholder}
286
+ value={search}
287
+ onChangeText={setSearch}
288
+ selectionColor={palette.accent}
289
+ style={{
290
+ flexGrow: 1,
291
+ flexShrink: 1,
292
+ padding: 0,
293
+ margin: 0,
294
+ ...TYPE_SCALE['body-2-regular'],
295
+ color: palette.text,
296
+ backgroundColor: 'transparent',
297
+ }}
298
+ testID={testID ? `${testID}-search` : undefined}
299
+ />
300
+ </View>
301
+ <Button appearance="plain" tone="neutral"
302
+ accessibilityLabel={labels.skinTone}
303
+ aria-expanded={toneOpen}
304
+ onPress={() => setToneOpen(!toneOpen)}
305
+ style={{ padding: 0, minWidth: 0, minHeight: 0, flexShrink: 0,
306
+ width: 32,
307
+ height: 32,
308
+ alignItems: 'center',
309
+ justifyContent: 'center',
310
+ borderRadius: 9999,
311
+ backgroundColor: toneOpen ? palette.hover : palette.inset,
312
+ }}
313
+ testID={testID ? `${testID}-skin-tone` : undefined}>
314
+ <Text variant="body-regular">{SKIN_TONE_SWATCHES[tone] ?? SKIN_TONE_SWATCHES[0]}</Text>
315
+ </Button>
316
+ </View>
317
+
318
+ {toneOpen ? (
319
+ <View
320
+ style={{ flexDirection: 'row', gap: 2, justifyContent: 'flex-end' }}
321
+ testID={testID ? `${testID}-skin-tones` : undefined}>
322
+ {SKIN_TONE_SWATCHES.map((swatch, index) => {
323
+ const selected = index === tone;
324
+ return (
325
+ <Button appearance="plain" tone="neutral"
326
+ key={index}
327
+ accessibilityLabel={`${labels.skinTone} ${index + 1}`}
328
+ pressed={selected}
329
+ onPress={() => {
330
+ setTone(index);
331
+ setToneOpen(false);
332
+ }}
333
+ style={{ padding: 0, minWidth: 0, minHeight: 0, flexShrink: 0,
334
+ width: 30,
335
+ height: 30,
336
+ alignItems: 'center',
337
+ justifyContent: 'center',
338
+ borderRadius: 9999,
339
+ backgroundColor: selected ? palette.accentSoft : 'transparent',
340
+ }}
341
+ testID={testID ? `${testID}-skin-tone-${index}` : undefined}>
342
+ <Text variant="body-regular">{swatch}</Text>
343
+ </Button>
344
+ );
345
+ })}
346
+ </View>
347
+ ) : null}
348
+
349
+ <View
350
+ accessibilityRole="tablist"
351
+ style={{ flexDirection: 'row', justifyContent: 'space-between' }}
352
+ testID={testID ? `${testID}-categories` : undefined}>
353
+ {groups.map((group) => {
354
+ const selected = group.key === category;
355
+ const Glyph = group.icon ?? EMOJI_CATEGORY_ICONS[group.key] ?? RiEmotionLine;
356
+ return (
357
+ <Pressable
358
+ key={group.key}
359
+ {...dataHook('bloomChatComposerControl')}
360
+ accessibilityRole="tab"
361
+ accessibilityLabel={group.label}
362
+ aria-selected={selected}
363
+ accessibilityState={{ selected }}
364
+ onPress={() => jumpTo(group.key)}
365
+ style={{
366
+ width: EMOJI_CATEGORY_SIZE,
367
+ height: EMOJI_CATEGORY_SIZE,
368
+ alignItems: 'center',
369
+ justifyContent: 'center',
370
+ borderRadius: 9999,
371
+ backgroundColor: selected ? palette.accentSoft : 'transparent',
372
+ }}
373
+ testID={testID ? `${testID}-category-${group.key}` : undefined}>
374
+ <Glyph
375
+ width={18}
376
+ height={18}
377
+ fill={selected ? palette.accentStrong : palette.iconSecondary}
378
+ />
379
+ </Pressable>
380
+ );
381
+ })}
382
+ </View>
383
+
384
+ {rows.length === 0 ? (
385
+ <View style={{ height, alignItems: 'center', justifyContent: 'center' }}>
386
+ <Text variant="body-2-regular" style={{ color: palette.textSecondary }}>
387
+ {labels.empty}
388
+ </Text>
389
+ </View>
390
+ ) : (
391
+ <FlatList
392
+ ref={listRef}
393
+ {...dataHook('bloomChatComposerScroll')}
394
+ data={rows}
395
+ keyExtractor={(row) => row.key}
396
+ renderItem={renderRow}
397
+ getItemLayout={(_data, index) => ({
398
+ length: heights[index] ?? EMOJI_CELL,
399
+ offset: offsets[index] ?? 0,
400
+ index,
401
+ })}
402
+ style={{ height }}
403
+ showsVerticalScrollIndicator={false}
404
+ testID={testID ? `${testID}-grid` : undefined}
405
+ />
406
+ )}
407
+ </>
408
+ )}
409
+ </Surface>
410
+ );
411
+ }
412
+
413
+ return EmojiPicker;
414
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The long-press / right-click menu for one message: the quick reaction bar on
3
+ * top, then the rows the app decided apply.
4
+ *
5
+ * Built on `DropdownMenu`, which is already an anchored panel on a pointer and
6
+ * a bottom sheet on a phone — so the rows, their destructive colour, their
7
+ * dismissal and their keyboard behaviour are the ones Bloom already gates,
8
+ * and this part only decides what goes in them.
9
+ *
10
+ * `items` is a prop and not a fixed list: which actions exist depends on who
11
+ * sent the message, how old it is and what the channel allows, and a menu that
12
+ * hid its own rows would be deciding policy the app owns.
13
+ */
14
+ import React from 'react';
15
+ import { View } from 'react-native';
16
+
17
+ import type {
18
+ DropdownMenu as DropdownMenuComponent,
19
+ DropdownMenuContent as DropdownMenuContentComponent,
20
+ DropdownMenuItem as DropdownMenuItemComponent,
21
+ DropdownMenuSeparator as DropdownMenuSeparatorComponent,
22
+ DropdownMenuShortcut as DropdownMenuShortcutComponent,
23
+ DropdownMenuTrigger as DropdownMenuTriggerComponent,
24
+ } from '../dropdown-menu';
25
+ import { useTheme } from '../theme/use-theme';
26
+ import type { ReactionPicker as ReactionPickerComponent } from './ReactionPicker';
27
+ import { REACTION_PICKER_EMOJIS, resolveChatComposerPalette } from './shared';
28
+ import type { MessageContextMenuProps } from './types';
29
+ import { useMessages } from '../locale/messages';
30
+ import { CHAT_COMPOSER_MESSAGES } from './messages';
31
+
32
+ /** Platform dependencies are bound once; shared rendering adds no wrapper. */
33
+ export function createMessageContextMenu({ DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, ReactionPicker }: {
34
+ DropdownMenu: typeof DropdownMenuComponent;
35
+ DropdownMenuContent: typeof DropdownMenuContentComponent;
36
+ DropdownMenuItem: typeof DropdownMenuItemComponent;
37
+ DropdownMenuSeparator: typeof DropdownMenuSeparatorComponent;
38
+ DropdownMenuShortcut: typeof DropdownMenuShortcutComponent;
39
+ DropdownMenuTrigger: typeof DropdownMenuTriggerComponent;
40
+ ReactionPicker: typeof ReactionPickerComponent;
41
+ }) {
42
+
43
+ function MessageContextMenu({
44
+ children,
45
+ open,
46
+ defaultOpen,
47
+ onOpenChange,
48
+ items,
49
+ onSelect,
50
+ reactions = REACTION_PICKER_EMOJIS,
51
+ selectedReaction,
52
+ onSelectReaction,
53
+ onMoreReactions,
54
+ label: labelProp,
55
+ style,
56
+ reactionBarStyle,
57
+ testID,
58
+ }: MessageContextMenuProps) {
59
+ const theme = useTheme();
60
+ const { messages } = useMessages(CHAT_COMPOSER_MESSAGES);
61
+ const label = labelProp ?? messages.messageActions;
62
+ const palette = resolveChatComposerPalette(theme);
63
+ const showReactions = reactions !== false && reactions.length > 0;
64
+
65
+ return (
66
+ <DropdownMenu open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>
67
+ <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
68
+ <DropdownMenuContent label={label} minWidth={224} style={style} testID={testID}>
69
+ {showReactions ? (
70
+ <View style={{ paddingBottom: 4 }}>
71
+ <ReactionPicker
72
+ emojis={reactions}
73
+ selected={selectedReaction}
74
+ onSelectEmoji={onSelectReaction}
75
+ onMorePress={onMoreReactions}
76
+ size="small"
77
+ surface={false}
78
+ style={[{ alignSelf: 'stretch', justifyContent: 'space-between' }, reactionBarStyle]}
79
+ testID={testID ? `${testID}-reactions` : undefined}
80
+ />
81
+ <View style={{ height: 1, backgroundColor: palette.border, marginTop: 4 }} />
82
+ </View>
83
+ ) : null}
84
+ {items.map((item) => (
85
+ <React.Fragment key={item.id}>
86
+ {item.separated ? <DropdownMenuSeparator /> : null}
87
+ <DropdownMenuItem
88
+ disabled={item.disabled}
89
+ variant={item.variant}
90
+ leading={
91
+ item.icon ? (
92
+ <item.icon
93
+ width={18}
94
+ height={18}
95
+ fill={item.variant === 'destructive' ? palette.destructive : palette.iconSecondary}
96
+ />
97
+ ) : undefined
98
+ }
99
+ trailing={item.shortcut ? <DropdownMenuShortcut>{item.shortcut}</DropdownMenuShortcut> : undefined}
100
+ onPress={() => onSelect?.(item.id, item)}
101
+ testID={testID ? `${testID}-${item.id}` : undefined}>
102
+ {item.label}
103
+ </DropdownMenuItem>
104
+ </React.Fragment>
105
+ ))}
106
+ </DropdownMenuContent>
107
+ </DropdownMenu>
108
+ );
109
+ }
110
+
111
+ return MessageContextMenu;
112
+ }
@@ -0,0 +1,112 @@
1
+ import { useSurfaceFill } from '../styles/surface-levels';
2
+ import { useCardFill } from '../card/use-card-fill';
3
+ import type { Surface as SurfaceComponent } from '../surface';
4
+ /**
5
+ * The quick reaction bar: six glyphs and a "+" that hands over to the full
6
+ * `EmojiPicker`. It is its own part rather than a mode of the picker because it
7
+ * is shown in a different place (over a message, above its menu) and must stay
8
+ * one row tall at 390px.
9
+ */
10
+ import React from 'react';
11
+ import { View } from 'react-native';
12
+
13
+ import type { Button as ButtonComponent } from '../button';
14
+ import { RiAddLine } from '../icons/remix/RiAddLine';
15
+ import type { WebCssStyle } from '../styles/web-view-style';
16
+ import { useTheme } from '../theme/use-theme';
17
+ import { Text } from '../typography';
18
+ import { REACTION_PICKER_EMOJIS, resolveChatComposerPalette } from './shared';
19
+ import type { ReactionPickerProps } 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 createReactionPicker({ Surface, Button }: {
26
+ Surface: typeof SurfaceComponent;
27
+ Button: typeof ButtonComponent;
28
+ }) {
29
+
30
+ const BOX = { small: 30, medium: 36 } as const;
31
+ const GLYPH = { small: 'title-3-regular', medium: 'title-2-regular' } as const;
32
+
33
+ function ReactionPicker({
34
+ emojis = REACTION_PICKER_EMOJIS,
35
+ selected,
36
+ onSelectEmoji,
37
+ onMorePress,
38
+ moreLabel: moreLabelProp,
39
+ size = 'medium',
40
+ surface = true,
41
+ style,
42
+ testID,
43
+ accessibilityLabel: accessibilityLabelProp,
44
+ emojiLabel,
45
+ }: ReactionPickerProps) {
46
+ const theme = useTheme();
47
+ const raisedFill = useCardFill(style);
48
+ const parentFill = useSurfaceFill();
49
+ const palette = resolveChatComposerPalette(theme, surface ? raisedFill : parentFill);
50
+ const { messages } = useMessages(CHAT_COMPOSER_MESSAGES);
51
+ const moreLabel = moreLabelProp ?? messages.moreReactions;
52
+ const accessibilityLabel = accessibilityLabelProp ?? messages.quickReactions;
53
+ useChatComposerWebCss();
54
+ const box = BOX[size];
55
+
56
+ const Container = surface ? Surface : View;
57
+ const bar: WebCssStyle = {
58
+ flexDirection: 'row',
59
+ alignItems: 'center',
60
+ gap: 2,
61
+ alignSelf: 'flex-start',
62
+ borderRadius: 9999,
63
+ paddingLeft: 4,
64
+ paddingRight: 4,
65
+ paddingTop: 4,
66
+ paddingBottom: 4,
67
+ '--bloom-chat-composer-ring': palette.focusRing,
68
+ };
69
+
70
+ const cell: WebCssStyle = {
71
+ width: box, height: box, minWidth: box, minHeight: box, flexShrink: 0, padding: 0, borderRadius: 9999,
72
+ };
73
+
74
+ return (
75
+ <Container
76
+ accessibilityLabel={accessibilityLabel}
77
+ style={[bar, style]}
78
+ testID={testID}>
79
+ {emojis.map((emoji) => {
80
+ const active = selected === emoji;
81
+ return (
82
+ <Button
83
+ key={emoji}
84
+ appearance="plain"
85
+ tone={active ? 'accent' : 'neutral'}
86
+ accessibilityLabel={emojiLabel ? emojiLabel(emoji) : emoji}
87
+ pressed={active}
88
+ onPress={() => onSelectEmoji?.(emoji)}
89
+ style={cell}
90
+ testID={testID ? `${testID}-${emoji}` : undefined}>
91
+ <Text variant={GLYPH[size]}>{emoji}</Text>
92
+ </Button>
93
+ );
94
+ })}
95
+ {onMorePress ? (
96
+ <Button
97
+ appearance="subtle"
98
+ tone="neutral"
99
+ accessibilityLabel={moreLabel}
100
+ onPress={onMorePress}
101
+ iconOnly
102
+ icon={RiAddLine}
103
+ iconSize={18}
104
+ style={cell}
105
+ testID={testID ? `${testID}-more` : undefined} />
106
+ ) : null}
107
+ </Container>
108
+ );
109
+ }
110
+
111
+ return ReactionPicker;
112
+ }