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

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 CHANGED
@@ -97,10 +97,10 @@ const imagePolicy = { hosts: ['images.example.com'], aspectRatio: 1.6, Placehold
97
97
  from. Every agent part asks the runtime to `sweep()` when the app comes back to the foreground. `AskAboutRow` is "ask the agent about this" on
98
98
  your own pages, decided once as the page draws, from the status already read: it is never added under a drawn page
99
99
  (an agent whose status arrives later shows from the next visit), and `appearance` gives it a tint (`background`) and the
100
- `chevron` or none.
101
- - **Policies and adapters:** `imagePolicy` (photo hosts, frame, the stand-in for a missing photo) applies to every card
100
+ `chevron` or none, and `testID` its test id.
101
+ - **Policies and adapters:** `imagePolicy` (photo hosts, frame, the stand-in for a missing photo, given the card's `title` and `kind`) applies to every card
102
102
  and every fetch ahead; `announce` reads finished replies and the greeting your way; `onChip` hears a tapped chip.
103
- Card renderers get the card read once (`read`).
103
+ Card renderers get the card read once (`read`). A listing with no rating draws `copy.ratingNone` in the rating's place (empty by default; "New", say).
104
104
  - **Hooks** for your own parts: `useAgentConversation`, `useAgentStatus`, `useAgentFeatures`, `useAgentProfile`,
105
105
  `useAgentName`, `useAgentLauncher`, `useAgentRuntime`.
106
106
  - **Events** for analytics through `onEvent`: sessions, ratings, chips, targets and links opened, the launcher shown,
@@ -168,9 +168,20 @@ What is lost without it: a screen that imports `/chat` statically, or anything t
168
168
  (about 13 kB of the kit, its cards and list) when that screen's module first runs; with inline requires, when it is
169
169
  first used. Nothing breaks either way, and the bundle is the same on iOS and Android.
170
170
 
171
- Metro resolves an ES `import` to the package's ES module build and a `require` to its CommonJS build: import the kit
172
- with `import` statements throughout (never a `require` beside them), so every part comes from one build. With tree
173
- shaking (Expo's production tree shaking, webpack, Rollup, esbuild) either way of importing costs the same.
171
+ **One build under Metro.** Every `@vinaverse/*` entry lists the `react-native` condition first, which React Native's
172
+ and Expo's Metro configs set for iOS and Android: Metro takes the CommonJS build for an `import`, a `require`, and a
173
+ `require` Babel writes for you (an `export const X = ImportedBinding` becomes a getter that requires), so an app holds
174
+ one copy of the kit and one of each React context. Before 0.1.0-alpha.8 an ES import and a require resolved to
175
+ different builds, and a card drawn from the second found no chat around it; a `metro.config.js` that forces the `import`
176
+ condition for `@vinaverse/*` is no longer needed (harmless if kept). Jest with jest-expo resolves the same CommonJS
177
+ build, untransformed. Web bundlers (no `react-native` condition) take the ES module build for an import: import the kit
178
+ with `import` statements there.
179
+
180
+ **Size on iOS and Android comes from the per-part entries, not tree shaking.** Metro takes the CommonJS build there,
181
+ which no tree shaking (Expo's production tree shaking included) can trim: a screen ships and runs every module of the
182
+ entry it imports. So import by part (`/launcher`, `/ask`, `/chat`) to keep the kit's start-up work to the parts a
183
+ screen draws. Tree shaking (webpack, Rollup, esbuild, Expo on the web) applies on the web only, where an import takes
184
+ the ES module build.
174
185
 
175
186
  ## Peer dependencies
176
187
 
@@ -217,7 +228,7 @@ shaking (Expo's production tree shaking, webpack, Rollup, esbuild) either way of
217
228
  | `onCardAction(card, action)` | a card action without a link (also sent to the session) |
218
229
  | `onPickPhoto(question, card)` | a photo question: pick, upload to your backend, return `{ upload_ref }` |
219
230
  | `failureAction` | `{ label?, onPress(state) }`: a way out on a failed turn and on "couldn't connect" ([When the agent fails](#when-the-agent-fails)) |
220
- | `onWarning(message)` | development warnings: a hard-to-read theme, copy that says "assistant" |
231
+ | `onWarning(message, { code })` | warnings for your logger, `code` one of `theme` (hard to read), `copy` (says "assistant"), `send_failed`, `answer_failed`, `proposal_failed`, `photo_failed`, so you count them without the text |
221
232
 
222
233
  ## When the agent fails
223
234
 
package/dist/ask.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkV6HHPE5K_cjs = require('./chunk-V6HHPE5K.cjs');
3
+ var chunkNMKJ7LIJ_cjs = require('./chunk-NMKJ7LIJ.cjs');
4
4
  var chunk6QYDPGRS_cjs = require('./chunk-6QYDPGRS.cjs');
5
5
  var agent = require('@vinaverse/react/agent');
6
6
 
@@ -8,7 +8,7 @@ var agent = require('@vinaverse/react/agent');
8
8
 
9
9
  Object.defineProperty(exports, "AskAboutRow", {
10
10
  enumerable: true,
11
- get: function () { return chunkV6HHPE5K_cjs.AskAboutRow; }
11
+ get: function () { return chunkNMKJ7LIJ_cjs.AskAboutRow; }
12
12
  });
13
13
  Object.defineProperty(exports, "ThemeProvider", {
14
14
  enumerable: true,
package/dist/ask.d.cts CHANGED
@@ -30,6 +30,8 @@ interface AskAboutRowProps {
30
30
  readonly copy?: CopyOverrides;
31
31
  readonly theme?: ThemeOverrides;
32
32
  readonly colorScheme?: ColorSchemeSetting;
33
+ /** The row's test id. Default `vinaverse-ask-about`. */
34
+ readonly testID?: string;
33
35
  }
34
36
  declare function AskAboutRow(props: AskAboutRowProps): ReactNode;
35
37
 
package/dist/ask.d.ts CHANGED
@@ -30,6 +30,8 @@ interface AskAboutRowProps {
30
30
  readonly copy?: CopyOverrides;
31
31
  readonly theme?: ThemeOverrides;
32
32
  readonly colorScheme?: ColorSchemeSetting;
33
+ /** The row's test id. Default `vinaverse-ask-about`. */
34
+ readonly testID?: string;
33
35
  }
34
36
  declare function AskAboutRow(props: AskAboutRowProps): ReactNode;
35
37
 
package/dist/ask.js CHANGED
@@ -1,4 +1,4 @@
1
- export { AskAboutRow } from './chunk-NJ6ARGZS.js';
1
+ export { AskAboutRow } from './chunk-7KPCO443.js';
2
2
  export { ThemeProvider, useTheme } from './chunk-EFEXTVIT.js';
3
3
  export { AgentRuntimeProvider, forgetGreeting, greetedKey, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus } from '@vinaverse/react/agent';
4
4
  //# sourceMappingURL=ask.js.map
package/dist/chat.cjs CHANGED
@@ -1,241 +1,241 @@
1
1
  'use strict';
2
2
 
3
- var chunkAGZ7IH7E_cjs = require('./chunk-AGZ7IH7E.cjs');
3
+ var chunkEXN5TNLU_cjs = require('./chunk-EXN5TNLU.cjs');
4
4
  var chunk6QYDPGRS_cjs = require('./chunk-6QYDPGRS.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "ActivityLine", {
9
9
  enumerable: true,
10
- get: function () { return chunkAGZ7IH7E_cjs.ActivityLine; }
10
+ get: function () { return chunkEXN5TNLU_cjs.ActivityLine; }
11
11
  });
12
12
  Object.defineProperty(exports, "AgentChat", {
13
13
  enumerable: true,
14
- get: function () { return chunkAGZ7IH7E_cjs.AgentChat; }
14
+ get: function () { return chunkEXN5TNLU_cjs.AgentChat; }
15
15
  });
16
16
  Object.defineProperty(exports, "AgentFooter", {
17
17
  enumerable: true,
18
- get: function () { return chunkAGZ7IH7E_cjs.AgentFooter; }
18
+ get: function () { return chunkEXN5TNLU_cjs.AgentFooter; }
19
19
  });
20
20
  Object.defineProperty(exports, "AgentRuntimeProvider", {
21
21
  enumerable: true,
22
- get: function () { return chunkAGZ7IH7E_cjs.AgentRuntimeProvider; }
22
+ get: function () { return chunkEXN5TNLU_cjs.AgentRuntimeProvider; }
23
23
  });
24
24
  Object.defineProperty(exports, "Avatar", {
25
25
  enumerable: true,
26
- get: function () { return chunkAGZ7IH7E_cjs.Avatar; }
26
+ get: function () { return chunkEXN5TNLU_cjs.Avatar; }
27
27
  });
28
28
  Object.defineProperty(exports, "Button", {
29
29
  enumerable: true,
30
- get: function () { return chunkAGZ7IH7E_cjs.Button; }
30
+ get: function () { return chunkEXN5TNLU_cjs.Button; }
31
31
  });
32
32
  Object.defineProperty(exports, "CardActions", {
33
33
  enumerable: true,
34
- get: function () { return chunkAGZ7IH7E_cjs.CardActions; }
34
+ get: function () { return chunkEXN5TNLU_cjs.CardActions; }
35
35
  });
36
36
  Object.defineProperty(exports, "CardCarousel", {
37
37
  enumerable: true,
38
- get: function () { return chunkAGZ7IH7E_cjs.CardCarousel; }
38
+ get: function () { return chunkEXN5TNLU_cjs.CardCarousel; }
39
39
  });
40
40
  Object.defineProperty(exports, "CardFrame", {
41
41
  enumerable: true,
42
- get: function () { return chunkAGZ7IH7E_cjs.CardFrame; }
42
+ get: function () { return chunkEXN5TNLU_cjs.CardFrame; }
43
43
  });
44
44
  Object.defineProperty(exports, "CardView", {
45
45
  enumerable: true,
46
- get: function () { return chunkAGZ7IH7E_cjs.CardView; }
46
+ get: function () { return chunkEXN5TNLU_cjs.CardView; }
47
47
  });
48
48
  Object.defineProperty(exports, "ChatHeader", {
49
49
  enumerable: true,
50
- get: function () { return chunkAGZ7IH7E_cjs.ChatHeader; }
50
+ get: function () { return chunkEXN5TNLU_cjs.ChatHeader; }
51
51
  });
52
52
  Object.defineProperty(exports, "ChatSkeleton", {
53
53
  enumerable: true,
54
- get: function () { return chunkAGZ7IH7E_cjs.ChatSkeleton; }
54
+ get: function () { return chunkEXN5TNLU_cjs.ChatSkeleton; }
55
55
  });
56
56
  Object.defineProperty(exports, "Composer", {
57
57
  enumerable: true,
58
- get: function () { return chunkAGZ7IH7E_cjs.Composer; }
58
+ get: function () { return chunkEXN5TNLU_cjs.Composer; }
59
59
  });
60
60
  Object.defineProperty(exports, "DefaultBubble", {
61
61
  enumerable: true,
62
- get: function () { return chunkAGZ7IH7E_cjs.DefaultBubble; }
62
+ get: function () { return chunkEXN5TNLU_cjs.DefaultBubble; }
63
63
  });
64
64
  Object.defineProperty(exports, "DefaultComposer", {
65
65
  enumerable: true,
66
- get: function () { return chunkAGZ7IH7E_cjs.DefaultComposer; }
66
+ get: function () { return chunkEXN5TNLU_cjs.DefaultComposer; }
67
67
  });
68
68
  Object.defineProperty(exports, "DefaultEnded", {
69
69
  enumerable: true,
70
- get: function () { return chunkAGZ7IH7E_cjs.DefaultEnded; }
70
+ get: function () { return chunkEXN5TNLU_cjs.DefaultEnded; }
71
71
  });
72
72
  Object.defineProperty(exports, "DefaultHeader", {
73
73
  enumerable: true,
74
- get: function () { return chunkAGZ7IH7E_cjs.DefaultHeader; }
74
+ get: function () { return chunkEXN5TNLU_cjs.DefaultHeader; }
75
75
  });
76
76
  Object.defineProperty(exports, "DefaultTurnFailed", {
77
77
  enumerable: true,
78
- get: function () { return chunkAGZ7IH7E_cjs.DefaultTurnFailed; }
78
+ get: function () { return chunkEXN5TNLU_cjs.DefaultTurnFailed; }
79
79
  });
80
80
  Object.defineProperty(exports, "DefaultUnavailable", {
81
81
  enumerable: true,
82
- get: function () { return chunkAGZ7IH7E_cjs.DefaultUnavailable; }
82
+ get: function () { return chunkEXN5TNLU_cjs.DefaultUnavailable; }
83
83
  });
84
84
  Object.defineProperty(exports, "DefaultUnavailableScreen", {
85
85
  enumerable: true,
86
- get: function () { return chunkAGZ7IH7E_cjs.DefaultUnavailableScreen; }
86
+ get: function () { return chunkEXN5TNLU_cjs.DefaultUnavailableScreen; }
87
87
  });
88
88
  Object.defineProperty(exports, "DefaultUnreachable", {
89
89
  enumerable: true,
90
- get: function () { return chunkAGZ7IH7E_cjs.DefaultUnreachable; }
90
+ get: function () { return chunkEXN5TNLU_cjs.DefaultUnreachable; }
91
91
  });
92
92
  Object.defineProperty(exports, "DisclosureBar", {
93
93
  enumerable: true,
94
- get: function () { return chunkAGZ7IH7E_cjs.DisclosureBar; }
94
+ get: function () { return chunkEXN5TNLU_cjs.DisclosureBar; }
95
95
  });
96
96
  Object.defineProperty(exports, "FailureActionButton", {
97
97
  enumerable: true,
98
- get: function () { return chunkAGZ7IH7E_cjs.FailureActionButton; }
98
+ get: function () { return chunkEXN5TNLU_cjs.FailureActionButton; }
99
99
  });
100
100
  Object.defineProperty(exports, "InfoCard", {
101
101
  enumerable: true,
102
- get: function () { return chunkAGZ7IH7E_cjs.InfoCard; }
102
+ get: function () { return chunkEXN5TNLU_cjs.InfoCard; }
103
103
  });
104
104
  Object.defineProperty(exports, "LinksCard", {
105
105
  enumerable: true,
106
- get: function () { return chunkAGZ7IH7E_cjs.LinksCard; }
106
+ get: function () { return chunkEXN5TNLU_cjs.LinksCard; }
107
107
  });
108
108
  Object.defineProperty(exports, "ListingCard", {
109
109
  enumerable: true,
110
- get: function () { return chunkAGZ7IH7E_cjs.ListingCard; }
110
+ get: function () { return chunkEXN5TNLU_cjs.ListingCard; }
111
111
  });
112
112
  Object.defineProperty(exports, "MessageBubble", {
113
113
  enumerable: true,
114
- get: function () { return chunkAGZ7IH7E_cjs.MessageBubble; }
114
+ get: function () { return chunkEXN5TNLU_cjs.MessageBubble; }
115
115
  });
116
116
  Object.defineProperty(exports, "MessageList", {
117
117
  enumerable: true,
118
- get: function () { return chunkAGZ7IH7E_cjs.MessageList; }
118
+ get: function () { return chunkEXN5TNLU_cjs.MessageList; }
119
119
  });
120
120
  Object.defineProperty(exports, "NextStepCard", {
121
121
  enumerable: true,
122
- get: function () { return chunkAGZ7IH7E_cjs.NextStepCard; }
122
+ get: function () { return chunkEXN5TNLU_cjs.NextStepCard; }
123
123
  });
124
124
  Object.defineProperty(exports, "ProposalCard", {
125
125
  enumerable: true,
126
- get: function () { return chunkAGZ7IH7E_cjs.ProposalCard; }
126
+ get: function () { return chunkEXN5TNLU_cjs.ProposalCard; }
127
127
  });
128
128
  Object.defineProperty(exports, "QuestionCard", {
129
129
  enumerable: true,
130
- get: function () { return chunkAGZ7IH7E_cjs.QuestionCard; }
130
+ get: function () { return chunkEXN5TNLU_cjs.QuestionCard; }
131
131
  });
132
132
  Object.defineProperty(exports, "Row", {
133
133
  enumerable: true,
134
- get: function () { return chunkAGZ7IH7E_cjs.Row; }
134
+ get: function () { return chunkEXN5TNLU_cjs.Row; }
135
135
  });
136
136
  Object.defineProperty(exports, "StatusBanner", {
137
137
  enumerable: true,
138
- get: function () { return chunkAGZ7IH7E_cjs.StatusBanner; }
138
+ get: function () { return chunkEXN5TNLU_cjs.StatusBanner; }
139
139
  });
140
140
  Object.defineProperty(exports, "StreamingBubble", {
141
141
  enumerable: true,
142
- get: function () { return chunkAGZ7IH7E_cjs.StreamingBubble; }
142
+ get: function () { return chunkEXN5TNLU_cjs.StreamingBubble; }
143
143
  });
144
144
  Object.defineProperty(exports, "SystemRow", {
145
145
  enumerable: true,
146
- get: function () { return chunkAGZ7IH7E_cjs.SystemRow; }
146
+ get: function () { return chunkEXN5TNLU_cjs.SystemRow; }
147
147
  });
148
148
  Object.defineProperty(exports, "TimeSlotsCard", {
149
149
  enumerable: true,
150
- get: function () { return chunkAGZ7IH7E_cjs.TimeSlotsCard; }
150
+ get: function () { return chunkEXN5TNLU_cjs.TimeSlotsCard; }
151
151
  });
152
152
  Object.defineProperty(exports, "VinaverseChat", {
153
153
  enumerable: true,
154
- get: function () { return chunkAGZ7IH7E_cjs.VinaverseChat; }
154
+ get: function () { return chunkEXN5TNLU_cjs.VinaverseChat; }
155
155
  });
156
156
  Object.defineProperty(exports, "VinaverseChatProvider", {
157
157
  enumerable: true,
158
- get: function () { return chunkAGZ7IH7E_cjs.VinaverseChatProvider; }
158
+ get: function () { return chunkEXN5TNLU_cjs.VinaverseChatProvider; }
159
159
  });
160
160
  Object.defineProperty(exports, "Welcome", {
161
161
  enumerable: true,
162
- get: function () { return chunkAGZ7IH7E_cjs.Welcome; }
162
+ get: function () { return chunkEXN5TNLU_cjs.Welcome; }
163
163
  });
164
164
  Object.defineProperty(exports, "allowedImage", {
165
165
  enumerable: true,
166
- get: function () { return chunkAGZ7IH7E_cjs.allowedImage; }
166
+ get: function () { return chunkEXN5TNLU_cjs.allowedImage; }
167
167
  });
168
168
  Object.defineProperty(exports, "answerText", {
169
169
  enumerable: true,
170
- get: function () { return chunkAGZ7IH7E_cjs.answerText; }
170
+ get: function () { return chunkEXN5TNLU_cjs.answerText; }
171
171
  });
172
172
  Object.defineProperty(exports, "carousels", {
173
173
  enumerable: true,
174
- get: function () { return chunkAGZ7IH7E_cjs.carousels; }
174
+ get: function () { return chunkEXN5TNLU_cjs.carousels; }
175
175
  });
176
176
  Object.defineProperty(exports, "defaultCard", {
177
177
  enumerable: true,
178
- get: function () { return chunkAGZ7IH7E_cjs.defaultCard; }
178
+ get: function () { return chunkEXN5TNLU_cjs.defaultCard; }
179
179
  });
180
180
  Object.defineProperty(exports, "fieldText", {
181
181
  enumerable: true,
182
- get: function () { return chunkAGZ7IH7E_cjs.fieldText; }
182
+ get: function () { return chunkEXN5TNLU_cjs.fieldText; }
183
183
  });
184
184
  Object.defineProperty(exports, "forgetGreeting", {
185
185
  enumerable: true,
186
- get: function () { return chunkAGZ7IH7E_cjs.forgetGreeting; }
186
+ get: function () { return chunkEXN5TNLU_cjs.forgetGreeting; }
187
187
  });
188
188
  Object.defineProperty(exports, "greetedKey", {
189
189
  enumerable: true,
190
- get: function () { return chunkAGZ7IH7E_cjs.greetedKey; }
190
+ get: function () { return chunkEXN5TNLU_cjs.greetedKey; }
191
191
  });
192
192
  Object.defineProperty(exports, "itemType", {
193
193
  enumerable: true,
194
- get: function () { return chunkAGZ7IH7E_cjs.itemType; }
194
+ get: function () { return chunkEXN5TNLU_cjs.itemType; }
195
195
  });
196
196
  Object.defineProperty(exports, "monogram", {
197
197
  enumerable: true,
198
- get: function () { return chunkAGZ7IH7E_cjs.monogram; }
198
+ get: function () { return chunkEXN5TNLU_cjs.monogram; }
199
199
  });
200
200
  Object.defineProperty(exports, "newestWholeReply", {
201
201
  enumerable: true,
202
- get: function () { return chunkAGZ7IH7E_cjs.newestWholeReply; }
202
+ get: function () { return chunkEXN5TNLU_cjs.newestWholeReply; }
203
203
  });
204
204
  Object.defineProperty(exports, "ratingText", {
205
205
  enumerable: true,
206
- get: function () { return chunkAGZ7IH7E_cjs.ratingText; }
206
+ get: function () { return chunkEXN5TNLU_cjs.ratingText; }
207
207
  });
208
208
  Object.defineProperty(exports, "useAgentConversation", {
209
209
  enumerable: true,
210
- get: function () { return chunkAGZ7IH7E_cjs.useAgentConversation; }
210
+ get: function () { return chunkEXN5TNLU_cjs.useAgentConversation; }
211
211
  });
212
212
  Object.defineProperty(exports, "useAgentFeatures", {
213
213
  enumerable: true,
214
- get: function () { return chunkAGZ7IH7E_cjs.useAgentFeatures; }
214
+ get: function () { return chunkEXN5TNLU_cjs.useAgentFeatures; }
215
215
  });
216
216
  Object.defineProperty(exports, "useAgentLauncher", {
217
217
  enumerable: true,
218
- get: function () { return chunkAGZ7IH7E_cjs.useAgentLauncher; }
218
+ get: function () { return chunkEXN5TNLU_cjs.useAgentLauncher; }
219
219
  });
220
220
  Object.defineProperty(exports, "useAgentName", {
221
221
  enumerable: true,
222
- get: function () { return chunkAGZ7IH7E_cjs.useAgentName; }
222
+ get: function () { return chunkEXN5TNLU_cjs.useAgentName; }
223
223
  });
224
224
  Object.defineProperty(exports, "useAgentProfile", {
225
225
  enumerable: true,
226
- get: function () { return chunkAGZ7IH7E_cjs.useAgentProfile; }
226
+ get: function () { return chunkEXN5TNLU_cjs.useAgentProfile; }
227
227
  });
228
228
  Object.defineProperty(exports, "useAgentRuntime", {
229
229
  enumerable: true,
230
- get: function () { return chunkAGZ7IH7E_cjs.useAgentRuntime; }
230
+ get: function () { return chunkEXN5TNLU_cjs.useAgentRuntime; }
231
231
  });
232
232
  Object.defineProperty(exports, "useAgentStatus", {
233
233
  enumerable: true,
234
- get: function () { return chunkAGZ7IH7E_cjs.useAgentStatus; }
234
+ get: function () { return chunkEXN5TNLU_cjs.useAgentStatus; }
235
235
  });
236
236
  Object.defineProperty(exports, "useChat", {
237
237
  enumerable: true,
238
- get: function () { return chunkAGZ7IH7E_cjs.useChat; }
238
+ get: function () { return chunkEXN5TNLU_cjs.useChat; }
239
239
  });
240
240
  Object.defineProperty(exports, "ThemeProvider", {
241
241
  enumerable: true,
package/dist/chat.d.cts CHANGED
@@ -142,6 +142,10 @@ declare const ActivityLine: react.NamedExoticComponent<object>;
142
142
 
143
143
  type ProposalDecision = 'confirm' | 'decline';
144
144
  /** What the kit asks of the tenant's app. Only `onProposal` and `onOpenLink` are needed for the cards that use them. */
145
+ /** What a chat warning is about. */
146
+ interface ChatWarning {
147
+ readonly code: 'theme' | 'copy' | 'send_failed' | 'answer_failed' | 'proposal_failed' | 'photo_failed';
148
+ }
145
149
  interface ChatHandlers {
146
150
  /**
147
151
  * The person confirmed or declined a proposal: call your backend with the person's own token, then say what
@@ -164,8 +168,11 @@ interface ChatHandlers {
164
168
  * drawn by the kit's own parts when no `components.Error` or `components.Unavailable` replaces them.
165
169
  */
166
170
  readonly failureAction?: FailureAction;
167
- /** Development warnings: a theme that is hard to read, copy that says "assistant". */
168
- readonly onWarning?: (message: string) => void;
171
+ /**
172
+ * Warnings for the app's logger: a theme that is hard to read, copy that says "assistant", a send, an answer, a
173
+ * proposal or a photo pick that failed. `warning.code` says which, so a logger counts them without the text.
174
+ */
175
+ readonly onWarning?: (message: string, warning: ChatWarning) => void;
169
176
  /**
170
177
  * The person tapped a card about something of yours (its `ref`: a professional, a space, a booking): open its page
171
178
  * with your router. Without it, only the card's own actions open anything.
@@ -184,9 +191,13 @@ interface ImagePolicy {
184
191
  readonly hosts?: readonly string[];
185
192
  /** Width / height of a listing's photo frame. Default 1.6 (16:10). */
186
193
  readonly aspectRatio?: number;
187
- /** What stands in for a missing, refused or failed photo. Default the name's monogram. */
194
+ /**
195
+ * What stands in for a missing, refused or failed photo, by the card's `kind` (a person's tile, a space's tile).
196
+ * Default the name's monogram.
197
+ */
188
198
  readonly Placeholder?: ComponentType<{
189
199
  readonly title: string;
200
+ readonly kind: string;
190
201
  }>;
191
202
  }
192
203
  /** Parts a tenant can replace. Each gets the default's props and the default itself (`Default`), to wrap it. */
@@ -458,4 +469,4 @@ declare function useReducedMotion(): boolean;
458
469
  /** Reads a line to a screen reader, without moving focus. */
459
470
  declare function announce(text: string): void;
460
471
 
461
- export { ActivityLine, AgentChat, type AgentChatProps, type AgentChatSlots, type AgentEndedProps, AgentFooter, type AgentFooterProps, type AgentUnavailableScreenProps, type AgentUnreachableProps, Avatar, Button, type ButtonProps, CardActions, CardCarousel, CardFrame, type CardGroupProps, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type Chip, ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultEnded, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, type ImagePolicy, InfoCard, type LifecycleTarget, LinksCard, type ListProps, ListingCard, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeOverrides, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, Welcome, allowedImage, announce, answerText, carousels, defaultCard, fieldText, itemType, monogram, newestWholeReply, ratingText, useChat, useNativeLifecycle, useReducedMotion };
472
+ export { ActivityLine, AgentChat, type AgentChatProps, type AgentChatSlots, type AgentEndedProps, AgentFooter, type AgentFooterProps, type AgentUnavailableScreenProps, type AgentUnreachableProps, Avatar, Button, type ButtonProps, CardActions, CardCarousel, CardFrame, type CardGroupProps, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ChatWarning, type Chip, ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultEnded, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, type ImagePolicy, InfoCard, type LifecycleTarget, LinksCard, type ListProps, ListingCard, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeOverrides, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, Welcome, allowedImage, announce, answerText, carousels, defaultCard, fieldText, itemType, monogram, newestWholeReply, ratingText, useChat, useNativeLifecycle, useReducedMotion };
package/dist/chat.d.ts CHANGED
@@ -142,6 +142,10 @@ declare const ActivityLine: react.NamedExoticComponent<object>;
142
142
 
143
143
  type ProposalDecision = 'confirm' | 'decline';
144
144
  /** What the kit asks of the tenant's app. Only `onProposal` and `onOpenLink` are needed for the cards that use them. */
145
+ /** What a chat warning is about. */
146
+ interface ChatWarning {
147
+ readonly code: 'theme' | 'copy' | 'send_failed' | 'answer_failed' | 'proposal_failed' | 'photo_failed';
148
+ }
145
149
  interface ChatHandlers {
146
150
  /**
147
151
  * The person confirmed or declined a proposal: call your backend with the person's own token, then say what
@@ -164,8 +168,11 @@ interface ChatHandlers {
164
168
  * drawn by the kit's own parts when no `components.Error` or `components.Unavailable` replaces them.
165
169
  */
166
170
  readonly failureAction?: FailureAction;
167
- /** Development warnings: a theme that is hard to read, copy that says "assistant". */
168
- readonly onWarning?: (message: string) => void;
171
+ /**
172
+ * Warnings for the app's logger: a theme that is hard to read, copy that says "assistant", a send, an answer, a
173
+ * proposal or a photo pick that failed. `warning.code` says which, so a logger counts them without the text.
174
+ */
175
+ readonly onWarning?: (message: string, warning: ChatWarning) => void;
169
176
  /**
170
177
  * The person tapped a card about something of yours (its `ref`: a professional, a space, a booking): open its page
171
178
  * with your router. Without it, only the card's own actions open anything.
@@ -184,9 +191,13 @@ interface ImagePolicy {
184
191
  readonly hosts?: readonly string[];
185
192
  /** Width / height of a listing's photo frame. Default 1.6 (16:10). */
186
193
  readonly aspectRatio?: number;
187
- /** What stands in for a missing, refused or failed photo. Default the name's monogram. */
194
+ /**
195
+ * What stands in for a missing, refused or failed photo, by the card's `kind` (a person's tile, a space's tile).
196
+ * Default the name's monogram.
197
+ */
188
198
  readonly Placeholder?: ComponentType<{
189
199
  readonly title: string;
200
+ readonly kind: string;
190
201
  }>;
191
202
  }
192
203
  /** Parts a tenant can replace. Each gets the default's props and the default itself (`Default`), to wrap it. */
@@ -458,4 +469,4 @@ declare function useReducedMotion(): boolean;
458
469
  /** Reads a line to a screen reader, without moving focus. */
459
470
  declare function announce(text: string): void;
460
471
 
461
- export { ActivityLine, AgentChat, type AgentChatProps, type AgentChatSlots, type AgentEndedProps, AgentFooter, type AgentFooterProps, type AgentUnavailableScreenProps, type AgentUnreachableProps, Avatar, Button, type ButtonProps, CardActions, CardCarousel, CardFrame, type CardGroupProps, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type Chip, ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultEnded, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, type ImagePolicy, InfoCard, type LifecycleTarget, LinksCard, type ListProps, ListingCard, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeOverrides, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, Welcome, allowedImage, announce, answerText, carousels, defaultCard, fieldText, itemType, monogram, newestWholeReply, ratingText, useChat, useNativeLifecycle, useReducedMotion };
472
+ export { ActivityLine, AgentChat, type AgentChatProps, type AgentChatSlots, type AgentEndedProps, AgentFooter, type AgentFooterProps, type AgentUnavailableScreenProps, type AgentUnreachableProps, Avatar, Button, type ButtonProps, CardActions, CardCarousel, CardFrame, type CardGroupProps, type CardProps, CardView, type ChatHandlers, ChatHeader, ChatSkeleton, type ChatSlots, type ChatWarning, type Chip, ColorSchemeSetting, Composer, type ComposerProps, DefaultBubble, DefaultComposer, DefaultEnded, DefaultHeader, DefaultTurnFailed, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, DisclosureBar, type EmptyStateProps, type FailureAction, FailureActionButton, type FailureProps, type FailureState, type HeaderProps, type ImagePolicy, InfoCard, type LifecycleTarget, LinksCard, type ListProps, ListingCard, MessageBubble, type MessageBubbleProps, MessageList, NextStepCard, ProposalCard, type ProposalDecision, QuestionCard, Row, StatusBanner, StreamingBubble, SystemRow, ThemeOverrides, TimeSlotsCard, VinaverseChat, type VinaverseChatProps, VinaverseChatProvider, Welcome, allowedImage, announce, answerText, carousels, defaultCard, fieldText, itemType, monogram, newestWholeReply, ratingText, useChat, useNativeLifecycle, useReducedMotion };
package/dist/chat.js CHANGED
@@ -1,4 +1,4 @@
1
- export { ActivityLine, AgentChat, AgentFooter, AgentRuntimeProvider, 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, forgetGreeting, greetedKey, itemType, monogram, newestWholeReply, ratingText, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus, useChat } from './chunk-HTUXHZ7X.js';
1
+ export { ActivityLine, AgentChat, AgentFooter, AgentRuntimeProvider, 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, forgetGreeting, greetedKey, itemType, monogram, newestWholeReply, ratingText, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus, useChat } from './chunk-NXGLI4Y7.js';
2
2
  export { ThemeProvider, announce, createTheme, themeProblems, useNativeLifecycle, useReducedMotion, useTheme } from './chunk-EFEXTVIT.js';
3
3
  //# sourceMappingURL=chat.js.map
4
4
  //# sourceMappingURL=chat.js.map
@@ -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"]}
@@ -321,7 +321,7 @@ function ListingCard(props) {
321
321
  );
322
322
  const hero = photoUrl === failed ? null : photoUrl;
323
323
  const Img = slots.Image ?? reactNative.Image;
324
- const rating = card.rating ? `\u2605 ${ratingText(card.rating.value_ppm, locale)} (${card.rating.count})` : null;
324
+ const rating = card.rating ? `\u2605 ${ratingText(card.rating.value_ppm, locale)} (${card.rating.count})` : t("ratingNone") || null;
325
325
  const price = card.price_from ? t("priceFrom", {
326
326
  price: react$1.formatMoney(
327
327
  card.price_from.amount,
@@ -350,7 +350,7 @@ function ListingCard(props) {
350
350
  accessible: false,
351
351
  testID: `vinaverse-photo-${card.id}`
352
352
  }
353
- ) : imagePolicy?.Placeholder ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: photo, testID: `vinaverse-placeholder-${card.id}`, children: /* @__PURE__ */ jsxRuntime.jsx(imagePolicy.Placeholder, { title: card.title }) }) : /* @__PURE__ */ jsxRuntime.jsx(
353
+ ) : imagePolicy?.Placeholder ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: photo, testID: `vinaverse-placeholder-${card.id}`, children: /* @__PURE__ */ jsxRuntime.jsx(imagePolicy.Placeholder, { title: card.title, kind: card.kind }) }) : /* @__PURE__ */ jsxRuntime.jsx(
354
354
  reactNative.View,
355
355
  {
356
356
  accessible: false,
@@ -505,7 +505,9 @@ function ProposalCard(props) {
505
505
  props.card.id,
506
506
  () => onProposal(props.card, decision)
507
507
  ).catch(
508
- (error) => handlers.current?.onWarning?.(`Vinaverse proposal: ${String(error)}`)
508
+ (error) => handlers.current?.onWarning?.(`Vinaverse proposal: ${String(error)}`, {
509
+ code: "proposal_failed"
510
+ })
509
511
  );
510
512
  };
511
513
  const fields = proposal.fields.map((f) => {
@@ -627,7 +629,9 @@ function QuestionCard(props) {
627
629
  try {
628
630
  store.answer(held.id, questionId, answer);
629
631
  } catch (error) {
630
- handlers.current?.onWarning?.(`Vinaverse answer: ${String(error)}`);
632
+ handlers.current?.onWarning?.(`Vinaverse answer: ${String(error)}`, {
633
+ code: "answer_failed"
634
+ });
631
635
  }
632
636
  };
633
637
  const locked = held.locked.includes(question.question_id);
@@ -738,7 +742,8 @@ function Answer(props) {
738
742
  if (picked) send({ upload_ref: picked.upload_ref });
739
743
  }).catch(
740
744
  (error) => handlers.current?.onWarning?.(
741
- `Vinaverse photo: ${String(error)}`
745
+ `Vinaverse photo: ${String(error)}`,
746
+ { code: "photo_failed" }
742
747
  )
743
748
  );
744
749
  }
@@ -2199,10 +2204,11 @@ function VinaverseChatProvider(props) {
2199
2204
  react.useEffect(() => {
2200
2205
  if (!onWarning) return;
2201
2206
  for (const problem of chunk6QYDPGRS_cjs.themeProblems(theme))
2202
- onWarning(`Vinaverse theme: ${problem}`);
2207
+ onWarning(`Vinaverse theme: ${problem}`, { code: "theme" });
2203
2208
  for (const key of react$1.bannedWordsIn(copy ?? {}))
2204
2209
  onWarning(
2205
- `Vinaverse copy: "${key}" says assistant, bot or crew; the copy says agent.`
2210
+ `Vinaverse copy: "${key}" says assistant, bot or crew; the copy says agent.`,
2211
+ { code: "copy" }
2206
2212
  );
2207
2213
  }, [onWarning, theme, copy]);
2208
2214
  return /* @__PURE__ */ jsxRuntime.jsx(react$1.CopyProvider, { locale: props.locale, copy: props.copy, children: /* @__PURE__ */ jsxRuntime.jsx(chunk6QYDPGRS_cjs.ThemeProvider, { theme: props.theme, colorScheme: props.colorScheme, children: /* @__PURE__ */ jsxRuntime.jsx(ChatContextProvider, { value, children: props.children }) }) });
@@ -2226,7 +2232,7 @@ function Layout(props) {
2226
2232
  const { direction } = react$1.useCopy();
2227
2233
  const { onError } = props;
2228
2234
  const reportError = react.useMemo(
2229
- () => onError ? (e) => onError(String(e)) : void 0,
2235
+ () => onError ? (e) => onError(String(e), { code: "send_failed" }) : void 0,
2230
2236
  [onError]
2231
2237
  );
2232
2238
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -2646,5 +2652,5 @@ exports.monogram = monogram;
2646
2652
  exports.newestWholeReply = newestWholeReply;
2647
2653
  exports.ratingText = ratingText;
2648
2654
  exports.useChat = useChat;
2649
- //# sourceMappingURL=chunk-AGZ7IH7E.cjs.map
2650
- //# sourceMappingURL=chunk-AGZ7IH7E.cjs.map
2655
+ //# sourceMappingURL=chunk-EXN5TNLU.cjs.map
2656
+ //# sourceMappingURL=chunk-EXN5TNLU.cjs.map