@vinaverse/react-native 0.1.0-alpha.2 → 0.1.0-alpha.3

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.
package/dist/index.d.cts CHANGED
@@ -107,6 +107,30 @@ interface ListProps {
107
107
  readonly keyboardShouldPersistTaps: 'handled';
108
108
  readonly contentContainerStyle: object;
109
109
  }
110
+ /** A failure the person needs a way out of: a turn that failed before any reply, or no session to talk to. */
111
+ interface FailureState {
112
+ /** `turn_failed`: a turn failed before any of its reply; `unavailable`: the backend gave no session, or none it could use. */
113
+ readonly kind: 'turn_failed' | 'unavailable';
114
+ /** Why: the turn's error `code` (`internal`, `timeout`, …), or the conversation's status (`unavailable`, `unauthorized`). */
115
+ readonly reason: string | null;
116
+ /** Try again, when it can be: the person's text again for a turn the server allows to retry, a new session otherwise. */
117
+ readonly retry: (() => void) | undefined;
118
+ /** The conversation, once a session named it: for your support records. */
119
+ readonly conversationId: string | null;
120
+ }
121
+ /** A slot for a failure (`components.Error`, `components.Unavailable`): the state, and the kit's own part to wrap. */
122
+ interface FailureProps {
123
+ readonly state: FailureState;
124
+ readonly Default: ComponentType<{
125
+ readonly state: FailureState;
126
+ }>;
127
+ }
128
+ /** One action on every failure, drawn as a button by the kit's own parts: a person is always the way out. */
129
+ interface FailureAction {
130
+ /** Default: the copy's `talkToPerson` ("Talk to a person"), in the person's language. */
131
+ readonly label?: string;
132
+ readonly onPress: (state: FailureState) => void;
133
+ }
110
134
 
111
135
  declare function DefaultHeader(props: Omit<HeaderProps, 'Default'>): react.JSX.Element;
112
136
  declare const ChatHeader: react.NamedExoticComponent<object>;
