@unif/react-native-chat 3.2.4 → 3.3.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 (124) hide show
  1. package/lib/module/components/Attachments/AttachmentItem.js +8 -4
  2. package/lib/module/components/Attachments/AttachmentItem.js.map +1 -1
  3. package/lib/module/components/Attachments/Attachments.js +1 -0
  4. package/lib/module/components/Attachments/Attachments.js.map +1 -1
  5. package/lib/module/components/Attachments/constants.js +1 -0
  6. package/lib/module/components/Attachments/constants.js.map +1 -1
  7. package/lib/module/components/Attachments/styles.js +10 -5
  8. package/lib/module/components/Attachments/styles.js.map +1 -1
  9. package/lib/module/components/Composer/Composer.js +13 -9
  10. package/lib/module/components/Composer/Composer.js.map +1 -1
  11. package/lib/module/components/Composer/styles.js +1 -0
  12. package/lib/module/components/Composer/styles.js.map +1 -1
  13. package/lib/module/components/Confirmation/Confirmation.js +29 -13
  14. package/lib/module/components/Confirmation/Confirmation.js.map +1 -1
  15. package/lib/module/components/Confirmation/styles.js +17 -6
  16. package/lib/module/components/Confirmation/styles.js.map +1 -1
  17. package/lib/module/components/Message/MarkdownContent/styles.js +29 -33
  18. package/lib/module/components/Message/MarkdownContent/styles.js.map +1 -1
  19. package/lib/module/components/Message/Message.js +37 -24
  20. package/lib/module/components/Message/Message.js.map +1 -1
  21. package/lib/module/components/Message/MessageWaiting.js +53 -0
  22. package/lib/module/components/Message/MessageWaiting.js.map +1 -0
  23. package/lib/module/components/Message/constants.js +3 -0
  24. package/lib/module/components/Message/constants.js.map +1 -1
  25. package/lib/module/components/Message/styles.js +41 -3
  26. package/lib/module/components/Message/styles.js.map +1 -1
  27. package/lib/module/components/MessageList/MessageList.js +60 -31
  28. package/lib/module/components/MessageList/MessageList.js.map +1 -1
  29. package/lib/module/components/MessageList/MessageListEndButton.js +60 -0
  30. package/lib/module/components/MessageList/MessageListEndButton.js.map +1 -0
  31. package/lib/module/components/MessageList/MessageListRow.js +9 -2
  32. package/lib/module/components/MessageList/MessageListRow.js.map +1 -1
  33. package/lib/module/components/MessageList/styles.js +6 -0
  34. package/lib/module/components/MessageList/styles.js.map +1 -1
  35. package/lib/module/components/MessageList/useMessageListScroll.js +218 -13
  36. package/lib/module/components/MessageList/useMessageListScroll.js.map +1 -1
  37. package/lib/module/components/Process/Process.js +15 -5
  38. package/lib/module/components/Process/Process.js.map +1 -1
  39. package/lib/module/components/Process/ProcessCompactStep.js +21 -12
  40. package/lib/module/components/Process/ProcessCompactStep.js.map +1 -1
  41. package/lib/module/components/Process/ProcessTimelineStep.js +79 -0
  42. package/lib/module/components/Process/ProcessTimelineStep.js.map +1 -0
  43. package/lib/module/components/Process/styles.js +63 -3
  44. package/lib/module/components/Process/styles.js.map +1 -1
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/typescript/src/components/Attachments/AttachmentItem.d.ts +1 -1
  47. package/lib/typescript/src/components/Attachments/AttachmentItem.d.ts.map +1 -1
  48. package/lib/typescript/src/components/Attachments/Attachments.d.ts.map +1 -1
  49. package/lib/typescript/src/components/Attachments/constants.d.ts +1 -0
  50. package/lib/typescript/src/components/Attachments/constants.d.ts.map +1 -1
  51. package/lib/typescript/src/components/Attachments/styles.d.ts +5 -0
  52. package/lib/typescript/src/components/Attachments/styles.d.ts.map +1 -1
  53. package/lib/typescript/src/components/Attachments/types.d.ts +2 -1
  54. package/lib/typescript/src/components/Attachments/types.d.ts.map +1 -1
  55. package/lib/typescript/src/components/Composer/Composer.d.ts.map +1 -1
  56. package/lib/typescript/src/components/Composer/styles.d.ts +1 -0
  57. package/lib/typescript/src/components/Composer/styles.d.ts.map +1 -1
  58. package/lib/typescript/src/components/Confirmation/Confirmation.d.ts.map +1 -1
  59. package/lib/typescript/src/components/Confirmation/styles.d.ts +13 -2
  60. package/lib/typescript/src/components/Confirmation/styles.d.ts.map +1 -1
  61. package/lib/typescript/src/components/Message/MarkdownContent/styles.d.ts +32 -66
  62. package/lib/typescript/src/components/Message/MarkdownContent/styles.d.ts.map +1 -1
  63. package/lib/typescript/src/components/Message/Message.d.ts.map +1 -1
  64. package/lib/typescript/src/components/Message/MessageWaiting.d.ts +3 -0
  65. package/lib/typescript/src/components/Message/MessageWaiting.d.ts.map +1 -0
  66. package/lib/typescript/src/components/Message/constants.d.ts +3 -0
  67. package/lib/typescript/src/components/Message/constants.d.ts.map +1 -1
  68. package/lib/typescript/src/components/Message/styles.d.ts +40 -2
  69. package/lib/typescript/src/components/Message/styles.d.ts.map +1 -1
  70. package/lib/typescript/src/components/Message/types.d.ts +5 -0
  71. package/lib/typescript/src/components/Message/types.d.ts.map +1 -1
  72. package/lib/typescript/src/components/MessageList/MessageList.d.ts.map +1 -1
  73. package/lib/typescript/src/components/MessageList/MessageListEndButton.d.ts +3 -0
  74. package/lib/typescript/src/components/MessageList/MessageListEndButton.d.ts.map +1 -0
  75. package/lib/typescript/src/components/MessageList/MessageListRow.d.ts +2 -8
  76. package/lib/typescript/src/components/MessageList/MessageListRow.d.ts.map +1 -1
  77. package/lib/typescript/src/components/MessageList/index.d.ts +1 -1
  78. package/lib/typescript/src/components/MessageList/index.d.ts.map +1 -1
  79. package/lib/typescript/src/components/MessageList/styles.d.ts +6 -0
  80. package/lib/typescript/src/components/MessageList/styles.d.ts.map +1 -1
  81. package/lib/typescript/src/components/MessageList/types.d.ts +41 -2
  82. package/lib/typescript/src/components/MessageList/types.d.ts.map +1 -1
  83. package/lib/typescript/src/components/MessageList/useMessageListScroll.d.ts +14 -3
  84. package/lib/typescript/src/components/MessageList/useMessageListScroll.d.ts.map +1 -1
  85. package/lib/typescript/src/components/Process/Process.d.ts.map +1 -1
  86. package/lib/typescript/src/components/Process/ProcessCompactStep.d.ts +1 -1
  87. package/lib/typescript/src/components/Process/ProcessCompactStep.d.ts.map +1 -1
  88. package/lib/typescript/src/components/Process/ProcessTimelineStep.d.ts +5 -0
  89. package/lib/typescript/src/components/Process/ProcessTimelineStep.d.ts.map +1 -0
  90. package/lib/typescript/src/components/Process/styles.d.ts +62 -2
  91. package/lib/typescript/src/components/Process/styles.d.ts.map +1 -1
  92. package/lib/typescript/src/components/Process/types.d.ts +7 -2
  93. package/lib/typescript/src/components/Process/types.d.ts.map +1 -1
  94. package/lib/typescript/src/index.d.ts +1 -1
  95. package/lib/typescript/src/index.d.ts.map +1 -1
  96. package/package.json +1 -1
  97. package/src/components/Attachments/AttachmentItem.tsx +16 -5
  98. package/src/components/Attachments/Attachments.tsx +1 -0
  99. package/src/components/Attachments/constants.ts +1 -0
  100. package/src/components/Attachments/styles.ts +7 -4
  101. package/src/components/Attachments/types.ts +2 -1
  102. package/src/components/Composer/Composer.tsx +34 -8
  103. package/src/components/Composer/styles.ts +1 -0
  104. package/src/components/Confirmation/Confirmation.tsx +50 -14
  105. package/src/components/Confirmation/styles.ts +13 -6
  106. package/src/components/Message/MarkdownContent/styles.ts +18 -44
  107. package/src/components/Message/Message.tsx +53 -33
  108. package/src/components/Message/MessageWaiting.tsx +68 -0
  109. package/src/components/Message/constants.ts +4 -0
  110. package/src/components/Message/styles.ts +25 -2
  111. package/src/components/Message/types.ts +6 -0
  112. package/src/components/MessageList/MessageList.tsx +107 -35
  113. package/src/components/MessageList/MessageListEndButton.tsx +61 -0
  114. package/src/components/MessageList/MessageListRow.tsx +12 -12
  115. package/src/components/MessageList/index.ts +1 -0
  116. package/src/components/MessageList/styles.ts +6 -0
  117. package/src/components/MessageList/types.ts +52 -2
  118. package/src/components/MessageList/useMessageListScroll.ts +296 -21
  119. package/src/components/Process/Process.tsx +38 -5
  120. package/src/components/Process/ProcessCompactStep.tsx +32 -16
  121. package/src/components/Process/ProcessTimelineStep.tsx +109 -0
  122. package/src/components/Process/styles.ts +48 -3
  123. package/src/components/Process/types.ts +7 -2
  124. package/src/index.tsx +1 -0
