@vinaverse/react-native 0.1.0-alpha.7 → 0.1.0-alpha.9

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.
@@ -33,7 +33,7 @@ function Row(props) {
33
33
  backgroundColor: look?.background ?? colors.surface,
34
34
  opacity: pressed ? 0.85 : 1
35
35
  }),
36
- testID: "vinaverse-ask-about",
36
+ testID: props.testID ?? "vinaverse-ask-about",
37
37
  children: [
38
38
  /* @__PURE__ */ jsx(
39
39
  View,
@@ -70,5 +70,5 @@ function Row(props) {
70
70
  }
71
71
 
72
72
  export { AskAboutRow };
73
- //# sourceMappingURL=chunk-NJ6ARGZS.js.map
74
- //# sourceMappingURL=chunk-NJ6ARGZS.js.map
73
+ //# sourceMappingURL=chunk-7KPCO443.js.map
74
+ //# sourceMappingURL=chunk-7KPCO443.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/AskAboutRow.tsx"],"names":[],"mappings":"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","file":"chunk-7KPCO443.js","sourcesContent":["// \"Ask the agent about this\" on one of the app's own pages (a professional's, a space's, a booking's): a row that opens\n// the agent told the place. It shows only when the agent is available, decided once as the page draws, from the status\n// already read, so it never appears or disappears under content the person is reading.\nimport { type CopyOverrides, CopyProvider, useCopy } from '@vinaverse/react';\nimport {\n useAgentName,\n useAgentRuntime,\n useAgentStatus,\n} from '@vinaverse/react/agent';\nimport { type ComponentType, type ReactNode, useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { useAgentSweep } from '../platform.js';\nimport {\n type ColorSchemeSetting,\n type ThemeOverrides,\n ThemeProvider,\n useTheme,\n} from '../theme.js';\n\n/** The row's look beyond the theme. */\nexport interface AskAboutRowAppearance {\n /** A tint behind the row; default the theme's `surface`. */\n readonly background?: string;\n /** The chevron at the row's end. Default true. */\n readonly chevron?: boolean;\n}\n\nexport interface AskAboutRowProps {\n /** \"Ask Example Agent about Riley Sample\". */\n readonly title: string;\n readonly body?: string;\n /** The person asks: open the chat with `entryPoint` (`ask`), so the session says where it was opened from. */\n readonly onPress: (from: { readonly entryPoint: 'ask' }) => void;\n /** The app's brand mark at the row's start; default the agent name's first letter. */\n readonly Mark?: ComponentType<{\n readonly size: number;\n readonly color: string;\n }>;\n readonly appearance?: AskAboutRowAppearance;\n readonly locale?: string;\n readonly copy?: CopyOverrides;\n readonly theme?: ThemeOverrides;\n readonly colorScheme?: ColorSchemeSetting;\n /** The row's test id. Default `vinaverse-ask-about`. */\n readonly testID?: string;\n}\n\nexport function AskAboutRow(props: AskAboutRowProps): ReactNode {\n return (\n <CopyProvider locale={props.locale} copy={props.copy}>\n <ThemeProvider theme={props.theme} colorScheme={props.colorScheme}>\n <Row {...props} />\n </ThemeProvider>\n </CopyProvider>\n );\n}\n\nfunction Row(props: AskAboutRowProps): ReactNode {\n const { t } = useCopy();\n const { colors, radius, space, font } = useTheme();\n const name = useAgentName(t('agentFallbackName'));\n const runtime = useAgentRuntime();\n useAgentStatus(); // reads the status when none is held, for the pages after this one\n useAgentSweep(runtime);\n // Decided once, as the page draws, from the status already read: an agent unknown or unavailable then stays away for\n // the visit, and the row is never added under content the person is reading.\n const [shows] = useState(() => !!runtime.getStatus()?.available);\n if (!shows) return null;\n const { Mark, appearance: look } = props;\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={\n props.body ? `${props.title}. ${props.body}` : props.title\n }\n onPress={() => props.onPress({ entryPoint: 'ask' })}\n style={({ pressed }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n gap: space.md,\n padding: space.md,\n borderRadius: radius.lg,\n backgroundColor: look?.background ?? colors.surface,\n opacity: pressed ? 0.85 : 1,\n })}\n testID={props.testID ?? 'vinaverse-ask-about'}\n >\n <View\n style={{\n width: 36,\n height: 36,\n borderRadius: 18,\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: colors.primary,\n }}\n >\n {Mark ? (\n <Mark size={22} color={colors.onPrimary} />\n ) : (\n <Text style={{ color: colors.onPrimary, fontWeight: '600' }}>\n {(name.trim()[0] ?? '?').toUpperCase()}\n </Text>\n )}\n </View>\n <View style={{ flex: 1, gap: space.xxs }}>\n <Text\n style={{\n color: colors.text,\n fontSize: font.size.md,\n fontWeight: '600',\n }}\n >\n {props.title}\n </Text>\n {props.body ? (\n <Text style={{ color: colors.textMuted, fontSize: font.size.sm }}>\n {props.body}\n </Text>\n ) : null}\n </View>\n {look?.chevron === false ? null : (\n <Text style={{ color: colors.textMuted, fontSize: font.size.lg }}>\n ›\n </Text>\n )}\n </Pressable>\n );\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { useTheme, useReducedMotion, announce, useNativeLifecycle, themeProblems, ThemeProvider, useAgentSweep } from './chunk-EFEXTVIT.js';
2
2
  import { useAgentRuntime, useAgentConversation, useAgentName } from '@vinaverse/react/agent';
3
- export { AgentRuntimeProvider, forgetGreeting, greetedKey, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus } from '@vinaverse/react/agent';
3
+ export { AgentRuntimeProvider, forgetGreeting, greetedKey, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus, useAgentStatusState } from '@vinaverse/react/agent';
4
4
  import { FlashList } from '@shopify/flash-list';
5
- import { useCopy, formatMoney, formatTimeRange, useConversationSelector, formatDate, useStreamingText, bannedWordsIn, CopyProvider } from '@vinaverse/react';
5
+ import { useCopy, formatMoney, formatTimeRange, formatDayTime, useConversationSelector, formatDate, useStreamingText, bannedWordsIn, CopyProvider } from '@vinaverse/react';
6
6
  import { Pressable, ActivityIndicator, Text, View, Image, Linking, TextInput, useWindowDimensions, Platform, KeyboardAvoidingView } from 'react-native';
7
7
  import { readCard } from '@vinaverse/client/agent';
8
8
  import { useContext, memo, useState, useMemo, useCallback, useRef, useEffect, createContext } from 'react';
@@ -170,7 +170,7 @@ function safeImage(url) {
170
170
  function InfoCard(props) {
171
171
  const card = cardOf(props.card);
172
172
  const { locale, t } = useCopy();
173
- const { slots, timeZone } = useChat();
173
+ const { slots, timeZone, handlers } = useChat();
174
174
  const { colors, radius, space, font } = useTheme();
175
175
  const image = safeImage(card.image_url);
176
176
  const Img = slots.Image ?? Image;
@@ -179,13 +179,42 @@ function InfoCard(props) {
179
179
  const amount = money ? formatMoney(money.amount, money.currency, locale) : null;
180
180
  const price = amount && !card.price ? t("priceFrom", { price: amount }) : amount;
181
181
  const when = card.starts_at ? formatTimeRange(card.starts_at, void 0, locale, timeZone) : null;
182
+ const status = typeof card.status === "string" && card.status ? card.status : null;
183
+ const ref = card.ref;
184
+ const onOpenTarget = handlers.current?.onOpenTarget;
185
+ const open = ref && onOpenTarget && !props.restored ? () => onOpenTarget({ type: ref.type, id: ref.id }, props.card) : null;
182
186
  const label = [
183
187
  card.title,
184
188
  card.subtitle,
189
+ status,
185
190
  rating && `\u2605 ${rating}`,
186
191
  price,
187
192
  when
188
193
  ].filter(Boolean).join(", ");
194
+ const top = /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: space.md }, children: [
195
+ image ? /* @__PURE__ */ jsx(
196
+ Img,
197
+ {
198
+ source: { uri: image },
199
+ style: {
200
+ width: 64,
201
+ height: 64,
202
+ borderRadius: radius.md,
203
+ backgroundColor: colors.surface
204
+ },
205
+ accessible: false
206
+ }
207
+ ) : null,
208
+ /* @__PURE__ */ jsxs(View, { style: { flex: 1, gap: space.xxs }, children: [
209
+ /* @__PURE__ */ jsx(Title, { numberOfLines: 2, children: card.title }),
210
+ card.subtitle ? /* @__PURE__ */ jsx(Body, { muted: true, children: card.subtitle }) : null,
211
+ /* @__PURE__ */ jsx(Text, { style: { color: colors.textMuted, fontSize: font.size.sm }, children: [
212
+ rating && `\u2605 ${rating}${card.rating ? ` (${card.rating.count})` : ""}`,
213
+ price,
214
+ when
215
+ ].filter(Boolean).join(" \xB7 ") })
216
+ ] })
217
+ ] });
189
218
  return /* @__PURE__ */ jsxs(
190
219
  CardFrame,
191
220
  {
@@ -193,32 +222,23 @@ function InfoCard(props) {
193
222
  restored: props.restored,
194
223
  testID: `vinaverse-card-${card.id}`,
195
224
  children: [
196
- /* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", gap: space.md }, children: [
197
- image ? /* @__PURE__ */ jsx(
198
- Img,
199
- {
200
- source: { uri: image },
201
- style: {
202
- width: 64,
203
- height: 64,
204
- borderRadius: radius.md,
205
- backgroundColor: colors.surface
206
- },
207
- accessible: false
208
- }
209
- ) : null,
210
- /* @__PURE__ */ jsxs(View, { style: { flex: 1, gap: space.xxs }, children: [
211
- /* @__PURE__ */ jsx(Title, { numberOfLines: 2, children: card.title }),
212
- card.subtitle ? /* @__PURE__ */ jsx(Body, { muted: true, children: card.subtitle }) : null,
213
- /* @__PURE__ */ jsx(Text, { style: { color: colors.textMuted, fontSize: font.size.sm }, children: [
214
- rating && `\u2605 ${rating}${card.rating ? ` (${card.rating.count})` : ""}`,
215
- price,
216
- when
217
- ].filter(Boolean).join(" \xB7 ") })
218
- ] })
219
- ] }),
225
+ open ? /* @__PURE__ */ jsx(
226
+ Pressable,
227
+ {
228
+ accessibilityRole: "link",
229
+ accessibilityLabel: card.title,
230
+ onPress: open,
231
+ testID: `vinaverse-open-${card.id}`,
232
+ children: top
233
+ }
234
+ ) : top,
220
235
  card.body ? /* @__PURE__ */ jsx(Body, { children: card.body }) : null,
221
- /* @__PURE__ */ jsx(Badges, { badges: card.badges }),
236
+ /* @__PURE__ */ jsx(
237
+ Badges,
238
+ {
239
+ badges: status ? [status, ...card.badges ?? []] : card.badges
240
+ }
241
+ ),
222
242
  props.restored ? null : /* @__PURE__ */ jsx(CardActions, { ...props })
223
243
  ]
224
244
  }
@@ -320,7 +340,7 @@ function ListingCard(props) {
320
340
  );
321
341
  const hero = photoUrl === failed ? null : photoUrl;
322
342
  const Img = slots.Image ?? Image;
323
- const rating = card.rating ? `\u2605 ${ratingText(card.rating.value_ppm, locale)} (${card.rating.count})` : null;
343
+ const rating = card.rating ? `\u2605 ${ratingText(card.rating.value_ppm, locale)} (${card.rating.count})` : t("ratingNone") || null;
324
344
  const price = card.price_from ? t("priceFrom", {
325
345
  price: formatMoney(
326
346
  card.price_from.amount,
@@ -329,14 +349,24 @@ function ListingCard(props) {
329
349
  )
330
350
  }) : null;
331
351
  const next = card.next_available ? t("nextAvailable", {
332
- time: formatTimeRange(card.next_available, void 0, locale, timeZone)
352
+ // "today, 10:00 AM", "tomorrow, 10:00 AM", else the date (the copy's `today` and `tomorrow`).
353
+ time: formatDayTime(
354
+ card.next_available,
355
+ { today: t("today"), tomorrow: t("tomorrow") },
356
+ locale,
357
+ timeZone
358
+ )
333
359
  }) : null;
334
360
  const ref = card.ref;
335
361
  const onOpenTarget = handlers.current?.onOpenTarget;
336
362
  const open = ref && onOpenTarget && !props.restored ? () => onOpenTarget({ type: ref.type, id: ref.id }, props.card) : null;
363
+ const asked = imagePolicy?.aspectRatio;
364
+ const size2 = card.images?.[0];
365
+ const range = imagePolicy?.naturalAspect ?? { min: 1, max: 2 };
366
+ const own = asked === "natural" && !props.grouped && size2?.width && size2.height ? Math.min(range.max, Math.max(range.min, size2.width / size2.height)) : null;
337
367
  const photo = {
338
368
  width: "100%",
339
- aspectRatio: imagePolicy?.aspectRatio ?? 1.6,
369
+ aspectRatio: own ?? (typeof asked === "number" ? asked : 1.6),
340
370
  borderRadius: radius.md
341
371
  };
342
372
  const top = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -349,7 +379,7 @@ function ListingCard(props) {
349
379
  accessible: false,
350
380
  testID: `vinaverse-photo-${card.id}`
351
381
  }
352
- ) : imagePolicy?.Placeholder ? /* @__PURE__ */ jsx(View, { style: photo, testID: `vinaverse-placeholder-${card.id}`, children: /* @__PURE__ */ jsx(imagePolicy.Placeholder, { title: card.title }) }) : /* @__PURE__ */ jsx(
382
+ ) : imagePolicy?.Placeholder ? /* @__PURE__ */ jsx(View, { style: photo, testID: `vinaverse-placeholder-${card.id}`, children: /* @__PURE__ */ jsx(imagePolicy.Placeholder, { title: card.title, kind: card.kind }) }) : /* @__PURE__ */ jsx(
353
383
  View,
354
384
  {
355
385
  accessible: false,
@@ -504,7 +534,9 @@ function ProposalCard(props) {
504
534
  props.card.id,
505
535
  () => onProposal(props.card, decision)
506
536
  ).catch(
507
- (error) => handlers.current?.onWarning?.(`Vinaverse proposal: ${String(error)}`)
537
+ (error) => handlers.current?.onWarning?.(`Vinaverse proposal: ${String(error)}`, {
538
+ code: "proposal_failed"
539
+ })
508
540
  );
509
541
  };
510
542
  const fields = proposal.fields.map((f) => {
@@ -626,7 +658,9 @@ function QuestionCard(props) {
626
658
  try {
627
659
  store.answer(held.id, questionId, answer);
628
660
  } catch (error) {
629
- handlers.current?.onWarning?.(`Vinaverse answer: ${String(error)}`);
661
+ handlers.current?.onWarning?.(`Vinaverse answer: ${String(error)}`, {
662
+ code: "answer_failed"
663
+ });
630
664
  }
631
665
  };
632
666
  const locked = held.locked.includes(question.question_id);
@@ -737,7 +771,8 @@ function Answer(props) {
737
771
  if (picked) send({ upload_ref: picked.upload_ref });
738
772
  }).catch(
739
773
  (error) => handlers.current?.onWarning?.(
740
- `Vinaverse photo: ${String(error)}`
774
+ `Vinaverse photo: ${String(error)}`,
775
+ { code: "photo_failed" }
741
776
  )
742
777
  );
743
778
  }
@@ -1290,7 +1325,13 @@ var CardView = /* @__PURE__ */ memo(function CardView2(props) {
1290
1325
  const Default = defaultCard(card.kind);
1291
1326
  const Custom = slots.cards?.[card.kind];
1292
1327
  const read = useMemo(() => readCard(card.card), [card]);
1293
- const own = { card, read, busy, restored: props.item.restored === true };
1328
+ const own = {
1329
+ card,
1330
+ read,
1331
+ busy,
1332
+ restored: props.item.restored === true,
1333
+ grouped: props.grouped === true
1334
+ };
1294
1335
  return Custom ? /* @__PURE__ */ jsx(Custom, { ...own, Default }) : /* @__PURE__ */ jsx(Default, { ...own });
1295
1336
  });
1296
1337
  var keyOf = (item) => item.key;
@@ -1313,7 +1354,7 @@ function CardCarousel(props) {
1313
1354
  data: props.items,
1314
1355
  keyExtractor: keyOf,
1315
1356
  getItemType: kindOf,
1316
- renderItem: ({ item }) => /* @__PURE__ */ jsx(View, { style: { width: size2 }, children: /* @__PURE__ */ jsx(CardView, { item }) }),
1357
+ renderItem: ({ item }) => /* @__PURE__ */ jsx(View, { style: { width: size2 }, children: /* @__PURE__ */ jsx(CardView, { item, grouped: true }) }),
1317
1358
  snapToInterval: size2,
1318
1359
  decelerationRate: "fast",
1319
1360
  showsHorizontalScrollIndicator: false
@@ -1899,29 +1940,27 @@ function authorOf(item) {
1899
1940
  return item?.type === "message" ? item.role : null;
1900
1941
  }
1901
1942
  function carousels(items, previous) {
1943
+ const groups = /* @__PURE__ */ new Map();
1944
+ for (const item of items) {
1945
+ if (item.type !== "card") continue;
1946
+ const group = item.card.card.group;
1947
+ if (group?.layout !== "carousel" || typeof group.id !== "string") continue;
1948
+ const id = `${item.card.turnId ?? ""}\0${group.id}`;
1949
+ const members = groups.get(id);
1950
+ if (members) members.push(item);
1951
+ else groups.set(id, [item]);
1952
+ }
1902
1953
  const runs = /* @__PURE__ */ new Map();
1903
1954
  const inside = /* @__PURE__ */ new Set();
1904
- const groupOf = (item) => {
1905
- if (item?.type !== "card") return null;
1906
- const group = item.card.card.group;
1907
- return group?.layout === "carousel" && typeof group.id === "string" ? group.id : null;
1908
- };
1909
- for (let i = 0; i < items.length; i++) {
1910
- const id = groupOf(items[i]);
1911
- if (id === null) continue;
1912
- let end = i + 1;
1913
- while (end < items.length && groupOf(items[end]) === id) end++;
1914
- if (end - i > 1) {
1915
- const run = items.slice(i, end);
1916
- const key = run[0]?.key;
1917
- const before = previous.get(key);
1918
- runs.set(
1919
- key,
1920
- before && before.length === run.length && before.every((c, n) => c === run[n]) ? before : run
1921
- );
1922
- for (const card of run.slice(1)) inside.add(card.key);
1923
- }
1924
- i = end - 1;
1955
+ for (const run of groups.values()) {
1956
+ if (run.length < 2) continue;
1957
+ const key = run[0]?.key;
1958
+ const before = previous.get(key);
1959
+ runs.set(
1960
+ key,
1961
+ before && before.length === run.length && before.every((c, n) => c === run[n]) ? before : run
1962
+ );
1963
+ for (const card of run.slice(1)) inside.add(card.key);
1925
1964
  }
1926
1965
  return { runs, inside };
1927
1966
  }
@@ -2198,10 +2237,11 @@ function VinaverseChatProvider(props) {
2198
2237
  useEffect(() => {
2199
2238
  if (!onWarning) return;
2200
2239
  for (const problem of themeProblems(theme))
2201
- onWarning(`Vinaverse theme: ${problem}`);
2240
+ onWarning(`Vinaverse theme: ${problem}`, { code: "theme" });
2202
2241
  for (const key of bannedWordsIn(copy ?? {}))
2203
2242
  onWarning(
2204
- `Vinaverse copy: "${key}" says assistant, bot or crew; the copy says agent.`
2243
+ `Vinaverse copy: "${key}" says assistant, bot or crew; the copy says agent.`,
2244
+ { code: "copy" }
2205
2245
  );
2206
2246
  }, [onWarning, theme, copy]);
2207
2247
  return /* @__PURE__ */ jsx(CopyProvider, { locale: props.locale, copy: props.copy, children: /* @__PURE__ */ jsx(ThemeProvider, { theme: props.theme, colorScheme: props.colorScheme, children: /* @__PURE__ */ jsx(ChatContextProvider, { value, children: props.children }) }) });
@@ -2225,7 +2265,7 @@ function Layout(props) {
2225
2265
  const { direction } = useCopy();
2226
2266
  const { onError } = props;
2227
2267
  const reportError = useMemo(
2228
- () => onError ? (e) => onError(String(e)) : void 0,
2268
+ () => onError ? (e) => onError(String(e), { code: "send_failed" }) : void 0,
2229
2269
  [onError]
2230
2270
  );
2231
2271
  return /* @__PURE__ */ jsxs(
@@ -2558,5 +2598,5 @@ function AgentFooter(props) {
2558
2598
  }
2559
2599
 
2560
2600
  export { ActivityLine, AgentChat, AgentFooter, Avatar, Button, CardActions, CardCarousel, CardFrame, CardView, ChatHeader, ChatSkeleton, Composer, DefaultBubble, DefaultComposer, DefaultEnded, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, DisclosureBar, FailureActionButton, InfoCard, LinksCard, ListingCard, MessageBubble, MessageList, NextStepCard, ProposalCard, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, TimeSlotsCard, VinaverseChat, VinaverseChatProvider, Welcome, allowedImage, answerText, carousels, defaultCard, fieldText, itemType, monogram, newestWholeReply, ratingText, useChat };
2561
- //# sourceMappingURL=chunk-HTUXHZ7X.js.map
2562
- //# sourceMappingURL=chunk-HTUXHZ7X.js.map
2601
+ //# sourceMappingURL=chunk-GIQYOTNH.js.map
2602
+ //# sourceMappingURL=chunk-GIQYOTNH.js.map