@vinaverse/react-native 0.1.0-alpha.3 → 0.1.0-alpha.4
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/README.md +32 -2
- package/dist/index.cjs +342 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -64
- package/dist/index.d.ts +110 -64
- package/dist/index.js +336 -83
- package/dist/index.js.map +1 -1
- package/package.json +37 -5
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FlashList } from '@shopify/flash-list';
|
|
2
|
+
import { useCopy, useConversationSelector, useStreamingText, formatMoney, formatTimeRange, formatDate, bannedWordsIn, CopyProvider } from '@vinaverse/react';
|
|
3
|
+
import { Pressable, ActivityIndicator, Text, View, Image, TextInput, AccessibilityInfo, Linking, useColorScheme, useWindowDimensions, AppState, Platform, KeyboardAvoidingView } from 'react-native';
|
|
2
4
|
import { createContext, memo, useCallback, useState, useRef, useMemo, useEffect, useContext } from 'react';
|
|
3
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
6
|
import { contrastRatio, colors, size, motion, radius, space, font, contrastProblems } from '@vinaverse/tokens';
|
|
5
|
-
import { useCopy, useConversationSelector, useStreamingText, formatTimeRange, formatMoney, formatDate, bannedWordsIn, CopyProvider } from '@vinaverse/react';
|
|
6
7
|
import { codePoints, MAX_TEXT, answerProblem } from '@vinaverse/client/conversation';
|
|
7
|
-
import { FlashList } from '@shopify/flash-list';
|
|
8
8
|
|
|
9
|
-
// src/cards/
|
|
9
|
+
// src/cards/CardCarousel.tsx
|
|
10
10
|
var ChatContext = createContext(null);
|
|
11
11
|
function ChatContextProvider(props) {
|
|
12
12
|
return /* @__PURE__ */ jsx(ChatContext.Provider, { value: props.value, children: props.children });
|
|
@@ -55,6 +55,61 @@ function ThemeProvider(props) {
|
|
|
55
55
|
function useTheme() {
|
|
56
56
|
return useContext(ThemeContext);
|
|
57
57
|
}
|
|
58
|
+
var Button = memo(function Button2(props) {
|
|
59
|
+
const { colors: colors2, radius: radius2, space: space2, size: size3, font: font2 } = useTheme();
|
|
60
|
+
const variant = props.variant ?? "secondary";
|
|
61
|
+
const inactive = props.disabled === true || props.busy === true;
|
|
62
|
+
const filled = variant === "primary" || props.selected === true;
|
|
63
|
+
const background = filled ? colors2.primary : variant === "secondary" ? colors2.surface : "transparent";
|
|
64
|
+
const foreground = filled ? colors2.onPrimary : colors2.primary;
|
|
65
|
+
const checkable = props.role === "radio" || props.role === "checkbox";
|
|
66
|
+
return /* @__PURE__ */ jsxs(
|
|
67
|
+
Pressable,
|
|
68
|
+
{
|
|
69
|
+
accessibilityRole: props.role ?? "button",
|
|
70
|
+
accessibilityLabel: props.label,
|
|
71
|
+
...props.hint ? { accessibilityHint: props.hint } : {},
|
|
72
|
+
accessibilityState: {
|
|
73
|
+
disabled: inactive,
|
|
74
|
+
busy: props.busy === true,
|
|
75
|
+
...checkable ? props.role === "radio" ? { selected: props.selected === true } : { checked: props.selected === true } : {}
|
|
76
|
+
},
|
|
77
|
+
disabled: inactive,
|
|
78
|
+
onPress: props.onPress,
|
|
79
|
+
...props.testID ? { testID: props.testID } : {},
|
|
80
|
+
style: ({ pressed }) => ({
|
|
81
|
+
minHeight: size3.touchTarget,
|
|
82
|
+
minWidth: size3.touchTarget,
|
|
83
|
+
paddingHorizontal: space2.md,
|
|
84
|
+
paddingVertical: space2.sm,
|
|
85
|
+
borderRadius: radius2.md,
|
|
86
|
+
borderWidth: variant === "text" ? 0 : 1,
|
|
87
|
+
borderColor: filled ? colors2.primary : colors2.border,
|
|
88
|
+
backgroundColor: background,
|
|
89
|
+
opacity: inactive ? 0.55 : pressed ? 0.8 : 1,
|
|
90
|
+
alignItems: "center",
|
|
91
|
+
justifyContent: "center",
|
|
92
|
+
flexDirection: "row",
|
|
93
|
+
gap: space2.xs
|
|
94
|
+
}),
|
|
95
|
+
children: [
|
|
96
|
+
props.busy ? /* @__PURE__ */ jsx(ActivityIndicator, { color: foreground }) : null,
|
|
97
|
+
props.children ?? /* @__PURE__ */ jsx(
|
|
98
|
+
Text,
|
|
99
|
+
{
|
|
100
|
+
style: {
|
|
101
|
+
color: foreground,
|
|
102
|
+
fontSize: font2.size.md,
|
|
103
|
+
fontWeight: "500",
|
|
104
|
+
...font2.family ? { fontFamily: font2.family } : {}
|
|
105
|
+
},
|
|
106
|
+
children: props.label
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
});
|
|
58
113
|
function cardOf(held) {
|
|
59
114
|
return held.card;
|
|
60
115
|
}
|
|
@@ -123,64 +178,20 @@ function useLink(link, held) {
|
|
|
123
178
|
if (!link || !store.checkLink(link)) return null;
|
|
124
179
|
return () => handlers.current?.onOpenLink?.(link, held);
|
|
125
180
|
}
|
|
181
|
+
function ratingText(valuePpm, locale) {
|
|
182
|
+
const value = valuePpm / 1e6;
|
|
183
|
+
try {
|
|
184
|
+
return new Intl.NumberFormat(locale, {
|
|
185
|
+
minimumFractionDigits: 1,
|
|
186
|
+
maximumFractionDigits: 1
|
|
187
|
+
}).format(value);
|
|
188
|
+
} catch {
|
|
189
|
+
return value.toFixed(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
126
192
|
function safeImage(url) {
|
|
127
193
|
return url && /^https:\/\//i.test(url) ? url : null;
|
|
128
194
|
}
|
|
129
|
-
var Button = memo(function Button2(props) {
|
|
130
|
-
const { colors: colors2, radius: radius2, space: space2, size: size3, font: font2 } = useTheme();
|
|
131
|
-
const variant = props.variant ?? "secondary";
|
|
132
|
-
const inactive = props.disabled === true || props.busy === true;
|
|
133
|
-
const filled = variant === "primary" || props.selected === true;
|
|
134
|
-
const background = filled ? colors2.primary : variant === "secondary" ? colors2.surface : "transparent";
|
|
135
|
-
const foreground = filled ? colors2.onPrimary : colors2.primary;
|
|
136
|
-
const checkable = props.role === "radio" || props.role === "checkbox";
|
|
137
|
-
return /* @__PURE__ */ jsxs(
|
|
138
|
-
Pressable,
|
|
139
|
-
{
|
|
140
|
-
accessibilityRole: props.role ?? "button",
|
|
141
|
-
accessibilityLabel: props.label,
|
|
142
|
-
...props.hint ? { accessibilityHint: props.hint } : {},
|
|
143
|
-
accessibilityState: {
|
|
144
|
-
disabled: inactive,
|
|
145
|
-
busy: props.busy === true,
|
|
146
|
-
...checkable ? props.role === "radio" ? { selected: props.selected === true } : { checked: props.selected === true } : {}
|
|
147
|
-
},
|
|
148
|
-
disabled: inactive,
|
|
149
|
-
onPress: props.onPress,
|
|
150
|
-
...props.testID ? { testID: props.testID } : {},
|
|
151
|
-
style: ({ pressed }) => ({
|
|
152
|
-
minHeight: size3.touchTarget,
|
|
153
|
-
minWidth: size3.touchTarget,
|
|
154
|
-
paddingHorizontal: space2.md,
|
|
155
|
-
paddingVertical: space2.sm,
|
|
156
|
-
borderRadius: radius2.md,
|
|
157
|
-
borderWidth: variant === "text" ? 0 : 1,
|
|
158
|
-
borderColor: filled ? colors2.primary : colors2.border,
|
|
159
|
-
backgroundColor: background,
|
|
160
|
-
opacity: inactive ? 0.55 : pressed ? 0.8 : 1,
|
|
161
|
-
alignItems: "center",
|
|
162
|
-
justifyContent: "center",
|
|
163
|
-
flexDirection: "row",
|
|
164
|
-
gap: space2.xs
|
|
165
|
-
}),
|
|
166
|
-
children: [
|
|
167
|
-
props.busy ? /* @__PURE__ */ jsx(ActivityIndicator, { color: foreground }) : null,
|
|
168
|
-
props.children ?? /* @__PURE__ */ jsx(
|
|
169
|
-
Text,
|
|
170
|
-
{
|
|
171
|
-
style: {
|
|
172
|
-
color: foreground,
|
|
173
|
-
fontSize: font2.size.md,
|
|
174
|
-
fontWeight: "500",
|
|
175
|
-
...font2.family ? { fontFamily: font2.family } : {}
|
|
176
|
-
},
|
|
177
|
-
children: props.label
|
|
178
|
-
}
|
|
179
|
-
)
|
|
180
|
-
]
|
|
181
|
-
}
|
|
182
|
-
);
|
|
183
|
-
});
|
|
184
195
|
function InfoCard(props) {
|
|
185
196
|
const card = cardOf(props.card);
|
|
186
197
|
const { locale, t } = useCopy();
|
|
@@ -189,7 +200,7 @@ function InfoCard(props) {
|
|
|
189
200
|
const image = safeImage(card.image_url);
|
|
190
201
|
const Img = slots.Image ?? Image;
|
|
191
202
|
const money = card.price ?? card.price_from;
|
|
192
|
-
const rating = card.rating ? (card.rating.value_ppm
|
|
203
|
+
const rating = card.rating ? ratingText(card.rating.value_ppm, locale) : null;
|
|
193
204
|
const amount = money ? formatMoney(money.amount, money.currency, locale) : null;
|
|
194
205
|
const price = amount && !card.price ? t("priceFrom", { price: amount }) : amount;
|
|
195
206
|
const when = card.starts_at ? formatTimeRange(card.starts_at, void 0, locale, timeZone) : null;
|
|
@@ -232,27 +243,32 @@ function InfoCard(props) {
|
|
|
232
243
|
] })
|
|
233
244
|
] }),
|
|
234
245
|
card.body ? /* @__PURE__ */ jsx(Body, { children: card.body }) : null,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
{
|
|
238
|
-
style: {
|
|
239
|
-
color: colors2.text,
|
|
240
|
-
backgroundColor: colors2.surface,
|
|
241
|
-
borderRadius: radius2.pill,
|
|
242
|
-
paddingHorizontal: space2.sm,
|
|
243
|
-
paddingVertical: space2.xxs,
|
|
244
|
-
fontSize: font2.size.xs
|
|
245
|
-
},
|
|
246
|
-
children: b
|
|
247
|
-
},
|
|
248
|
-
b
|
|
249
|
-
)) }) : null,
|
|
250
|
-
props.restored ? null : /* @__PURE__ */ jsx(Actions, { ...props })
|
|
246
|
+
/* @__PURE__ */ jsx(Badges, { badges: card.badges }),
|
|
247
|
+
props.restored ? null : /* @__PURE__ */ jsx(CardActions, { ...props })
|
|
251
248
|
]
|
|
252
249
|
}
|
|
253
250
|
);
|
|
254
251
|
}
|
|
255
|
-
function
|
|
252
|
+
function Badges(props) {
|
|
253
|
+
const { colors: colors2, radius: radius2, space: space2, font: font2 } = useTheme();
|
|
254
|
+
if (!props.badges?.length) return null;
|
|
255
|
+
return /* @__PURE__ */ jsx(View, { style: { flexDirection: "row", flexWrap: "wrap", gap: space2.xs }, children: props.badges.map((b) => /* @__PURE__ */ jsx(
|
|
256
|
+
Text,
|
|
257
|
+
{
|
|
258
|
+
style: {
|
|
259
|
+
color: colors2.text,
|
|
260
|
+
backgroundColor: colors2.surface,
|
|
261
|
+
borderRadius: radius2.pill,
|
|
262
|
+
paddingHorizontal: space2.sm,
|
|
263
|
+
paddingVertical: space2.xxs,
|
|
264
|
+
fontSize: font2.size.xs
|
|
265
|
+
},
|
|
266
|
+
children: b
|
|
267
|
+
},
|
|
268
|
+
b
|
|
269
|
+
)) });
|
|
270
|
+
}
|
|
271
|
+
function CardActions(props) {
|
|
256
272
|
const card = cardOf(props.card);
|
|
257
273
|
const { space: space2 } = useTheme();
|
|
258
274
|
if (!card.actions?.length) return null;
|
|
@@ -284,6 +300,120 @@ function Action(props) {
|
|
|
284
300
|
}
|
|
285
301
|
);
|
|
286
302
|
}
|
|
303
|
+
function LinksCard(props) {
|
|
304
|
+
const card = cardOf(props.card);
|
|
305
|
+
const { store, handlers } = useChat();
|
|
306
|
+
const links = (card.links ?? []).filter(
|
|
307
|
+
(l) => /^https:\/\//i.test(l.url) || store.checkLink(l.url)
|
|
308
|
+
);
|
|
309
|
+
return /* @__PURE__ */ jsxs(
|
|
310
|
+
CardFrame,
|
|
311
|
+
{
|
|
312
|
+
label: [card.title, ...links.map((l) => l.label)].join(", "),
|
|
313
|
+
restored: props.restored,
|
|
314
|
+
testID: `vinaverse-card-${card.id}`,
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ jsx(Title, { children: card.title }),
|
|
317
|
+
links.map((l) => /* @__PURE__ */ jsx(
|
|
318
|
+
Button,
|
|
319
|
+
{
|
|
320
|
+
label: l.label,
|
|
321
|
+
role: "link",
|
|
322
|
+
variant: "secondary",
|
|
323
|
+
disabled: props.restored,
|
|
324
|
+
onPress: () => {
|
|
325
|
+
const open = handlers.current?.onOpenLink;
|
|
326
|
+
if (open) open(l.url, props.card);
|
|
327
|
+
else void Linking.openURL(l.url);
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
l.url
|
|
331
|
+
))
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
function ListingCard(props) {
|
|
337
|
+
const card = cardOf(props.card);
|
|
338
|
+
const { locale, t } = useCopy();
|
|
339
|
+
const { slots, timeZone } = useChat();
|
|
340
|
+
const { colors: colors2, radius: radius2, space: space2, font: font2 } = useTheme();
|
|
341
|
+
const [failed, setFailed] = useState(null);
|
|
342
|
+
const photoUrl = safeImage(card.images?.[0]?.url ?? card.image_url);
|
|
343
|
+
const hero = photoUrl === failed ? null : photoUrl;
|
|
344
|
+
const Img = slots.Image ?? Image;
|
|
345
|
+
const rating = card.rating ? `\u2605 ${ratingText(card.rating.value_ppm, locale)} (${card.rating.count})` : null;
|
|
346
|
+
const price = card.price_from ? t("priceFrom", {
|
|
347
|
+
price: formatMoney(
|
|
348
|
+
card.price_from.amount,
|
|
349
|
+
card.price_from.currency,
|
|
350
|
+
locale
|
|
351
|
+
)
|
|
352
|
+
}) : null;
|
|
353
|
+
const next = card.next_available ? t("nextAvailable", {
|
|
354
|
+
time: formatTimeRange(card.next_available, void 0, locale, timeZone)
|
|
355
|
+
}) : null;
|
|
356
|
+
const photo = {
|
|
357
|
+
width: "100%",
|
|
358
|
+
aspectRatio: 1.6,
|
|
359
|
+
borderRadius: radius2.md
|
|
360
|
+
};
|
|
361
|
+
return /* @__PURE__ */ jsxs(
|
|
362
|
+
CardFrame,
|
|
363
|
+
{
|
|
364
|
+
label: [card.title, card.subtitle, rating, price, next].filter(Boolean).join(", "),
|
|
365
|
+
restored: props.restored,
|
|
366
|
+
testID: `vinaverse-card-${card.id}`,
|
|
367
|
+
children: [
|
|
368
|
+
hero ? /* @__PURE__ */ jsx(
|
|
369
|
+
Img,
|
|
370
|
+
{
|
|
371
|
+
source: { uri: hero },
|
|
372
|
+
onError: () => setFailed(hero),
|
|
373
|
+
style: { ...photo, backgroundColor: colors2.surface },
|
|
374
|
+
accessible: false,
|
|
375
|
+
testID: `vinaverse-photo-${card.id}`
|
|
376
|
+
}
|
|
377
|
+
) : /* @__PURE__ */ jsx(
|
|
378
|
+
View,
|
|
379
|
+
{
|
|
380
|
+
accessible: false,
|
|
381
|
+
importantForAccessibility: "no-hide-descendants",
|
|
382
|
+
testID: `vinaverse-monogram-${card.id}`,
|
|
383
|
+
style: {
|
|
384
|
+
...photo,
|
|
385
|
+
backgroundColor: colors2.surface,
|
|
386
|
+
alignItems: "center",
|
|
387
|
+
justifyContent: "center"
|
|
388
|
+
},
|
|
389
|
+
children: /* @__PURE__ */ jsx(
|
|
390
|
+
Text,
|
|
391
|
+
{
|
|
392
|
+
style: {
|
|
393
|
+
color: colors2.textMuted,
|
|
394
|
+
fontSize: font2.size.xl,
|
|
395
|
+
fontWeight: "600"
|
|
396
|
+
},
|
|
397
|
+
children: monogram(card.title)
|
|
398
|
+
}
|
|
399
|
+
)
|
|
400
|
+
}
|
|
401
|
+
),
|
|
402
|
+
/* @__PURE__ */ jsxs(View, { style: { gap: space2.xxs }, children: [
|
|
403
|
+
/* @__PURE__ */ jsx(Title, { numberOfLines: 2, children: card.title }),
|
|
404
|
+
card.subtitle ? /* @__PURE__ */ jsx(Body, { muted: true, children: card.subtitle }) : null,
|
|
405
|
+
rating || price ? /* @__PURE__ */ jsx(Body, { muted: true, children: [rating, price].filter(Boolean).join(" \xB7 ") }) : null
|
|
406
|
+
] }),
|
|
407
|
+
card.body ? /* @__PURE__ */ jsx(Body, { children: card.body }) : null,
|
|
408
|
+
/* @__PURE__ */ jsx(Badges, { badges: next ? [next, ...card.badges ?? []] : card.badges }),
|
|
409
|
+
props.restored ? null : /* @__PURE__ */ jsx(CardActions, { ...props })
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function monogram(title) {
|
|
415
|
+
return title.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => [...w][0]?.toUpperCase() ?? "").join("");
|
|
416
|
+
}
|
|
287
417
|
function NextStepCard(props) {
|
|
288
418
|
const card = cardOf(props.card);
|
|
289
419
|
const action = card.actions?.[0];
|
|
@@ -1152,7 +1282,10 @@ var DEFAULTS = {
|
|
|
1152
1282
|
proposal: ProposalCard,
|
|
1153
1283
|
question: QuestionCard,
|
|
1154
1284
|
next_step: NextStepCard,
|
|
1155
|
-
time_slots: TimeSlotsCard
|
|
1285
|
+
time_slots: TimeSlotsCard,
|
|
1286
|
+
professional: ListingCard,
|
|
1287
|
+
workspace: ListingCard,
|
|
1288
|
+
links: LinksCard
|
|
1156
1289
|
};
|
|
1157
1290
|
function defaultCard(kind) {
|
|
1158
1291
|
return DEFAULTS[kind] ?? InfoCard;
|
|
@@ -1165,6 +1298,35 @@ var CardView = memo(function CardView2(props) {
|
|
|
1165
1298
|
const own = { card, busy, restored: props.item.restored === true };
|
|
1166
1299
|
return Custom ? /* @__PURE__ */ jsx(Custom, { ...own, Default }) : /* @__PURE__ */ jsx(Default, { ...own });
|
|
1167
1300
|
});
|
|
1301
|
+
var keyOf = (item) => item.key;
|
|
1302
|
+
var kindOf = (item) => item.card.kind;
|
|
1303
|
+
function CardCarousel(props) {
|
|
1304
|
+
const { width } = useWindowDimensions();
|
|
1305
|
+
const { t } = useCopy();
|
|
1306
|
+
const size3 = Math.min(Math.round(width * 0.8), 360);
|
|
1307
|
+
return /* @__PURE__ */ jsx(
|
|
1308
|
+
View,
|
|
1309
|
+
{
|
|
1310
|
+
accessibilityRole: "list",
|
|
1311
|
+
accessibilityLabel: t("cardsInRow", {
|
|
1312
|
+
count: String(props.items.length)
|
|
1313
|
+
}),
|
|
1314
|
+
children: /* @__PURE__ */ jsx(
|
|
1315
|
+
FlashList,
|
|
1316
|
+
{
|
|
1317
|
+
horizontal: true,
|
|
1318
|
+
data: props.items,
|
|
1319
|
+
keyExtractor: keyOf,
|
|
1320
|
+
getItemType: kindOf,
|
|
1321
|
+
renderItem: ({ item }) => /* @__PURE__ */ jsx(View, { style: { width: size3 }, children: /* @__PURE__ */ jsx(CardView, { item }) }),
|
|
1322
|
+
snapToInterval: size3,
|
|
1323
|
+
decelerationRate: "fast",
|
|
1324
|
+
showsHorizontalScrollIndicator: false
|
|
1325
|
+
}
|
|
1326
|
+
)
|
|
1327
|
+
}
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1168
1330
|
var ActivityLine = memo(function ActivityLine2() {
|
|
1169
1331
|
const { store } = useChat();
|
|
1170
1332
|
const { t } = useCopy();
|
|
@@ -1722,7 +1884,44 @@ function Line(props) {
|
|
|
1722
1884
|
}
|
|
1723
1885
|
);
|
|
1724
1886
|
}
|
|
1725
|
-
var
|
|
1887
|
+
var Welcome = memo(function Welcome2(props) {
|
|
1888
|
+
const { colors: colors2, radius: radius2, space: space2, font: font2 } = useTheme();
|
|
1889
|
+
return /* @__PURE__ */ jsxs(
|
|
1890
|
+
View,
|
|
1891
|
+
{
|
|
1892
|
+
style: { padding: space2.lg, gap: space2.md },
|
|
1893
|
+
testID: "vinaverse-welcome",
|
|
1894
|
+
children: [
|
|
1895
|
+
/* @__PURE__ */ jsx(
|
|
1896
|
+
Text,
|
|
1897
|
+
{
|
|
1898
|
+
style: {
|
|
1899
|
+
alignSelf: "flex-start",
|
|
1900
|
+
maxWidth: "85%",
|
|
1901
|
+
color: colors2.agentText,
|
|
1902
|
+
backgroundColor: colors2.agentBubble,
|
|
1903
|
+
borderRadius: radius2.lg,
|
|
1904
|
+
paddingHorizontal: space2.md,
|
|
1905
|
+
paddingVertical: space2.sm,
|
|
1906
|
+
fontSize: font2.size.md,
|
|
1907
|
+
lineHeight: font2.size.md * font2.lineHeight
|
|
1908
|
+
},
|
|
1909
|
+
children: props.welcome.text
|
|
1910
|
+
}
|
|
1911
|
+
),
|
|
1912
|
+
props.welcome.chips.length ? /* @__PURE__ */ jsx(View, { style: { flexDirection: "row", flexWrap: "wrap", gap: space2.sm }, children: props.welcome.chips.map((chip) => /* @__PURE__ */ jsx(
|
|
1913
|
+
Button,
|
|
1914
|
+
{
|
|
1915
|
+
label: chip.label,
|
|
1916
|
+
onPress: () => props.onChip(chip.message)
|
|
1917
|
+
},
|
|
1918
|
+
chip.label
|
|
1919
|
+
)) }) : null
|
|
1920
|
+
]
|
|
1921
|
+
}
|
|
1922
|
+
);
|
|
1923
|
+
});
|
|
1924
|
+
var keyOf2 = (item) => item.key;
|
|
1726
1925
|
function itemType(item) {
|
|
1727
1926
|
if (item.type === "card") return `card:${item.card.kind}`;
|
|
1728
1927
|
if (item.type === "message")
|
|
@@ -1732,8 +1931,39 @@ function itemType(item) {
|
|
|
1732
1931
|
function authorOf(item) {
|
|
1733
1932
|
return item?.type === "message" ? item.role : null;
|
|
1734
1933
|
}
|
|
1934
|
+
function carousels(items, previous) {
|
|
1935
|
+
const runs = /* @__PURE__ */ new Map();
|
|
1936
|
+
const inside = /* @__PURE__ */ new Set();
|
|
1937
|
+
const groupOf = (item) => {
|
|
1938
|
+
if (item?.type !== "card") return null;
|
|
1939
|
+
const group = item.card.card.group;
|
|
1940
|
+
return group?.layout === "carousel" && typeof group.id === "string" ? group.id : null;
|
|
1941
|
+
};
|
|
1942
|
+
for (let i = 0; i < items.length; i++) {
|
|
1943
|
+
const id = groupOf(items[i]);
|
|
1944
|
+
if (id === null) continue;
|
|
1945
|
+
let end = i + 1;
|
|
1946
|
+
while (end < items.length && groupOf(items[end]) === id) end++;
|
|
1947
|
+
if (end - i > 1) {
|
|
1948
|
+
const run = items.slice(i, end);
|
|
1949
|
+
const key = run[0]?.key;
|
|
1950
|
+
const before = previous.get(key);
|
|
1951
|
+
runs.set(
|
|
1952
|
+
key,
|
|
1953
|
+
before && before.length === run.length && before.every((c, n) => c === run[n]) ? before : run
|
|
1954
|
+
);
|
|
1955
|
+
for (const card of run.slice(1)) inside.add(card.key);
|
|
1956
|
+
}
|
|
1957
|
+
i = end - 1;
|
|
1958
|
+
}
|
|
1959
|
+
return { runs, inside };
|
|
1960
|
+
}
|
|
1735
1961
|
var Row = memo(function Row2(props) {
|
|
1736
1962
|
const { item } = props;
|
|
1963
|
+
const { slots } = useChat();
|
|
1964
|
+
const Group = slots.CardGroup;
|
|
1965
|
+
if (props.inside) return null;
|
|
1966
|
+
if (props.run && Group) return /* @__PURE__ */ jsx(Group, { items: props.run });
|
|
1737
1967
|
if (item.type === "card") return /* @__PURE__ */ jsx(CardView, { item });
|
|
1738
1968
|
if (item.type === "system") return /* @__PURE__ */ jsx(SystemRow, { item });
|
|
1739
1969
|
return item.state === "streaming" ? /* @__PURE__ */ jsx(StreamingBubble, { item, showAuthor: props.showAuthor }) : /* @__PURE__ */ jsx(MessageBubble, { item, showAuthor: props.showAuthor });
|
|
@@ -1749,26 +1979,49 @@ var MessageList = memo(function MessageList2() {
|
|
|
1749
1979
|
(v) => v.status === "starting" || v.status === "connecting"
|
|
1750
1980
|
);
|
|
1751
1981
|
const agentName = useConversationSelector(store, (v) => v.agent.name);
|
|
1982
|
+
const welcome = useConversationSelector(store, (v) => v.welcome);
|
|
1752
1983
|
useAnnounceReplies(items);
|
|
1984
|
+
const Group = slots.CardGroup;
|
|
1985
|
+
const runsRef = useRef(/* @__PURE__ */ new Map());
|
|
1986
|
+
const grouping = useMemo(
|
|
1987
|
+
() => Group ? carousels(items, runsRef.current) : null,
|
|
1988
|
+
[items, Group]
|
|
1989
|
+
);
|
|
1990
|
+
runsRef.current = grouping?.runs ?? /* @__PURE__ */ new Map();
|
|
1753
1991
|
const itemsRef = useRef(items);
|
|
1754
1992
|
itemsRef.current = items;
|
|
1993
|
+
const groupingRef = useRef(grouping);
|
|
1994
|
+
groupingRef.current = grouping;
|
|
1755
1995
|
const renderItem = useCallback(
|
|
1756
1996
|
({ item, index }) => /* @__PURE__ */ jsx(
|
|
1757
1997
|
Row,
|
|
1758
1998
|
{
|
|
1759
1999
|
item,
|
|
1760
|
-
showAuthor: authorOf(item) !== authorOf(itemsRef.current[index - 1])
|
|
2000
|
+
showAuthor: authorOf(item) !== authorOf(itemsRef.current[index - 1]),
|
|
2001
|
+
run: groupingRef.current?.runs.get(item.key),
|
|
2002
|
+
inside: groupingRef.current?.inside.has(item.key) === true
|
|
1761
2003
|
}
|
|
1762
2004
|
),
|
|
1763
2005
|
[]
|
|
1764
2006
|
);
|
|
2007
|
+
const onChip = useCallback(
|
|
2008
|
+
(message) => void store.send(message),
|
|
2009
|
+
[store]
|
|
2010
|
+
);
|
|
1765
2011
|
const Empty = slots.EmptyState;
|
|
1766
|
-
const empty = opening ? /* @__PURE__ */ jsx(ChatSkeleton, {}) : Empty ? /* @__PURE__ */ jsx(
|
|
2012
|
+
const empty = opening ? /* @__PURE__ */ jsx(ChatSkeleton, {}) : Empty ? /* @__PURE__ */ jsx(
|
|
2013
|
+
Empty,
|
|
2014
|
+
{
|
|
2015
|
+
agentName: agentName ?? t("agentFallbackName"),
|
|
2016
|
+
welcome,
|
|
2017
|
+
onChip
|
|
2018
|
+
}
|
|
2019
|
+
) : welcome ? /* @__PURE__ */ jsx(Welcome, { welcome, onChip }) : null;
|
|
1767
2020
|
const props = useMemo(
|
|
1768
2021
|
() => ({
|
|
1769
2022
|
data: items,
|
|
1770
2023
|
renderItem,
|
|
1771
|
-
keyExtractor:
|
|
2024
|
+
keyExtractor: keyOf2,
|
|
1772
2025
|
getItemType: itemType,
|
|
1773
2026
|
maintainVisibleContentPosition: {
|
|
1774
2027
|
startRenderingFromBottom: true,
|
|
@@ -1998,6 +2251,6 @@ function sameSlots(a, b) {
|
|
|
1998
2251
|
return true;
|
|
1999
2252
|
}
|
|
2000
2253
|
|
|
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 };
|
|
2254
|
+
export { ActivityLine, Avatar, Button, CardActions, CardCarousel, CardFrame, CardView, ChatHeader, ChatSkeleton, Composer, DefaultBubble, DefaultComposer, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DisclosureBar, FailureActionButton, InfoCard, LinksCard, ListingCard, MessageBubble, MessageList, NextStepCard, ProposalCard, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeProvider, TimeSlotsCard, VinaverseChat, VinaverseChatProvider, Welcome, announce, answerText, carousels, createTheme, defaultCard, fieldText, itemType, monogram, ratingText, themeProblems, useChat, useNativeLifecycle, useReducedMotion, useTheme };
|
|
2002
2255
|
//# sourceMappingURL=index.js.map
|
|
2003
2256
|
//# sourceMappingURL=index.js.map
|