@@ -6,21 +6,26 @@ export interface ProcessStep {
6
6
  id: string;
7
7
  title: string;
8
8
  status: ProcessStepStatus;
9
+ /** 调用者提供的状态显示文案;不改变 status 的语义。 */
10
+ statusText?: string;
9
11
  description?: string;
10
12
  elapsedMs?: number;
11
13
  details?: ReactNode;
12
14
  actions?: readonly ChatAction[];
13
15
  }
14
16
  export interface ProcessBaseProps {
15
- /** card 为完整步骤面板;compact 为可整行展开、有界详情的轻量过程展示。 */
16
- variant?: 'card' | 'compact';
17
+ /** card 为状态面板;compact 为单行过程;timeline 为带状态节点的连续步骤。 */
18
+ variant?: 'card' | 'compact' | 'timeline';
17
19
  steps: readonly ProcessStep[];
18
20
  title?: string;
19
21
  identity?: ReactNode;
22
+ /** inline 仅用于 compact 单项,让身份与状态处于同一行。 */
23
+ identityPlacement?: 'heading' | 'inline';
20
24
  style?: StyleProp<ViewStyle>;
21
25
  testID?: string;
22
26
  }
23
27
  export interface ProcessCompactStepProps {
28
+ identity?: ReactNode;
24
29
  step: ProcessStep;
25
30
  expanded: boolean;
26
31
  elapsed?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/Process/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAe,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAC3B,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,KAAK,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,KAAK,CAAC;IACpB,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,gBAAgB,CAAC,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GACzC,CAAC,0BAA0B,GAAG,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/Process/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAe,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAC3B,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;IAC1B,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAC1C,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACzC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,KAAK,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,KAAK,CAAC;IACpB,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,gBAAgB,CAAC,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GACzC,CAAC,0BAA0B,GAAG,qBAAqB,CAAC,CAAC"}
@@ -6,7 +6,7 @@ export type { AttachmentsProps, ChatAttachmentItem, ChatAttachmentStatus, } from
6
6
  export { Message } from './components/Message/index.js';
7
7
  export type { MessageBaseProps, MessageCustomContent, MessageMarkdownContent, MessagePlainContent, MessagePlacement, MessageProps, MessageStatus, } from './components/Message/index.js';
8
8
  export { MessageList } from './components/MessageList/index.js';
9
- export type { MessageListHandle, MessageListProps, MessageListScrollOptions, } from './components/MessageList/index.js';
9
+ export type { MessageListAnchorOptions, MessageListHandle, MessageListProps, MessageListScrollOptions, } from './components/MessageList/index.js';
10
10
  export { Chat } from './components/Chat/index.js';
11
11
  export type { ChatProps } from './components/Chat/index.js';
12
12
  export { Suggestions } from './components/Suggestions/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,gCAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,+BAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,4BAAmB,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,4BAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,cAAc,EACd,gBAAgB,GACjB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAA2B,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,oCAA2B,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,+BAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAAiC,CAAC;AACrE,YAAY,EAAE,uBAAuB,EAAE,MAAM,0CAAiC,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gCAAuB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,+BAAsB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,gCAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,+BAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,4BAAmB,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,4BAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mCAA0B,CAAC;AACvD,YAAY,EACV,cAAc,EACd,gBAAgB,GACjB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAA2B,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,oCAA2B,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,+BAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAAiC,CAAC;AACrE,YAAY,EAAE,uBAAuB,EAAE,MAAM,0CAAiC,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gCAAuB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,+BAAsB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAuB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unif/react-native-chat",
3
- "version": "3.2.4",
3
+ "version": "3.3.1",
4
4
  "description": "Unif React Native 聊天组件:消息、输入、附件和交互展示",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -13,6 +13,7 @@ import {
13
13
  import {
14
14
  ATTACHMENT_ICONS,
15
15
  ATTACHMENT_STATUS_OWNER_SIZE,
16
+ ATTACHMENT_REMOVE_OWNER_SIZE,
16
17
  ROW_IMAGE_SIZE,
17
18
  STATUS_LABELS,
18
19
  } from './constants';
@@ -25,6 +26,7 @@ export function AttachmentItem({
25
26
  imageSize,
26
27
  row,
27
28
  mixed = false,
29
+ compact = false,
28
30
  showProgressLabel = false,
29
31
  onPreview,
30
32
  onRemove,
@@ -225,15 +227,18 @@ export function AttachmentItem({
225
227
  );
226
228
  }
227
229
 
228
- const removeLeft =
229
- previewable && !separatePreview
230
+ // 预览和重试都须保留独立命中区域,不复制参考紧凑格的中心误删问题。
231
+ const removeInCell = compact && !(previewable && !separatePreview) && !retry;
232
+ const removeLeft = removeInCell
233
+ ? Math.max(0, imageSize - ATTACHMENT_REMOVE_OWNER_SIZE)
234
+ : previewable && !separatePreview
230
235
  ? width!
231
236
  : (busy && !caption) || failed
232
237
  ? (imageSize - ATTACHMENT_STATUS_OWNER_SIZE) / 2 +
233
238
  ATTACHMENT_STATUS_OWNER_SIZE
234
- : imageSize - ATTACHMENT_STATUS_OWNER_SIZE;
239
+ : imageSize - ATTACHMENT_REMOVE_OWNER_SIZE;
235
240
  const ownerWidth = removable
236
- ? Math.max(width!, removeLeft + ATTACHMENT_STATUS_OWNER_SIZE)
241
+ ? Math.max(width!, removeLeft + ATTACHMENT_REMOVE_OWNER_SIZE)
237
242
  : width;
238
243
  const picture = (
239
244
  <>
@@ -276,7 +281,13 @@ export function AttachmentItem({
276
281
  {statusOwner}
277
282
  {removable ? (
278
283
  <Pressable
279
- style={[styles.removeOwner, { left: removeLeft }]}
284
+ style={[
285
+ styles.removeOwner,
286
+ { left: removeLeft },
287
+ (removeInCell ||
288
+ removeLeft === imageSize - ATTACHMENT_REMOVE_OWNER_SIZE) &&
289
+ styles.removeInCell,
290
+ ]}
280
291
  accessibilityRole="button"
281
292
  accessibilityLabel={`移除${name}`}
282
293
  disabled={item.removeDisabled}
@@ -24,6 +24,7 @@ export function Attachments({
24
24
  item={item}
25
25
  row={row}
26
26
  mixed={layout === 'mixed'}
27
+ compact={layout === 'compact'}
27
28
  width={CARD_WIDTH}
28
29
  imageSize={
29
30
  row
@@ -10,6 +10,7 @@ export const ATTACHMENT_STATUS_OWNER_SIZE = Math.max(
10
10
  44,
11
11
  ATTACHMENT_STATUS_SIZE
12
12
  );
13
+ export const ATTACHMENT_REMOVE_OWNER_SIZE = 44;
13
14
  export const ATTACHMENT_ICONS: Record<
14
15
  NonNullable<ChatAttachmentItem['kind']>,
15
16
  IconName
@@ -12,6 +12,7 @@ import type { ColorTokens } from '@unif/react-native-design';
12
12
  import {
13
13
  ATTACHMENT_STATUS_OWNER_SIZE,
14
14
  ATTACHMENT_STATUS_SIZE,
15
+ ATTACHMENT_REMOVE_OWNER_SIZE,
15
16
  CARD_WIDTH,
16
17
  } from './constants';
17
18
 
@@ -65,8 +66,9 @@ export const createStyles = (colors: ColorTokens) =>
65
66
  height: r(64),
66
67
  paddingVertical: 0,
67
68
  paddingHorizontal: space[3],
68
- borderWidth: 0,
69
- borderRadius: 0,
69
+ borderWidth: StyleSheet.hairlineWidth,
70
+ borderRadius: radius.md,
71
+ backgroundColor: colors.surfaceContainerHigh,
70
72
  },
71
73
  content: { minWidth: 0, flexShrink: 1 },
72
74
  rowContent: { flex: 1 },
@@ -102,8 +104,8 @@ export const createStyles = (colors: ColorTokens) =>
102
104
  removeOwner: {
103
105
  position: 'absolute',
104
106
  top: 0,
105
- width: 44,
106
- height: 44,
107
+ width: ATTACHMENT_REMOVE_OWNER_SIZE,
108
+ height: ATTACHMENT_REMOVE_OWNER_SIZE,
107
109
  paddingTop: space[1],
108
110
  zIndex: 2,
109
111
  elevation: 2,
@@ -116,6 +118,7 @@ export const createStyles = (colors: ColorTokens) =>
116
118
  alignItems: 'center',
117
119
  justifyContent: 'center',
118
120
  },
121
+ removeInCell: { alignItems: 'flex-end', paddingRight: space[1] },
119
122
  removeFailed: { backgroundColor: colors.error },
120
123
  caption: {
121
124
  flexDirection: 'row',
@@ -20,7 +20,7 @@ export interface ChatAttachmentItem {
20
20
  }
21
21
  export interface AttachmentsProps {
22
22
  items: readonly ChatAttachmentItem[];
23
- layout?: 'grid' | 'mixed' | 'carousel' | 'list';
23
+ layout?: 'grid' | 'compact' | 'mixed' | 'carousel' | 'list';
24
24
  showProgressLabel?: boolean;
25
25
  onPreview?(item: ChatAttachmentItem): void;
26
26
  onRemove?(item: ChatAttachmentItem): void;
@@ -36,4 +36,5 @@ export interface AttachmentItemProps extends Pick<
36
36
  imageSize: number;
37
37
  row: boolean;
38
38
  mixed?: boolean;
39
+ compact?: boolean;
39
40
  }
@@ -5,12 +5,19 @@ import {
5
5
  useRef,
6
6
  useState,
7
7
  } from 'react';
8
- import { Pressable, Text, View, useWindowDimensions } from 'react-native';
8
+ import {
9
+ LayoutAnimation,
10
+ Pressable,
11
+ Text,
12
+ View,
13
+ useWindowDimensions,
14
+ } from 'react-native';
9
15
  import {
10
16
  fixed,
11
17
  Textarea,
12
18
  useTheme,
13
19
  useThemedStyles,
20
+ usePrefersReducedMotion,
14
21
  } from '@unif/react-native-design';
15
22
  import type { TextFieldHandle } from '@unif/react-native-design';
16
23
  import {
@@ -52,6 +59,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
52
59
  ) {
53
60
  const styles = useThemedStyles(createStyles);
54
61
  const { fontScale } = useTheme();
62
+ const reducedMotion = usePrefersReducedMotion();
55
63
  const { height: windowHeight } = useWindowDimensions();
56
64
  const inputRef = useRef<TextFieldHandle>(null);
57
65
  const lastHeight = useRef<number | undefined>(undefined);
@@ -59,6 +67,12 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
59
67
  const [focused, setFocused] = useState(false);
60
68
  const voiceActive = voice !== undefined && voice.status !== 'idle';
61
69
  const expanded = focused || value.length > 0;
70
+ const moreDisabled =
71
+ disabled ||
72
+ voiceActive ||
73
+ actions.every(
74
+ (action) => !action.label.trim() || action.disabled || action.loading
75
+ );
62
76
  const minHeight = Number.isFinite(minInputHeight)
63
77
  ? Math.max(fixed.hitTarget, minInputHeight!)
64
78
  : fixed.hitTarget;
@@ -98,8 +112,8 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
98
112
  inputRef.current?.blur();
99
113
  setFocused(false);
100
114
  }
101
- if (voiceActive || disabled) setMenuOpen(false);
102
- }, [voiceActive, disabled]);
115
+ if (moreDisabled) setMenuOpen(false);
116
+ }, [voiceActive, moreDisabled]);
103
117
 
104
118
  const moreAction =
105
119
  actions.length > 0 ? (
@@ -107,7 +121,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
107
121
  icon="plus"
108
122
  label="更多操作"
109
123
  expanded={menuOpen}
110
- disabled={disabled}
124
+ disabled={moreDisabled}
111
125
  onPress={() => setMenuOpen((open) => !open)}
112
126
  />
113
127
  ) : null;
@@ -126,7 +140,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
126
140
  {header != null ? (
127
141
  <View style={[styles.accessory, styles.header]}>{header}</View>
128
142
  ) : null}
129
- {menuOpen && !disabled && !voiceActive && actions.length > 0 ? (
143
+ {menuOpen && !moreDisabled && actions.length > 0 ? (
130
144
  <>
131
145
  <Pressable
132
146
  style={[styles.backdrop, { height: windowHeight }]}
@@ -191,10 +205,18 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
191
205
  onPressIn={() => setMenuOpen(false)}
192
206
  onFocus={() => {
193
207
  setMenuOpen(false);
208
+ if (!focused && !value.length && !reducedMotion)
209
+ LayoutAnimation.configureNext(
210
+ LayoutAnimation.Presets.easeInEaseOut
211
+ );
194
212
  setFocused(true);
195
213
  onFocusChange?.(true);
196
214
  }}
197
215
  onBlur={() => {
216
+ if (focused && !value.length && !reducedMotion)
217
+ LayoutAnimation.configureNext(
218
+ LayoutAnimation.Presets.easeInEaseOut
219
+ );
198
220
  setFocused(false);
199
221
  onFocusChange?.(false);
200
222
  }}
@@ -267,13 +289,17 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
267
289
  : voice.transcript || VOICE_LABELS[voice.status]}
268
290
  </Text>
269
291
  </View>
270
- {voice.status === 'listening' ? (
292
+ {voice.status === 'listening' || voice.status === 'finishing' ? (
271
293
  <ComposerIconAction
272
294
  icon="stop"
273
295
  visual="primary"
274
296
  label="停止语音输入"
275
- disabled={disabled || voice.disabled}
276
- onPress={voice.onStop}
297
+ disabled={
298
+ disabled || voice.disabled || voice.status === 'finishing'
299
+ }
300
+ onPress={
301
+ voice.status === 'listening' ? voice.onStop : undefined
302
+ }
277
303
  />
278
304
  ) : null}
279
305
  </View>
@@ -18,6 +18,7 @@ export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
18
18
  },
19
19
  accessory: { padding: space[3] },
20
20
  header: {
21
+ padding: space[2],
21
22
  borderBottomWidth: 0.5,
22
23
  borderBottomColor: colors.outlineVariant,
23
24
  },
@@ -1,5 +1,11 @@
1
1
  import { Text, View } from 'react-native';
2
- import { Button, useThemedStyles } from '@unif/react-native-design';
2
+ import {
3
+ Button,
4
+ Icon,
5
+ Spinner,
6
+ useColors,
7
+ useThemedStyles,
8
+ } from '@unif/react-native-design';
3
9
  import {
4
10
  CONFIRMATION_STATUS_TEXT,
5
11
  DEFAULT_CANCEL_LABEL,
@@ -24,35 +30,65 @@ export function Confirmation({
24
30
  testID,
25
31
  }: ConfirmationProps): React.JSX.Element {
26
32
  const styles = useThemedStyles(createStyles);
33
+ const colors = useColors();
34
+ const tint =
35
+ status === 'confirmed'
36
+ ? colors.success
37
+ : status === 'cancelled'
38
+ ? colors.foregroundSubtle
39
+ : colors.primary;
40
+ const borderColor =
41
+ status === 'cancelled' ? colors.surfaceContainerHighest : tint;
27
42
  const resolvedStatusText =
28
43
  status === 'pending'
29
44
  ? statusText
30
45
  : (statusText ?? CONFIRMATION_STATUS_TEXT[status]);
31
46
 
32
47
  return (
33
- <View style={[styles.root, style]} testID={testID}>
34
- <Text style={styles.title}>{title}</Text>
35
- <View>{children}</View>
48
+ <View style={[styles.root, { borderColor }, style]} testID={testID}>
49
+ <View style={styles.heading}>
50
+ {status === 'processing' ? (
51
+ <Spinner size={14} color={tint} />
52
+ ) : (
53
+ <Icon
54
+ name={
55
+ status === 'confirmed'
56
+ ? 'check'
57
+ : status === 'cancelled'
58
+ ? 'close'
59
+ : 'warning'
60
+ }
61
+ size={14}
62
+ color={tint}
63
+ />
64
+ )}
65
+ <Text
66
+ style={[styles.title, status === 'cancelled' && styles.cancelled]}
67
+ >
68
+ {title}
69
+ </Text>
70
+ </View>
71
+ <View style={styles.body}>{children}</View>
36
72
  {resolvedStatusText ? (
37
73
  <Text style={styles.status}>{resolvedStatusText}</Text>
38
74
  ) : null}
39
75
  {status === 'pending' && (onConfirm || onCancel) ? (
40
76
  <View style={styles.actions}>
41
- {onConfirm ? (
42
- <Button
43
- label={confirmLabel}
44
- onPress={onConfirm}
45
- disabled={confirmDisabled}
46
- size="sm"
47
- />
48
- ) : null}
49
77
  {onCancel ? (
50
78
  <Button
51
79
  label={cancelLabel}
52
80
  onPress={onCancel}
53
81
  disabled={cancelDisabled}
54
- size="sm"
55
- variant="outline"
82
+ block
83
+ variant="secondary"
84
+ />
85
+ ) : null}
86
+ {onConfirm ? (
87
+ <Button
88
+ label={confirmLabel}
89
+ onPress={onConfirm}
90
+ disabled={confirmDisabled}
91
+ block
56
92
  />
57
93
  ) : null}
58
94
  </View>
@@ -10,25 +10,32 @@ import {
10
10
  export const createStyles = (colors: ColorTokens) =>
11
11
  StyleSheet.create({
12
12
  root: {
13
- gap: space[4],
14
13
  padding: space[5],
15
- borderWidth: 1,
14
+ borderWidth: 2,
16
15
  borderColor: colors.outline,
17
- borderRadius: radius.xl,
16
+ borderRadius: radius.lg,
18
17
  backgroundColor: colors.surface,
19
18
  },
19
+ heading: {
20
+ flexDirection: 'row',
21
+ alignItems: 'center',
22
+ gap: space[2],
23
+ marginBottom: space[3],
24
+ },
25
+ body: { marginBottom: space[4] },
26
+ cancelled: { color: colors.foregroundSubtle },
20
27
  title: {
28
+ flex: 1,
21
29
  color: colors.foreground,
22
- fontSize: type.h3,
30
+ fontSize: type.xs,
23
31
  fontWeight: fw.semi,
24
32
  },
25
33
  status: {
26
34
  color: colors.foregroundMuted,
27
- fontSize: type.sm,
35
+ fontSize: type.xxs,
28
36
  },
29
37
  actions: {
30
38
  flexDirection: 'row',
31
- flexWrap: 'wrap',
32
39
  gap: space[3],
33
40
  },
34
41
  footer: {
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native';
2
- import { type, space, fontMono } from '@unif/react-native-design';
2
+ import { type, fw } from '@unif/react-native-design';
3
3
  import type { ColorTokens } from '@unif/react-native-design';
4
4
 
5
5
  const makeMarkdownStyles = (colors: ColorTokens, outgoing: boolean) => {
@@ -11,58 +11,32 @@ const makeMarkdownStyles = (colors: ColorTokens, outgoing: boolean) => {
11
11
  };
12
12
  return StyleSheet.create({
13
13
  text: body,
14
- em: { ...body, fontStyle: 'italic' },
15
- strong: { ...body, fontWeight: 'bold' },
16
- strikethrough: { ...body, textDecorationLine: 'line-through' },
14
+ em: { color: textColor, fontStyle: 'italic' },
15
+ strong: { color: textColor, fontWeight: 'bold' },
16
+ strikethrough: { color: textColor, textDecorationLine: 'line-through' },
17
17
  link: {
18
- ...body,
19
18
  color: outgoing ? colors.onPrimary : colors.primary,
20
19
  textDecorationLine: 'underline',
21
20
  },
22
- li: body,
21
+ li: { color: textColor, fontSize: type.sm },
23
22
  codespan: {
24
- ...body,
25
- fontFamily: fontMono,
26
23
  color: colors.foreground,
27
24
  backgroundColor: colors.surfaceContainer,
28
25
  },
29
- h1: {
30
- fontSize: type.h1,
31
- lineHeight: type.h1 * 1.4,
32
- color: textColor,
33
- borderBottomColor: colors.outline,
34
- },
35
- h2: {
36
- fontSize: type.h2,
37
- lineHeight: type.h2 * 1.4,
38
- color: textColor,
39
- borderBottomColor: colors.outline,
40
- },
41
- h3: {
42
- fontSize: type.h3,
43
- lineHeight: type.h3 * 1.4,
44
- color: textColor,
45
- },
46
- h4: {
47
- fontSize: type.body,
48
- lineHeight: type.body * 1.4,
49
- color: textColor,
50
- },
51
- h5: {
52
- fontSize: type.sm,
53
- lineHeight: type.sm * 1.4,
54
- color: textColor,
55
- },
56
- h6: {
57
- fontSize: type.xs,
58
- lineHeight: type.xs * 1.4,
59
- color: textColor,
26
+ h1: { fontSize: type.h2, fontWeight: fw.bold, color: textColor },
27
+ h2: { fontSize: type.h3, fontWeight: fw.bold, color: textColor },
28
+ h3: { fontSize: type.body, fontWeight: fw.semi, color: textColor },
29
+ h4: { fontSize: type.sm, fontWeight: fw.semi, color: textColor },
30
+ h5: { fontSize: type.sm, fontWeight: fw.semi, color: textColor },
31
+ h6: { fontSize: type.sm, fontWeight: fw.semi, color: textColor },
32
+ code: {
33
+ backgroundColor: colors.surfaceContainer,
34
+ borderColor: colors.outline,
35
+ borderWidth: 1,
60
36
  },
61
- paragraph: { paddingVertical: space[1] },
62
- code: { padding: space[2], backgroundColor: colors.surfaceContainer },
63
- codeText: { ...body, color: colors.foreground, fontFamily: fontMono },
64
- blockquote: { borderLeftColor: colors.outline },
65
- hr: { borderBottomColor: colors.outline },
37
+ codeText: { color: colors.foreground },
38
+ blockquote: { borderColor: colors.outline, borderLeftWidth: 3 },
39
+ hr: { backgroundColor: colors.outline, height: 1 },
66
40
  table: { borderColor: colors.outline },
67
41
  });
68
42
  };
@@ -2,13 +2,13 @@ import { Pressable, Text, View } from 'react-native';
2
2
  import {
3
3
  Button,
4
4
  IconButton,
5
- Spinner,
6
5
  useThemedStyles,
7
6
  useColors,
8
7
  } from '@unif/react-native-design';
9
8
  import { MarkdownContent } from './MarkdownContent/MarkdownContent';
10
9
  import { createStyles } from './styles';
11
10
  import { isNestedAction } from './isNestedAction';
11
+ import { MessageWaiting } from './MessageWaiting';
12
12
  import type { MessageProps } from './types';
13
13
 
14
14
  export function Message(props: MessageProps) {
@@ -23,6 +23,7 @@ export function Message(props: MessageProps) {
23
23
  header,
24
24
  footer,
25
25
  actions = [],
26
+ failureAction,
26
27
  onPress,
27
28
  onLongPress,
28
29
  style,
@@ -39,6 +40,7 @@ export function Message(props: MessageProps) {
39
40
  (footer !== undefined && footer !== null && footer !== false);
40
41
  const waiting =
41
42
  (status === 'pending' || status === 'streaming') && !hasContent;
43
+ const failedAction = status === 'failed' ? failureAction : undefined;
42
44
  const contentStyle = [
43
45
  styles.content,
44
46
  fullWidth && styles.fullWidth,
@@ -48,6 +50,12 @@ export function Message(props: MessageProps) {
48
50
  ],
49
51
  surface === 'outlined' && styles.outlined,
50
52
  status === 'failed' && styles.failed,
53
+ waiting &&
54
+ surface === 'bubble' &&
55
+ placement === 'start' &&
56
+ styles.waitingBubble,
57
+ failedAction && styles.failureContent,
58
+ failedAction && fullWidth && styles.failureFullWidth,
51
59
  ];
52
60
  const content = (
53
61
  <>
@@ -76,16 +84,8 @@ export function Message(props: MessageProps) {
76
84
  ) : (
77
85
  props.children
78
86
  )}
79
- {waiting ? (
80
- <View
81
- accessible
82
- accessibilityLabel="正在等待回复"
83
- accessibilityState={{ busy: true }}
84
- >
85
- <Spinner />
86
- </View>
87
- ) : null}
88
- {statusText ? (
87
+ {waiting ? <MessageWaiting label={statusText} /> : null}
88
+ {statusText && !waiting ? (
89
89
  <Text style={[styles.status, status === 'failed' && styles.errorText]}>
90
90
  {statusText}
91
91
  </Text>
@@ -93,6 +93,31 @@ export function Message(props: MessageProps) {
93
93
  {footer}
94
94
  </>
95
95
  );
96
+ const bubble =
97
+ onPress || onLongPress ? (
98
+ <Pressable
99
+ style={contentStyle}
100
+ onPress={
101
+ onPress
102
+ ? (event) => {
103
+ if (!isNestedAction(event)) onPress();
104
+ }
105
+ : undefined
106
+ }
107
+ onLongPress={
108
+ onLongPress
109
+ ? (event) => {
110
+ if (!isNestedAction(event)) onLongPress();
111
+ }
112
+ : undefined
113
+ }
114
+ accessible={false}
115
+ >
116
+ {content}
117
+ </Pressable>
118
+ ) : (
119
+ <View style={contentStyle}>{content}</View>
120
+ );
96
121
  return (
97
122
  <View
98
123
  style={[styles.root, placement === 'end' && styles.end, style]}
@@ -107,29 +132,24 @@ export function Message(props: MessageProps) {
107
132
  ]}
108
133
  >
109
134
  {name ? <Text style={styles.name}>{name}</Text> : null}
110
- {onPress || onLongPress ? (
111
- <Pressable
112
- style={contentStyle}
113
- onPress={
114
- onPress
115
- ? (event) => {
116
- if (!isNestedAction(event)) onPress();
117
- }
118
- : undefined
119
- }
120
- onLongPress={
121
- onLongPress
122
- ? (event) => {
123
- if (!isNestedAction(event)) onLongPress();
124
- }
125
- : undefined
126
- }
127
- accessible={false}
128
- >
129
- {content}
130
- </Pressable>
135
+ {failedAction ? (
136
+ <View style={[styles.failureRow, placement === 'end' && styles.end]}>
137
+ {bubble}
138
+ <IconButton
139
+ icon="alert"
140
+ size="sm"
141
+ variant="ghost"
142
+ color={colors.error}
143
+ style={styles.failureAction}
144
+ accessibilityLabel={failedAction.label}
145
+ accessibilityHint={failedAction.accessibilityHint}
146
+ disabled={failedAction.disabled}
147
+ loading={failedAction.loading}
148
+ onPress={failedAction.onPress}
149
+ />
150
+ </View>
131
151
  ) : (
132
- <View style={contentStyle}>{content}</View>
152
+ bubble
133
153
  )}
134
154
  {actions.length ? (
135
155
  <View style={styles.actions}>