@@ -120,6 +144,11 @@ declare const Composer: react.NamedExoticComponent<{
120
144
 
121
145
  declare const DisclosureBar: react.NamedExoticComponent<object>;
122
146
 
147
+ /** The tenant's failure action as a button, or nothing when there is none. */
148
+ declare function FailureActionButton(props: {
149
+ readonly state: FailureState;
150
+ }): ReactNode;
151
+
123
152
  declare function DefaultBubble(props: Omit<MessageBubbleProps, 'Default'>): react.JSX.Element;
124
153
  declare const MessageBubble: react.NamedExoticComponent<{
125
154
  readonly item: MessageItem;
@@ -141,10 +170,18 @@ declare const Row: react.NamedExoticComponent<{
141
170
  declare const MessageList: react.NamedExoticComponent<object>;
142
171
 
143
172
  declare const StatusBanner: react.NamedExoticComponent<object>;
173
+ /** The kit's own "Couldn't connect." banner: try again, and the tenant's failure action when there is one. */
174
+ declare function DefaultUnavailable(props: {
175
+ readonly state: FailureState;
176
+ }): ReactNode;
144
177
 
145
178
  declare const SystemRow: react.NamedExoticComponent<{
146
179
  readonly item: SystemItem;
147
180
  }>;
181
+ /** The kit's own failed-turn row: "Something went wrong.", and the tenant's failure action when there is one. */
182
+ declare function DefaultTurnFailed(props: {
183
+ readonly state: FailureState;
184
+ }): ReactNode;
148
185
 
149
186
  type ProposalDecision = 'confirm' | 'decline';
150
187
  /** What the kit asks of the tenant's app. Only `onProposal` and `onOpenLink` are needed for the cards that use them. */
@@ -162,6 +199,11 @@ interface ChatHandlers {
162
199
  readonly onPickPhoto?: (question: Question, card: HeldCard) => Promise<{
163
200
  readonly upload_ref: string;
164
201
  } | null>;
202
+ /**
203
+ * A way out on a failed turn and on "couldn't connect": a button with your label (default "Talk to a person"),
204
+ * drawn by the kit's own parts when no `components.Error` or `components.Unavailable` replaces them.
205
+ */
206
+ readonly failureAction?: FailureAction;
165
207
  /** Development warnings: a theme that is hard to read, copy that says "assistant". */
166
208
  readonly onWarning?: (message: string) => void;
167
209
  }
@@ -174,6 +216,10 @@ interface ChatSlots {
174
216
  readonly Image?: ComponentType<ImageProps>;
175
217
  /** A list with FlashList's props (LegendList works). Default: FlashList. */
176
218
  readonly ListComponent?: ComponentType<ListProps>;
219
+ /** A turn that failed before any reply: replaces the "Something went wrong." row. */
220
+ readonly Error?: ComponentType<FailureProps>;
221
+ /** No session to talk to: replaces the "Couldn't connect." banner. */
222
+ readonly Unavailable?: ComponentType<FailureProps>;
177
223
  /** Card renderers by kind (`professional`, `proposal`, …). */
178
224
  readonly cards?: Readonly<Partial<Record<string, ComponentType<CardProps>>>>;
179
225
  }
@@ -183,6 +229,10 @@ interface ChatContextValue {
183
229
  readonly slots: ChatSlots;
184
230
  readonly agentAvatar: string | undefined;
185
231
  readonly timeZone: string | undefined;
232
+ /** The failure action's label when there is one (`label` undefined: the copy's); `onPress` is read from `handlers`. */
233
+ readonly failureAction: {
234
+ readonly label: string | undefined;
235
+ } | null;
186
236
  }
187
237
  /** The conversation, handlers and slots; only inside `VinaverseChat` (or `VinaverseChatProvider`). */
188
238
  declare function useChat(): ChatContextValue;
@@ -261,4 +311,4 @@ declare function useReducedMotion(): boolean;
261
311
  /** Reads a line to a screen reader, without moving focus. */
262
312
  declare function announce(text: string): void;
263
313
 
264
- export { ActivityLine, Avatar, Button, type ButtonProps, CardFrame, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultHeader, DisclosureBar, type EmptyStateProps, type HeaderProps, InfoCard, type LifecycleTarget, type ListProps, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, type Theme, type ThemeOverrides, ThemeProvider, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
314
+ export { ActivityLine, Avatar, Button, type ButtonProps, CardFrame, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, InfoCard, type LifecycleTarget, type ListProps, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, type Theme, type ThemeOverrides, ThemeProvider, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
package/dist/index.d.ts CHANGED
@@ -107,6 +107,30 @@ interface ListProps {
107
107
  readonly keyboardShouldPersistTaps: 'handled';
108
108
  readonly contentContainerStyle: object;
109
109
  }
110
+ /** A failure the person needs a way out of: a turn that failed before any reply, or no session to talk to. */
111
+ interface FailureState {
112
+ /** `turn_failed`: a turn failed before any of its reply; `unavailable`: the backend gave no session, or none it could use. */
113
+ readonly kind: 'turn_failed' | 'unavailable';
114
+ /** Why: the turn's error `code` (`internal`, `timeout`, …), or the conversation's status (`unavailable`, `unauthorized`). */
115
+ readonly reason: string | null;
116
+ /** Try again, when it can be: the person's text again for a turn the server allows to retry, a new session otherwise. */
117
+ readonly retry: (() => void) | undefined;
118
+ /** The conversation, once a session named it: for your support records. */
119
+ readonly conversationId: string | null;
120
+ }
121
+ /** A slot for a failure (`components.Error`, `components.Unavailable`): the state, and the kit's own part to wrap. */
122
+ interface FailureProps {
123
+ readonly state: FailureState;
124
+ readonly Default: ComponentType<{
125
+ readonly state: FailureState;
126
+ }>;
127
+ }
128
+ /** One action on every failure, drawn as a button by the kit's own parts: a person is always the way out. */
129
+ interface FailureAction {
130
+ /** Default: the copy's `talkToPerson` ("Talk to a person"), in the person's language. */
131
+ readonly label?: string;
132
+ readonly onPress: (state: FailureState) => void;
133
+ }
110
134
 
111
135
  declare function DefaultHeader(props: Omit<HeaderProps, 'Default'>): react.JSX.Element;
112
136
  declare const ChatHeader: react.NamedExoticComponent<object>;
@@ -120,6 +144,11 @@ declare const Composer: react.NamedExoticComponent<{
120
144
 
121
145
  declare const DisclosureBar: react.NamedExoticComponent<object>;
122
146
 
147
+ /** The tenant's failure action as a button, or nothing when there is none. */
148
+ declare function FailureActionButton(props: {
149
+ readonly state: FailureState;
150
+ }): ReactNode;
151
+
123
152
  declare function DefaultBubble(props: Omit<MessageBubbleProps, 'Default'>): react.JSX.Element;
124
153
  declare const MessageBubble: react.NamedExoticComponent<{
125
154
  readonly item: MessageItem;
@@ -141,10 +170,18 @@ declare const Row: react.NamedExoticComponent<{
141
170
  declare const MessageList: react.NamedExoticComponent<object>;
142
171
 
143
172
  declare const StatusBanner: react.NamedExoticComponent<object>;
173
+ /** The kit's own "Couldn't connect." banner: try again, and the tenant's failure action when there is one. */
174
+ declare function DefaultUnavailable(props: {
175
+ readonly state: FailureState;
176
+ }): ReactNode;
144
177
 
145
178
  declare const SystemRow: react.NamedExoticComponent<{
146
179
  readonly item: SystemItem;
147
180
  }>;
181
+ /** The kit's own failed-turn row: "Something went wrong.", and the tenant's failure action when there is one. */
182
+ declare function DefaultTurnFailed(props: {
183
+ readonly state: FailureState;
184
+ }): ReactNode;
148
185
 
149
186
  type ProposalDecision = 'confirm' | 'decline';
150
187
  /** What the kit asks of the tenant's app. Only `onProposal` and `onOpenLink` are needed for the cards that use them. */
@@ -162,6 +199,11 @@ interface ChatHandlers {
162
199
  readonly onPickPhoto?: (question: Question, card: HeldCard) => Promise<{
163
200
  readonly upload_ref: string;
164
201
  } | null>;
202
+ /**
203
+ * A way out on a failed turn and on "couldn't connect": a button with your label (default "Talk to a person"),
204
+ * drawn by the kit's own parts when no `components.Error` or `components.Unavailable` replaces them.
205
+ */
206
+ readonly failureAction?: FailureAction;
165
207
  /** Development warnings: a theme that is hard to read, copy that says "assistant". */
166
208
  readonly onWarning?: (message: string) => void;
167
209
  }
@@ -174,6 +216,10 @@ interface ChatSlots {
174
216
  readonly Image?: ComponentType<ImageProps>;
175
217
  /** A list with FlashList's props (LegendList works). Default: FlashList. */
176
218
  readonly ListComponent?: ComponentType<ListProps>;
219
+ /** A turn that failed before any reply: replaces the "Something went wrong." row. */
220
+ readonly Error?: ComponentType<FailureProps>;
221
+ /** No session to talk to: replaces the "Couldn't connect." banner. */
222
+ readonly Unavailable?: ComponentType<FailureProps>;
177
223
  /** Card renderers by kind (`professional`, `proposal`, …). */
178
224
  readonly cards?: Readonly<Partial<Record<string, ComponentType<CardProps>>>>;
179
225
  }
@@ -183,6 +229,10 @@ interface ChatContextValue {
183
229
  readonly slots: ChatSlots;
184
230
  readonly agentAvatar: string | undefined;
185
231
  readonly timeZone: string | undefined;
232
+ /** The failure action's label when there is one (`label` undefined: the copy's); `onPress` is read from `handlers`. */
233
+ readonly failureAction: {
234
+ readonly label: string | undefined;
235
+ } | null;
186
236
  }
187
237
  /** The conversation, handlers and slots; only inside `VinaverseChat` (or `VinaverseChatProvider`). */
188
238
  declare function useChat(): ChatContextValue;
@@ -261,4 +311,4 @@ declare function useReducedMotion(): boolean;
261
311
  /** Reads a line to a screen reader, without moving focus. */
262
312
  declare function announce(text: string): void;
263
313
 
264
- export { ActivityLine, Avatar, Button, type ButtonProps, CardFrame, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultHeader, DisclosureBar, type EmptyStateProps, type HeaderProps, InfoCard, type LifecycleTarget, type ListProps, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, type Theme, type ThemeOverrides, ThemeProvider, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
314
+ export { ActivityLine, Avatar, Button, type ButtonProps, CardFrame, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, InfoCard, type LifecycleTarget, type ListProps, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, type Theme, type ThemeOverrides, ThemeProvider, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
package/dist/index.js CHANGED
@@ -1471,6 +1471,23 @@ var DisclosureBar = memo(function DisclosureBar2() {
1471
1471
  }
1472
1472
  );
1473
1473
  });
1474
+ function FailureActionButton(props) {
1475
+ const { handlers, failureAction } = useChat();
1476
+ const { t } = useCopy();
1477
+ if (!failureAction) return null;
1478
+ return /* @__PURE__ */ jsx(
1479
+ Button,
1480
+ {
1481
+ label: failureAction.label ?? t("talkToPerson"),
1482
+ variant: "text",
1483
+ onPress: () => handlers.current.failureAction?.onPress(props.state)
1484
+ }
1485
+ );
1486
+ }
1487
+ function FailureSlot(props) {
1488
+ const { slot: Slot, state, Default } = props;
1489
+ return Slot ? /* @__PURE__ */ jsx(Slot, { state, Default }) : /* @__PURE__ */ jsx(Default, { state });
1490
+ }
1474
1491
  function DefaultBubble(props) {
1475
1492
  const { colors: colors2, radius: radius2, space: space2, font: font2 } = useTheme();
1476
1493
  const role = props.item.role;
@@ -1626,9 +1643,29 @@ function announce(text) {
1626
1643
  }
1627
1644
  var SystemRow = memo(function SystemRow2(props) {
1628
1645
  const { t } = useCopy();
1629
- const { store } = useChat();
1630
- const { colors: colors2, space: space2, font: font2 } = useTheme();
1646
+ const { store, slots } = useChat();
1647
+ const conversationId = useConversationSelector(
1648
+ store,
1649
+ (v) => v.conversationId
1650
+ );
1631
1651
  const { event, data } = props.item;
1652
+ if (event === "turn_failed") {
1653
+ const key = props.item.key;
1654
+ const state = {
1655
+ kind: "turn_failed",
1656
+ reason: typeof data.code === "string" ? data.code : null,
1657
+ retry: data.retry === true ? () => void store.retryTurn(key) : void 0,
1658
+ conversationId
1659
+ };
1660
+ return /* @__PURE__ */ jsx(
1661
+ FailureSlot,
1662
+ {
1663
+ slot: slots.Error,
1664
+ state,
1665
+ Default: DefaultTurnFailed
1666
+ }
1667
+ );
1668
+ }
1632
1669
  const agent = store.getSnapshot().agent.name ?? t("agentFallbackName");
1633
1670
  const text = (() => {
1634
1671
  switch (event) {
@@ -1642,18 +1679,30 @@ var SystemRow = memo(function SystemRow2(props) {
1642
1679
  return data.expected_response ? t("handoffCreated", { expected: data.expected_response }) : t("handoffCreatedNoTime");
1643
1680
  case "flow_completed":
1644
1681
  return data.result === "ok" ? t("flowSent") : data.result === "failed" ? t("flowNotSent") : null;
1645
- case "turn_failed":
1646
- return t("turnFailed");
1647
1682
  default:
1648
1683
  return null;
1649
1684
  }
1650
1685
  })();
1651
1686
  if (!text) return null;
1687
+ return /* @__PURE__ */ jsx(Line, { text });
1688
+ });
1689
+ function DefaultTurnFailed(props) {
1690
+ const { t } = useCopy();
1691
+ const { failureAction } = useChat();
1692
+ const text = t("turnFailed");
1693
+ if (!failureAction) return /* @__PURE__ */ jsx(Line, { text, danger: true });
1694
+ return /* @__PURE__ */ jsxs(View, { style: { alignItems: "center" }, children: [
1695
+ /* @__PURE__ */ jsx(Line, { text, danger: true }),
1696
+ /* @__PURE__ */ jsx(FailureActionButton, { state: props.state })
1697
+ ] });
1698
+ }
1699
+ function Line(props) {
1700
+ const { colors: colors2, space: space2, font: font2 } = useTheme();
1652
1701
  return /* @__PURE__ */ jsx(
1653
1702
  View,
1654
1703
  {
1655
1704
  accessible: true,
1656
- accessibilityLabel: text,
1705
+ accessibilityLabel: props.text,
1657
1706
  style: {
1658
1707
  alignItems: "center",
1659
1708
  paddingHorizontal: space2.xl,
@@ -1663,16 +1712,16 @@ var SystemRow = memo(function SystemRow2(props) {
1663
1712
  Text,
1664
1713
  {
1665
1714
  style: {
1666
- color: event === "turn_failed" ? colors2.danger : colors2.textMuted,
1715
+ color: props.danger ? colors2.danger : colors2.textMuted,
1667
1716
  fontSize: font2.size.sm,
1668
1717
  textAlign: "center"
1669
1718
  },
1670
- children: text
1719
+ children: props.text
1671
1720
  }
1672
1721
  )
1673
1722
  }
1674
1723
  );
1675
- });
1724
+ }
1676
1725
  var keyOf = (item) => item.key;
1677
1726
  function itemType(item) {
1678
1727
  if (item.type === "card") return `card:${item.card.kind}`;
@@ -1757,10 +1806,23 @@ function useAnnounceReplies(items) {
1757
1806
  }
1758
1807
  var CONNECTING_DELAY = motion.bannerDelay;
1759
1808
  var StatusBanner = memo(function StatusBanner2() {
1760
- const { store } = useChat();
1809
+ const { store, slots } = useChat();
1761
1810
  const { t } = useCopy();
1762
- const { colors: colors2, space: space2, font: font2 } = useTheme();
1763
1811
  const banner = useConversationSelector(store, (v) => v.banner);
1812
+ const status = useConversationSelector(store, (v) => v.status);
1813
+ const conversationId = useConversationSelector(
1814
+ store,
1815
+ (v) => v.conversationId
1816
+ );
1817
+ const unavailable = useMemo(
1818
+ () => ({
1819
+ kind: "unavailable",
1820
+ reason: status,
1821
+ retry: () => store.start(),
1822
+ conversationId
1823
+ }),
1824
+ [store, status, conversationId]
1825
+ );
1764
1826
  const [late, setLate] = useState(false);
1765
1827
  useEffect(() => {
1766
1828
  setLate(false);
@@ -1769,12 +1831,20 @@ var StatusBanner = memo(function StatusBanner2() {
1769
1831
  return () => clearTimeout(timer);
1770
1832
  }, [banner]);
1771
1833
  if (banner === null || banner === "connecting" && !late) return null;
1834
+ if (banner === "unavailable")
1835
+ return /* @__PURE__ */ jsx(
1836
+ FailureSlot,
1837
+ {
1838
+ slot: slots.Unavailable,
1839
+ state: unavailable,
1840
+ Default: DefaultUnavailable
1841
+ }
1842
+ );
1772
1843
  const text = {
1773
1844
  connecting: t("bannerConnecting"),
1774
1845
  reconnecting: t("bannerReconnecting"),
1775
1846
  offline: t("bannerOffline"),
1776
- continued_elsewhere: t("bannerContinuedElsewhere"),
1777
- unavailable: t("bannerUnavailable")
1847
+ continued_elsewhere: t("bannerContinuedElsewhere")
1778
1848
  }[banner];
1779
1849
  const action = banner === "continued_elsewhere" ? /* @__PURE__ */ jsx(
1780
1850
  Button,
@@ -1783,7 +1853,7 @@ var StatusBanner = memo(function StatusBanner2() {
1783
1853
  variant: "text",
1784
1854
  onPress: () => void store.continueHere()
1785
1855
  }
1786
- ) : banner === "offline" || banner === "unavailable" ? /* @__PURE__ */ jsx(
1856
+ ) : banner === "offline" ? /* @__PURE__ */ jsx(
1787
1857
  Button,
1788
1858
  {
1789
1859
  label: t("tryAgain"),
@@ -1791,6 +1861,18 @@ var StatusBanner = memo(function StatusBanner2() {
1791
1861
  onPress: () => store.start()
1792
1862
  }
1793
1863
  ) : null;
1864
+ return /* @__PURE__ */ jsx(Banner, { text, children: action });
1865
+ });
1866
+ function DefaultUnavailable(props) {
1867
+ const { t } = useCopy();
1868
+ const { retry } = props.state;
1869
+ return /* @__PURE__ */ jsxs(Banner, { text: t("bannerUnavailable"), children: [
1870
+ retry ? /* @__PURE__ */ jsx(Button, { label: t("tryAgain"), variant: "text", onPress: retry }) : null,
1871
+ /* @__PURE__ */ jsx(FailureActionButton, { state: props.state })
1872
+ ] });
1873
+ }
1874
+ function Banner(props) {
1875
+ const { colors: colors2, space: space2, font: font2 } = useTheme();
1794
1876
  return /* @__PURE__ */ jsxs(
1795
1877
  View,
1796
1878
  {
@@ -1812,22 +1894,35 @@ var StatusBanner = memo(function StatusBanner2() {
1812
1894
  Text,
1813
1895
  {
1814
1896
  style: { color: colors2.text, fontSize: font2.size.sm, flexShrink: 1 },
1815
- children: text
1897
+ children: props.text
1816
1898
  }
1817
1899
  ),
1818
- action
1900
+ props.children
1819
1901
  ]
1820
1902
  }
1821
1903
  );
1822
- });
1904
+ }
1823
1905
  function VinaverseChatProvider(props) {
1824
1906
  const { conversation, components, agentAvatar, timeZone } = props;
1825
1907
  const handlers = useRef(props);
1826
1908
  handlers.current = props;
1827
1909
  const slots = useStableSlots(components);
1910
+ const hasAction = props.failureAction !== void 0;
1911
+ const actionLabel = props.failureAction?.label;
1912
+ const failureAction = useMemo(
1913
+ () => hasAction ? { label: actionLabel } : null,
1914
+ [hasAction, actionLabel]
1915
+ );
1828
1916
  const value = useMemo(
1829
- () => ({ store: conversation, handlers, slots, agentAvatar, timeZone }),
1830
- [conversation, slots, agentAvatar, timeZone]
1917
+ () => ({
1918
+ store: conversation,
1919
+ handlers,
1920
+ slots,
1921
+ agentAvatar,
1922
+ timeZone,
1923
+ failureAction
1924
+ }),
1925
+ [conversation, slots, agentAvatar, timeZone, failureAction]
1831
1926
  );
1832
1927
  useNativeLifecycle(conversation);
1833
1928
  useEffect(() => {
@@ -1903,6 +1998,6 @@ function sameSlots(a, b) {
1903
1998
  return true;
1904
1999
  }
1905
2000
 
1906
- export { ActivityLine, Avatar, Button, CardFrame, CardView, ChatHeader, ChatSkeleton, Composer, DefaultBubble, DefaultComposer, DefaultHeader, DisclosureBar, InfoCard, MessageBubble, MessageList, NextStepCard, ProposalCard, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeProvider, TimeSlotsCard, VinaverseChat, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
2001
+ export { ActivityLine, Avatar, Button, CardFrame, CardView, ChatHeader, ChatSkeleton, Composer, DefaultBubble, DefaultComposer, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DisclosureBar, FailureActionButton, InfoCard, MessageBubble, MessageList, NextStepCard, ProposalCard, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeProvider, TimeSlotsCard, VinaverseChat, VinaverseChatProvider, announce, answerText, createTheme, defaultCard, fieldText, itemType, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
1907
2002
  //# sourceMappingURL=index.js.map
1908
2003
  //# sourceMappingURL=index.js.map