@appilots/sdk 0.13.0 → 0.14.0
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/.build-meta.json +3 -3
- package/dist/{chunk-UYBKXULM.mjs → chunk-6JWU3NBT.mjs} +52 -24
- package/dist/{chunk-HRWBK35Y.mjs → chunk-AKAMWKO6.mjs} +61 -10
- package/dist/{chunk-ALJGKORS.js → chunk-GDCBLSYT.js} +8 -8
- package/dist/{chunk-AJDHZRBN.js → chunk-JGUDXRXN.js} +369 -340
- package/dist/{chunk-L3SY3Q4K.mjs → chunk-N66DUP54.mjs} +1 -1
- package/dist/{chunk-UZ2D4BVX.js → chunk-QAZ4TN3Z.js} +64 -9
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/{index-CI4jmSoP.d.mts → index-wMMetyrj.d.mts} +33 -0
- package/dist/{index-CI4jmSoP.d.ts → index-wMMetyrj.d.ts} +33 -0
- package/dist/index.d.mts +115 -62
- package/dist/index.d.ts +115 -62
- package/dist/index.js +504 -179
- package/dist/index.mjs +399 -78
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { AppilotsNavigationContainer } from './chunk-
|
|
2
|
-
import { subscribeSpotlight, getSpotlightTarget, AppilotsI18nProvider, useAppilotsI18n, useAppilotsChat, useAppilotsActions, setSpotlightMode, shouldShowSuggestedPrompts, useSuggestedPrompts } from './chunk-
|
|
3
|
-
export { AppilotsI18nProvider, REVEAL_MARGIN, SPOTLIGHT_TTL_MS, appilotsSelfCheck, captureSnapshot, detectDeviceLocale, executeAction, getSpotlightMode, getSpotlightTarget, offsetToReveal, resolveLocale, revealTarget, setSpotlightMode, setSpotlightTarget, subscribeSpotlight, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsI18n, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts } from './chunk-
|
|
4
|
-
import { defaultLightTheme, describeAction, isRectOnScreen, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, subscribeGeometryHost, geometryAvailability, isGeometryResolved, needsWideChatLayout, componentRegistry, appilotsDebugWarn, enhancePlainAssistantContent, looksLikeMarkdown, parseMarkdownBlocks, parseInlineMarkdown, getFiberRoot, shouldSkipSubtree, isModalFiber } from './chunk-
|
|
5
|
-
export { AppilotsClient, AppilotsProvider, AppilotsRegistryProvider, RateLimitedError, SDK_VERSION, _patchJsxRuntimes, clearAppilotsDebugTraces, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, defaultDarkTheme, defaultLightTheme, describeAction, elementRegistry, enableAppilotsAutoTracking, getAppilotsDebugTraces, getAutoTrackingState, getGlobalConfig, getIntrospectionDiagnostics, humanizeError, initAppilots, isAutoTrackingEnabled, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-
|
|
1
|
+
export { AppilotsNavigationContainer } from './chunk-N66DUP54.mjs';
|
|
2
|
+
import { subscribeSpotlight, getSpotlightTarget, AppilotsI18nProvider, useAppilotsI18n, useAppilotsChat, useAppilotsActions, setSpotlightMode, shouldShowSuggestedPrompts, useSuggestedPrompts, subscribeSpotlightAnnouncement } from './chunk-6JWU3NBT.mjs';
|
|
3
|
+
export { AppilotsI18nProvider, REVEAL_MARGIN, SPOTLIGHT_TTL_MS, appilotsSelfCheck, captureSnapshot, detectDeviceLocale, executeAction, getSpotlightMode, getSpotlightTarget, offsetToReveal, resolveLocale, revealTarget, setSpotlightMode, setSpotlightTarget, subscribeSpotlight, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsI18n, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts } from './chunk-6JWU3NBT.mjs';
|
|
4
|
+
import { defaultLightTheme, describeAction, confirmExpiresAt, isRectOnScreen, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, isSpeechHost, subscribeGeometryHost, geometryAvailability, isGeometryResolved, needsWideChatLayout, componentRegistry, startStillWorkingTimer, appilotsDebugWarn, enhancePlainAssistantContent, looksLikeMarkdown, parseMarkdownBlocks, parseInlineMarkdown, getFiberRoot, shouldSkipSubtree, isModalFiber } from './chunk-AKAMWKO6.mjs';
|
|
5
|
+
export { AppilotsClient, AppilotsProvider, AppilotsRegistryProvider, RateLimitedError, SDK_VERSION, _patchJsxRuntimes, clearAppilotsDebugTraces, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, defaultDarkTheme, defaultLightTheme, describeAction, elementRegistry, enableAppilotsAutoTracking, getAppilotsDebugTraces, getAutoTrackingState, getGlobalConfig, getIntrospectionDiagnostics, humanizeError, initAppilots, isAutoTrackingEnabled, isSpeechHost, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-AKAMWKO6.mjs';
|
|
6
6
|
import * as React8 from 'react';
|
|
7
|
-
import React8__default, { createContext, useRef, useEffect, useCallback, useSyncExternalStore, useMemo, useContext
|
|
8
|
-
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, ActivityIndicator, useColorScheme, FlatList, Image, TextInput, KeyboardAvoidingView, Modal, Linking } from 'react-native';
|
|
7
|
+
import React8__default, { createContext, useRef, useEffect, useState, useCallback, useSyncExternalStore, useMemo, useContext } from 'react';
|
|
8
|
+
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, AccessibilityInfo, ActivityIndicator, useColorScheme, useWindowDimensions, FlatList, Image, TextInput, KeyboardAvoidingView, Modal, Linking } from 'react-native';
|
|
9
9
|
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
|
10
10
|
import Svg, { Path } from 'react-native-svg';
|
|
11
11
|
|
|
@@ -116,13 +116,15 @@ var PT_BR_CONFIRM_FALLBACK = {
|
|
|
116
116
|
confirmDestructiveApprove: "Sim, executar",
|
|
117
117
|
confirmApprove: "Confirmar",
|
|
118
118
|
confirmCancel: "Cancelar",
|
|
119
|
-
confirmThisAction: "esta a\xE7\xE3o"
|
|
119
|
+
confirmThisAction: "esta a\xE7\xE3o",
|
|
120
|
+
confirmExpired: "Esta confirma\xE7\xE3o expirou. Pe\xE7a de novo ao assistente para continuar."
|
|
120
121
|
};
|
|
121
122
|
function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE, strings) {
|
|
122
123
|
const payload = action.payload ?? {};
|
|
123
124
|
const isDestructive = isDestructiveAction(action);
|
|
124
125
|
const copy = { ...PT_BR_CONFIRM_FALLBACK, ...strings ?? {} };
|
|
125
|
-
const
|
|
126
|
+
const described = typeof payload.actionDescription === "string" ? payload.actionDescription : "";
|
|
127
|
+
const actionName = described || copy.confirmThisAction;
|
|
126
128
|
const message = typeof payload.message === "string" && payload.message || copy.confirmMessage.replace("{action}", actionName);
|
|
127
129
|
const title = typeof payload.title === "string" && payload.title || (isDestructive ? copy.confirmDestructiveTitle : copy.confirmTitle);
|
|
128
130
|
const confirmLabel = typeof payload.confirmLabel === "string" && payload.confirmLabel || (isDestructive ? copy.confirmDestructiveApprove : copy.confirmApprove);
|
|
@@ -133,6 +135,10 @@ function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE,
|
|
|
133
135
|
message,
|
|
134
136
|
confirmLabel,
|
|
135
137
|
cancelLabel,
|
|
138
|
+
// A bare "Confirm" heard out of context says nothing about what it does.
|
|
139
|
+
confirmA11yLabel: described ? `${confirmLabel}: ${described}` : confirmLabel,
|
|
140
|
+
cancelA11yLabel: described ? `${cancelLabel}: ${described}` : cancelLabel,
|
|
141
|
+
expiredMessage: copy.confirmExpired ?? PT_BR_CONFIRM_FALLBACK.confirmExpired,
|
|
136
142
|
glyph: isDestructive ? "\u26A0" : "?",
|
|
137
143
|
actionColor: isDestructive ? palette.error : palette.primary,
|
|
138
144
|
cardBackground: palette.surface,
|
|
@@ -142,6 +148,79 @@ function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE,
|
|
|
142
148
|
cancelTextColor: palette.textSecondary
|
|
143
149
|
};
|
|
144
150
|
}
|
|
151
|
+
var TARGET_ANNOUNCEMENT = {
|
|
152
|
+
"pt-BR": {
|
|
153
|
+
press: "Tocando em {label}",
|
|
154
|
+
toggle: "Alternando {label}",
|
|
155
|
+
focus: "Selecionando {label}",
|
|
156
|
+
fill: "Preenchendo {label}"
|
|
157
|
+
},
|
|
158
|
+
en: {
|
|
159
|
+
press: "Tapping {label}",
|
|
160
|
+
toggle: "Toggling {label}",
|
|
161
|
+
focus: "Selecting {label}",
|
|
162
|
+
fill: "Filling in {label}"
|
|
163
|
+
},
|
|
164
|
+
es: {
|
|
165
|
+
press: "Tocando {label}",
|
|
166
|
+
toggle: "Cambiando {label}",
|
|
167
|
+
focus: "Seleccionando {label}",
|
|
168
|
+
fill: "Rellenando {label}"
|
|
169
|
+
},
|
|
170
|
+
fr: {
|
|
171
|
+
press: "Appui sur {label}",
|
|
172
|
+
toggle: "Bascule de {label}",
|
|
173
|
+
focus: "S\xE9lection de {label}",
|
|
174
|
+
fill: "Saisie de {label}"
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
function targetAnnouncement(verb, label, locale = "pt-BR") {
|
|
178
|
+
return (TARGET_ANNOUNCEMENT[locale] ?? TARGET_ANNOUNCEMENT["pt-BR"])[verb].replace(
|
|
179
|
+
"{label}",
|
|
180
|
+
label
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
function executorNamesTarget(action) {
|
|
184
|
+
if (action.type === "form_fill") return true;
|
|
185
|
+
if (action.type !== "ui_interaction") return false;
|
|
186
|
+
const interaction = action.payload?.action;
|
|
187
|
+
return !["scroll", "scroll_to"].includes(String(interaction ?? "press"));
|
|
188
|
+
}
|
|
189
|
+
function actionAnnouncement(action, locale, named) {
|
|
190
|
+
const { state, label } = describeAction(action, locale);
|
|
191
|
+
if (state === "failed") return label;
|
|
192
|
+
const executorNames = executorNamesTarget(action);
|
|
193
|
+
if (state === "running") return executorNames ? null : label;
|
|
194
|
+
if (state === "success") return executorNames && !named ? label : null;
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
var reduceMotion = false;
|
|
198
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
199
|
+
var subscription;
|
|
200
|
+
function set(value) {
|
|
201
|
+
if (value === reduceMotion) return;
|
|
202
|
+
reduceMotion = value;
|
|
203
|
+
for (const listener of listeners) listener();
|
|
204
|
+
}
|
|
205
|
+
function subscribe(onChange) {
|
|
206
|
+
listeners.add(onChange);
|
|
207
|
+
if (!subscription) {
|
|
208
|
+
subscription = AccessibilityInfo.addEventListener("reduceMotionChanged", set);
|
|
209
|
+
AccessibilityInfo.isReduceMotionEnabled().then(set, () => {
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return () => {
|
|
213
|
+
listeners.delete(onChange);
|
|
214
|
+
if (listeners.size === 0) {
|
|
215
|
+
subscription?.remove();
|
|
216
|
+
subscription = void 0;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
var get = () => reduceMotion;
|
|
221
|
+
function useReduceMotion() {
|
|
222
|
+
return useSyncExternalStore(subscribe, get, get);
|
|
223
|
+
}
|
|
145
224
|
|
|
146
225
|
// src/components/ActionBreadcrumb.tsx
|
|
147
226
|
function ActionBreadcrumb({
|
|
@@ -154,7 +233,8 @@ function ActionBreadcrumb({
|
|
|
154
233
|
locale,
|
|
155
234
|
requireApprovalFor,
|
|
156
235
|
onApprove,
|
|
157
|
-
onReject
|
|
236
|
+
onReject,
|
|
237
|
+
onConfirmCardGone
|
|
158
238
|
}) {
|
|
159
239
|
if (actions.length === 0) return null;
|
|
160
240
|
const resolvedPalette = {
|
|
@@ -176,7 +256,8 @@ function ActionBreadcrumb({
|
|
|
176
256
|
locale,
|
|
177
257
|
needsApproval: requireApprovalFor?.(action) ?? false,
|
|
178
258
|
onApprove,
|
|
179
|
-
onReject
|
|
259
|
+
onReject,
|
|
260
|
+
onConfirmCardGone
|
|
180
261
|
}
|
|
181
262
|
)));
|
|
182
263
|
}
|
|
@@ -191,7 +272,8 @@ function BreadcrumbRow(props) {
|
|
|
191
272
|
fontFamily: props.fontFamily,
|
|
192
273
|
confirmStrings: props.confirmStrings,
|
|
193
274
|
onApprove: props.onApprove,
|
|
194
|
-
onReject: props.onReject
|
|
275
|
+
onReject: props.onReject,
|
|
276
|
+
onGone: props.onConfirmCardGone
|
|
195
277
|
}
|
|
196
278
|
);
|
|
197
279
|
}
|
|
@@ -213,40 +295,39 @@ function RegularBreadcrumbRow({
|
|
|
213
295
|
const fade = useRef(new Animated.Value(0)).current;
|
|
214
296
|
const pulse = useRef(new Animated.Value(1)).current;
|
|
215
297
|
const lastState = useRef(state);
|
|
298
|
+
const reduceMotion2 = useReduceMotion();
|
|
216
299
|
useEffect(() => {
|
|
300
|
+
if (reduceMotion2) {
|
|
301
|
+
fade.setValue(1);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
217
304
|
Animated.timing(fade, {
|
|
218
305
|
toValue: 1,
|
|
219
306
|
duration: 180,
|
|
220
307
|
useNativeDriver: true
|
|
221
308
|
}).start();
|
|
222
|
-
}, [fade]);
|
|
309
|
+
}, [fade, reduceMotion2]);
|
|
223
310
|
useEffect(() => {
|
|
224
311
|
if (lastState.current === state) return;
|
|
225
312
|
lastState.current = state;
|
|
313
|
+
if (reduceMotion2) return;
|
|
226
314
|
pulse.setValue(0.4);
|
|
227
315
|
Animated.timing(pulse, {
|
|
228
316
|
toValue: 1,
|
|
229
317
|
duration: 220,
|
|
230
318
|
useNativeDriver: true
|
|
231
319
|
}).start();
|
|
232
|
-
}, [state, pulse]);
|
|
320
|
+
}, [state, pulse, reduceMotion2]);
|
|
233
321
|
const isDestructive = isDestructiveAction(action);
|
|
234
|
-
return /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React8__default.createElement(
|
|
235
|
-
|
|
322
|
+
return /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.labelGroup, { opacity: pulse }] }, /* @__PURE__ */ React8__default.createElement(StateIcon, { state, tone, primaryColor }), /* @__PURE__ */ React8__default.createElement(
|
|
323
|
+
Text,
|
|
236
324
|
{
|
|
237
|
-
style: {
|
|
325
|
+
style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
|
|
326
|
+
accessibilityLabel: `${state}: ${label}`
|
|
238
327
|
},
|
|
239
|
-
|
|
240
|
-
/* @__PURE__ */ React8__default.createElement(
|
|
241
|
-
|
|
242
|
-
{
|
|
243
|
-
style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
|
|
244
|
-
accessibilityLabel: `${state}: ${label}`
|
|
245
|
-
},
|
|
246
|
-
label,
|
|
247
|
-
isDestructive && /* @__PURE__ */ React8__default.createElement(Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
|
|
248
|
-
)
|
|
249
|
-
), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React8__default.createElement(View, { style: styles.approvalButtons }, /* @__PURE__ */ React8__default.createElement(
|
|
328
|
+
label,
|
|
329
|
+
isDestructive && /* @__PURE__ */ React8__default.createElement(Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
|
|
330
|
+
)), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React8__default.createElement(View, { style: styles.approvalButtons }, /* @__PURE__ */ React8__default.createElement(
|
|
250
331
|
TouchableOpacity,
|
|
251
332
|
{
|
|
252
333
|
onPress: () => onReject(action.id),
|
|
@@ -268,13 +349,15 @@ function RegularBreadcrumbRow({
|
|
|
268
349
|
/* @__PURE__ */ React8__default.createElement(Text, { style: styles.approveBtnText }, "Aprovar")
|
|
269
350
|
)));
|
|
270
351
|
}
|
|
352
|
+
var MIN_TOUCH_TARGET = 44;
|
|
271
353
|
function ConfirmCard({
|
|
272
354
|
action,
|
|
273
355
|
palette,
|
|
274
356
|
fontFamily,
|
|
275
357
|
confirmStrings,
|
|
276
358
|
onApprove,
|
|
277
|
-
onReject
|
|
359
|
+
onReject,
|
|
360
|
+
onGone
|
|
278
361
|
}) {
|
|
279
362
|
const {
|
|
280
363
|
isDestructive,
|
|
@@ -282,6 +365,9 @@ function ConfirmCard({
|
|
|
282
365
|
message,
|
|
283
366
|
confirmLabel,
|
|
284
367
|
cancelLabel,
|
|
368
|
+
confirmA11yLabel,
|
|
369
|
+
cancelA11yLabel,
|
|
370
|
+
expiredMessage,
|
|
285
371
|
glyph,
|
|
286
372
|
actionColor,
|
|
287
373
|
cardBackground,
|
|
@@ -290,6 +376,23 @@ function ConfirmCard({
|
|
|
290
376
|
cancelBackground,
|
|
291
377
|
cancelTextColor
|
|
292
378
|
} = deriveConfirmCardContent(action, palette, confirmStrings);
|
|
379
|
+
const summaryRef = useRef(null);
|
|
380
|
+
const expiresAt = confirmExpiresAt(action);
|
|
381
|
+
const [expired, setExpired] = useState(() => expiresAt !== void 0 && expiresAt <= Date.now());
|
|
382
|
+
const onGoneRef = useRef(onGone);
|
|
383
|
+
onGoneRef.current = onGone;
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (summaryRef.current) AccessibilityInfo.sendAccessibilityEvent(summaryRef.current, "focus");
|
|
386
|
+
return () => onGoneRef.current?.();
|
|
387
|
+
}, []);
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (expiresAt === void 0 || expired) return;
|
|
390
|
+
const timer = setTimeout(() => setExpired(true), expiresAt - Date.now());
|
|
391
|
+
return () => clearTimeout(timer);
|
|
392
|
+
}, [expiresAt, expired]);
|
|
393
|
+
useEffect(() => {
|
|
394
|
+
if (expired) AccessibilityInfo.announceForAccessibility(expiredMessage);
|
|
395
|
+
}, [expired, expiredMessage]);
|
|
293
396
|
return /* @__PURE__ */ React8__default.createElement(
|
|
294
397
|
View,
|
|
295
398
|
{
|
|
@@ -297,26 +400,46 @@ function ConfirmCard({
|
|
|
297
400
|
confirmCardStyles.card,
|
|
298
401
|
{ backgroundColor: cardBackground, borderColor: cardBorderColor }
|
|
299
402
|
],
|
|
300
|
-
testID: "assistant-confirm-card"
|
|
403
|
+
testID: "assistant-confirm-card",
|
|
404
|
+
onAccessibilityEscape: () => onReject?.(action.id)
|
|
301
405
|
},
|
|
302
|
-
/* @__PURE__ */ React8__default.createElement(
|
|
406
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
407
|
+
View,
|
|
408
|
+
{
|
|
409
|
+
ref: summaryRef,
|
|
410
|
+
accessible: true,
|
|
411
|
+
accessibilityLabel: `${title}. ${message}`,
|
|
412
|
+
accessibilityLiveRegion: "polite"
|
|
413
|
+
},
|
|
414
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.headerRow }, /* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.glyph, { color: actionColor }] }, glyph), /* @__PURE__ */ React8__default.createElement(
|
|
415
|
+
Text,
|
|
416
|
+
{
|
|
417
|
+
style: [
|
|
418
|
+
confirmCardStyles.title,
|
|
419
|
+
{ color: isDestructive ? palette.error : palette.text, fontFamily }
|
|
420
|
+
]
|
|
421
|
+
},
|
|
422
|
+
title
|
|
423
|
+
)),
|
|
424
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message)
|
|
425
|
+
),
|
|
426
|
+
expired && /* @__PURE__ */ React8__default.createElement(
|
|
303
427
|
Text,
|
|
304
428
|
{
|
|
305
|
-
style: [
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
]
|
|
429
|
+
style: [confirmCardStyles.expired, { color: palette.error, fontFamily }],
|
|
430
|
+
accessibilityLiveRegion: "assertive",
|
|
431
|
+
testID: "assistant-confirm-expired"
|
|
309
432
|
},
|
|
310
|
-
|
|
311
|
-
)
|
|
312
|
-
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message),
|
|
433
|
+
expiredMessage
|
|
434
|
+
),
|
|
313
435
|
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React8__default.createElement(
|
|
314
436
|
TouchableOpacity,
|
|
315
437
|
{
|
|
316
438
|
onPress: () => onReject?.(action.id),
|
|
317
439
|
style: [confirmCardStyles.btn, { backgroundColor: cancelBackground }],
|
|
318
440
|
activeOpacity: 0.7,
|
|
319
|
-
|
|
441
|
+
accessibilityRole: "button",
|
|
442
|
+
accessibilityLabel: cancelA11yLabel,
|
|
320
443
|
testID: "assistant-confirm-reject"
|
|
321
444
|
},
|
|
322
445
|
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
|
|
@@ -324,13 +447,17 @@ function ConfirmCard({
|
|
|
324
447
|
TouchableOpacity,
|
|
325
448
|
{
|
|
326
449
|
onPress: () => onApprove?.(action.id),
|
|
450
|
+
disabled: expired,
|
|
327
451
|
style: [
|
|
328
452
|
confirmCardStyles.btn,
|
|
329
453
|
confirmCardStyles.confirmBtn,
|
|
330
|
-
{ backgroundColor: actionColor }
|
|
454
|
+
{ backgroundColor: actionColor },
|
|
455
|
+
expired && confirmCardStyles.disabledBtn
|
|
331
456
|
],
|
|
332
457
|
activeOpacity: 0.7,
|
|
333
|
-
|
|
458
|
+
accessibilityRole: "button",
|
|
459
|
+
accessibilityState: { disabled: expired },
|
|
460
|
+
accessibilityLabel: confirmA11yLabel,
|
|
334
461
|
testID: "assistant-confirm-approve"
|
|
335
462
|
},
|
|
336
463
|
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
|
|
@@ -367,18 +494,33 @@ var confirmCardStyles = StyleSheet.create({
|
|
|
367
494
|
// color set inline — theme-driven (textSecondary).
|
|
368
495
|
marginBottom: 12
|
|
369
496
|
},
|
|
497
|
+
// Wraps: on one line the two buttons ran off the LEFT edge at iOS AX5
|
|
498
|
+
// and Cancel was unreachable — on the one card that gates something
|
|
499
|
+
// irreversible.
|
|
370
500
|
buttons: {
|
|
371
501
|
flexDirection: "row",
|
|
502
|
+
flexWrap: "wrap",
|
|
372
503
|
gap: 8,
|
|
373
504
|
justifyContent: "flex-end"
|
|
374
505
|
},
|
|
375
506
|
btn: {
|
|
507
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
508
|
+
maxWidth: "100%",
|
|
509
|
+
justifyContent: "center",
|
|
376
510
|
paddingHorizontal: 14,
|
|
377
511
|
paddingVertical: 8,
|
|
378
512
|
borderRadius: 10,
|
|
379
513
|
minWidth: 96,
|
|
380
514
|
alignItems: "center"
|
|
381
515
|
},
|
|
516
|
+
disabledBtn: {
|
|
517
|
+
opacity: 0.4
|
|
518
|
+
},
|
|
519
|
+
expired: {
|
|
520
|
+
fontSize: 13,
|
|
521
|
+
fontWeight: "600",
|
|
522
|
+
marginBottom: 12
|
|
523
|
+
},
|
|
382
524
|
cancelText: {
|
|
383
525
|
fontSize: 13,
|
|
384
526
|
fontWeight: "600"
|
|
@@ -398,7 +540,11 @@ function StateIcon({
|
|
|
398
540
|
tone,
|
|
399
541
|
primaryColor
|
|
400
542
|
}) {
|
|
401
|
-
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: primaryColor }) :
|
|
543
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: primaryColor }) : (
|
|
544
|
+
// Decorative, inside a fixed circle: capped so it cannot clip. The
|
|
545
|
+
// state is also in the row's accessibilityLabel.
|
|
546
|
+
/* @__PURE__ */ React8__default.createElement(Text, { maxFontSizeMultiplier: 1.3, style: [styles.iconGlyph, { color: tone.color }] }, iconGlyphFor(state))
|
|
547
|
+
));
|
|
402
548
|
}
|
|
403
549
|
var styles = StyleSheet.create({
|
|
404
550
|
container: {
|
|
@@ -406,12 +552,26 @@ var styles = StyleSheet.create({
|
|
|
406
552
|
marginBottom: 8,
|
|
407
553
|
paddingVertical: 4
|
|
408
554
|
},
|
|
555
|
+
// Wraps so Approve/Reject drop below the label at large text sizes. On
|
|
556
|
+
// one line they squeezed the label to zero width (iOS AX5): the user was
|
|
557
|
+
// asked to approve an action they could not read.
|
|
409
558
|
row: {
|
|
410
559
|
flexDirection: "row",
|
|
560
|
+
flexWrap: "wrap",
|
|
561
|
+
gap: 8,
|
|
411
562
|
alignItems: "center",
|
|
412
563
|
paddingVertical: 6,
|
|
413
564
|
paddingHorizontal: 4
|
|
414
565
|
},
|
|
566
|
+
labelGroup: {
|
|
567
|
+
flexDirection: "row",
|
|
568
|
+
alignItems: "flex-start",
|
|
569
|
+
flexGrow: 1,
|
|
570
|
+
flexShrink: 1,
|
|
571
|
+
flexBasis: 0,
|
|
572
|
+
// What forces the wrap: the label keeps at least half the row.
|
|
573
|
+
minWidth: "50%"
|
|
574
|
+
},
|
|
415
575
|
iconCircle: {
|
|
416
576
|
width: 22,
|
|
417
577
|
height: 22,
|
|
@@ -439,9 +599,11 @@ var styles = StyleSheet.create({
|
|
|
439
599
|
approvalButtons: {
|
|
440
600
|
flexDirection: "row",
|
|
441
601
|
gap: 6,
|
|
442
|
-
marginLeft:
|
|
602
|
+
marginLeft: "auto"
|
|
443
603
|
},
|
|
444
604
|
btn: {
|
|
605
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
606
|
+
justifyContent: "center",
|
|
445
607
|
paddingHorizontal: 10,
|
|
446
608
|
paddingVertical: 5,
|
|
447
609
|
borderRadius: 8
|
|
@@ -505,6 +667,7 @@ var APPILOTS_SKIP_PROPS = {
|
|
|
505
667
|
};
|
|
506
668
|
|
|
507
669
|
// src/components/AgentPill.tsx
|
|
670
|
+
var PILL_MAX_FONT_SCALE = 1.5;
|
|
508
671
|
function toneFor(state, colors) {
|
|
509
672
|
switch (state) {
|
|
510
673
|
case "success":
|
|
@@ -519,6 +682,7 @@ function AgentPill({
|
|
|
519
682
|
label,
|
|
520
683
|
state,
|
|
521
684
|
onExpand,
|
|
685
|
+
expandRef,
|
|
522
686
|
onStop,
|
|
523
687
|
position,
|
|
524
688
|
insets,
|
|
@@ -527,15 +691,20 @@ function AgentPill({
|
|
|
527
691
|
strings
|
|
528
692
|
}) {
|
|
529
693
|
const atTop = position === "top-left" || position === "top-right";
|
|
694
|
+
const reduceMotion2 = useReduceMotion();
|
|
530
695
|
const enter = useRef(new Animated.Value(0)).current;
|
|
531
696
|
useEffect(() => {
|
|
697
|
+
if (reduceMotion2) {
|
|
698
|
+
enter.setValue(1);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
532
701
|
Animated.spring(enter, {
|
|
533
702
|
toValue: 1,
|
|
534
703
|
useNativeDriver: true,
|
|
535
704
|
tension: 70,
|
|
536
705
|
friction: 12
|
|
537
706
|
}).start();
|
|
538
|
-
}, [enter]);
|
|
707
|
+
}, [enter, reduceMotion2]);
|
|
539
708
|
const translateY = enter.interpolate({
|
|
540
709
|
inputRange: [0, 1],
|
|
541
710
|
outputRange: [atTop ? -80 : 80, 0]
|
|
@@ -556,6 +725,7 @@ function AgentPill({
|
|
|
556
725
|
TouchableOpacity,
|
|
557
726
|
{
|
|
558
727
|
...APPILOTS_SKIP_PROPS,
|
|
728
|
+
ref: expandRef,
|
|
559
729
|
testID: "appilots-agent-pill",
|
|
560
730
|
accessibilityRole: "button",
|
|
561
731
|
accessibilityLabel: strings.expandA11y,
|
|
@@ -568,7 +738,8 @@ function AgentPill({
|
|
|
568
738
|
Text,
|
|
569
739
|
{
|
|
570
740
|
testID: "appilots-agent-pill-label",
|
|
571
|
-
numberOfLines:
|
|
741
|
+
numberOfLines: 2,
|
|
742
|
+
maxFontSizeMultiplier: PILL_MAX_FONT_SCALE,
|
|
572
743
|
style: [styles2.label, { color: colors.text, fontFamily }]
|
|
573
744
|
},
|
|
574
745
|
label
|
|
@@ -640,15 +811,21 @@ function SpotlightOverlay({
|
|
|
640
811
|
fontFamily,
|
|
641
812
|
window: win
|
|
642
813
|
}) {
|
|
643
|
-
const
|
|
814
|
+
const reduceMotion2 = useReduceMotion();
|
|
815
|
+
const pulse = useRef(new Animated.Value(reduceMotion2 ? 1 : 0)).current;
|
|
644
816
|
useEffect(() => {
|
|
817
|
+
if (reduceMotion2) {
|
|
818
|
+
pulse.stopAnimation();
|
|
819
|
+
pulse.setValue(1);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
645
822
|
pulse.setValue(0);
|
|
646
823
|
Animated.timing(pulse, {
|
|
647
824
|
toValue: 1,
|
|
648
825
|
duration: 220,
|
|
649
826
|
useNativeDriver: true
|
|
650
827
|
}).start();
|
|
651
|
-
}, [seq, pulse]);
|
|
828
|
+
}, [seq, pulse, reduceMotion2]);
|
|
652
829
|
if (!isRectOnScreen(rect, win)) return null;
|
|
653
830
|
const frame = {
|
|
654
831
|
left: rect.x - PADDING,
|
|
@@ -739,11 +916,11 @@ var NEVER = () => () => {
|
|
|
739
916
|
};
|
|
740
917
|
var NULL_TARGET = () => null;
|
|
741
918
|
function useSpotlight(enabled) {
|
|
742
|
-
const
|
|
919
|
+
const subscribe2 = useCallback(
|
|
743
920
|
(onChange) => enabled ? subscribeSpotlight(onChange) : NEVER(),
|
|
744
921
|
[enabled]
|
|
745
922
|
);
|
|
746
|
-
return useSyncExternalStore(
|
|
923
|
+
return useSyncExternalStore(subscribe2, enabled ? getSpotlightTarget : NULL_TARGET, NULL_TARGET);
|
|
747
924
|
}
|
|
748
925
|
|
|
749
926
|
// src/components/pillStatus.ts
|
|
@@ -763,12 +940,74 @@ function resolvePillStatus(actions, busy, strings) {
|
|
|
763
940
|
}
|
|
764
941
|
return { label: strings.working, state: "running" };
|
|
765
942
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
943
|
+
var STREAMING_PREFIX = "streaming_";
|
|
944
|
+
function announce(message) {
|
|
945
|
+
if (Platform.OS === "ios" && AccessibilityInfo.announceForAccessibilityWithOptions) {
|
|
946
|
+
AccessibilityInfo.announceForAccessibilityWithOptions(message, { queue: true });
|
|
947
|
+
} else {
|
|
948
|
+
AccessibilityInfo.announceForAccessibility(message);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
var speakable = (content) => content.replace(/[*`#]+/g, "").trim();
|
|
952
|
+
function useChatAnnouncements({
|
|
953
|
+
messages,
|
|
954
|
+
actions,
|
|
955
|
+
awaitingApproval,
|
|
956
|
+
acting,
|
|
957
|
+
locale,
|
|
958
|
+
strings
|
|
959
|
+
}) {
|
|
960
|
+
const seenMessages = useRef(null);
|
|
961
|
+
if (!seenMessages.current) seenMessages.current = new Set(messages.map((m) => m.id));
|
|
962
|
+
const seenActions = useRef(null);
|
|
963
|
+
if (!seenActions.current) seenActions.current = new Map(actions.map((a) => [a.id, a.status]));
|
|
964
|
+
const prev = useRef({ awaitingApproval, acting });
|
|
965
|
+
const namedSinceSettle = useRef(false);
|
|
966
|
+
const localeRef = useRef(locale);
|
|
967
|
+
localeRef.current = locale;
|
|
968
|
+
useEffect(
|
|
969
|
+
() => subscribeSpotlightAnnouncement((label, verb) => {
|
|
970
|
+
namedSinceSettle.current = true;
|
|
971
|
+
announce(targetAnnouncement(verb, label, localeRef.current));
|
|
972
|
+
}),
|
|
973
|
+
[]
|
|
974
|
+
);
|
|
975
|
+
useEffect(() => {
|
|
976
|
+
const out = [];
|
|
977
|
+
for (const message of messages) {
|
|
978
|
+
if (message.role === "user" || message.id.startsWith(STREAMING_PREFIX)) continue;
|
|
979
|
+
if (seenMessages.current.has(message.id)) continue;
|
|
980
|
+
seenMessages.current.add(message.id);
|
|
981
|
+
const text = speakable(message.content);
|
|
982
|
+
if (text) out.push(text);
|
|
983
|
+
}
|
|
984
|
+
for (const action of actions) {
|
|
985
|
+
if (action.type === "confirm") continue;
|
|
986
|
+
if (seenActions.current.get(action.id) === action.status) continue;
|
|
987
|
+
seenActions.current.set(action.id, action.status);
|
|
988
|
+
const line = actionAnnouncement(action, locale, namedSinceSettle.current);
|
|
989
|
+
if (action.status === "completed" || action.status === "failed") {
|
|
990
|
+
namedSinceSettle.current = false;
|
|
991
|
+
}
|
|
992
|
+
if (line) out.push(line);
|
|
993
|
+
}
|
|
994
|
+
if (awaitingApproval && !prev.current.awaitingApproval) out.push(strings.a11yAwaitingApproval);
|
|
995
|
+
if (prev.current.acting && !acting) out.push(strings.a11yTurnDone);
|
|
996
|
+
prev.current = { awaitingApproval, acting };
|
|
997
|
+
for (const line of out) announce(line);
|
|
998
|
+
}, [messages, actions, awaitingApproval, acting, locale, strings]);
|
|
999
|
+
}
|
|
1000
|
+
function useStillWorking(active, template) {
|
|
1001
|
+
const [seconds, setSeconds] = useState(0);
|
|
1002
|
+
useEffect(() => {
|
|
1003
|
+
setSeconds(0);
|
|
1004
|
+
if (!active) return;
|
|
1005
|
+
return startStillWorkingTimer((elapsed) => {
|
|
1006
|
+
setSeconds(elapsed);
|
|
1007
|
+
AccessibilityInfo.announceForAccessibility(template.replace("{seconds}", String(elapsed)));
|
|
1008
|
+
});
|
|
1009
|
+
}, [active, template]);
|
|
1010
|
+
return seconds;
|
|
772
1011
|
}
|
|
773
1012
|
function useVoiceInput({
|
|
774
1013
|
host,
|
|
@@ -841,6 +1080,15 @@ function useVoiceInput({
|
|
|
841
1080
|
});
|
|
842
1081
|
return dispose;
|
|
843
1082
|
}, [host, state]);
|
|
1083
|
+
useEffect(() => {
|
|
1084
|
+
if (!host?.onEnd) return;
|
|
1085
|
+
if (state !== "listening") return;
|
|
1086
|
+
return host.onEnd((error) => {
|
|
1087
|
+
if (!mounted.current) return;
|
|
1088
|
+
setPartial("");
|
|
1089
|
+
setState(error ? "error" : "idle");
|
|
1090
|
+
});
|
|
1091
|
+
}, [host, state]);
|
|
844
1092
|
return { state, partial, start, stop, cancel };
|
|
845
1093
|
}
|
|
846
1094
|
|
|
@@ -894,7 +1142,7 @@ function resolveExperience(requested, caps) {
|
|
|
894
1142
|
field: "input",
|
|
895
1143
|
from: input.join("+"),
|
|
896
1144
|
to: input.filter((mode) => mode !== "voice").join("+") || "text",
|
|
897
|
-
reason: 'input:"voice" needs a SpeechHost passed to <AppilotsChat speech={...} />. The SDK ships no speech engine of its own \u2014 see docs/
|
|
1145
|
+
reason: 'input:"voice" needs a SpeechHost passed to <AppilotsChat speech={...} />. The SDK ships no speech engine of its own \u2014 see https://docs.appilots.com/docs/guides/voice-input.'
|
|
898
1146
|
});
|
|
899
1147
|
input = input.filter((mode) => mode !== "voice");
|
|
900
1148
|
}
|
|
@@ -1290,9 +1538,13 @@ function isImageSource(value) {
|
|
|
1290
1538
|
return typeof value === "number" || /^https?:\/\//i.test(value.trim());
|
|
1291
1539
|
}
|
|
1292
1540
|
var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get("window");
|
|
1541
|
+
var A11Y_FOCUS_DELAY_MS = 500;
|
|
1293
1542
|
var CHAT_HORIZONTAL_PADDING = 16;
|
|
1294
1543
|
var BUBBLE_HORIZONTAL_PADDING = 14;
|
|
1295
1544
|
var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
|
|
1545
|
+
var MIN_TOUCH_TARGET2 = 44;
|
|
1546
|
+
var LARGE_TEXT_FONT_SCALE = 1.6;
|
|
1547
|
+
var INPUT_MAX_HEIGHT = 120;
|
|
1296
1548
|
function AppilotsChat(props) {
|
|
1297
1549
|
const { degraded } = useAppilotsContext();
|
|
1298
1550
|
if (degraded) return null;
|
|
@@ -1402,6 +1654,7 @@ function AppilotsChatInner({
|
|
|
1402
1654
|
return void 0;
|
|
1403
1655
|
}, [messages]);
|
|
1404
1656
|
const insets = useSafeAreaInsetsOrDefault();
|
|
1657
|
+
const { fontScale } = useWindowDimensions();
|
|
1405
1658
|
const [internalVisible, setInternalVisible] = useState(mode === "inline");
|
|
1406
1659
|
const [inputText, setInputText] = useState("");
|
|
1407
1660
|
const flatListRef = useRef(null);
|
|
@@ -1439,9 +1692,19 @@ function AppilotsChatInner({
|
|
|
1439
1692
|
},
|
|
1440
1693
|
[autoExecute]
|
|
1441
1694
|
);
|
|
1442
|
-
const
|
|
1695
|
+
const awaitingApproval = pendingActions.some((action) => requireApproval(action));
|
|
1696
|
+
const awaitingUser = awaitingApproval || escalation?.status === "pending" || escalation?.status === "active";
|
|
1443
1697
|
const busy = isLoading || executingActions.length > 0;
|
|
1698
|
+
const stillWorkingSeconds = useStillWorking(busy && !awaitingUser, strings.stillWorking);
|
|
1444
1699
|
const acting = busy && hasStartedActing;
|
|
1700
|
+
useChatAnnouncements({
|
|
1701
|
+
messages,
|
|
1702
|
+
actions: allActions,
|
|
1703
|
+
awaitingApproval,
|
|
1704
|
+
acting,
|
|
1705
|
+
locale: resolvedLocale,
|
|
1706
|
+
strings
|
|
1707
|
+
});
|
|
1445
1708
|
const hostModalOpen = useHostModalOpen(
|
|
1446
1709
|
usesPill(presence) && (busy || wantsSheet || unreadResult)
|
|
1447
1710
|
);
|
|
@@ -1516,6 +1779,19 @@ function AppilotsChatInner({
|
|
|
1516
1779
|
friction: 11
|
|
1517
1780
|
}).start();
|
|
1518
1781
|
}, [isVisible, slideAnim, mode]);
|
|
1782
|
+
const titleRef = useRef(null);
|
|
1783
|
+
const launcherRef = useRef(null);
|
|
1784
|
+
const pillRef = useRef(null);
|
|
1785
|
+
const wasVisibleRef = useRef(isVisible);
|
|
1786
|
+
useEffect(() => {
|
|
1787
|
+
if (mode === "inline" || wasVisibleRef.current === isVisible) return;
|
|
1788
|
+
wasVisibleRef.current = isVisible;
|
|
1789
|
+
const timer = setTimeout(() => {
|
|
1790
|
+
const target = isVisible ? titleRef.current : pillRef.current ?? launcherRef.current;
|
|
1791
|
+
if (target) AccessibilityInfo.sendAccessibilityEvent(target, "focus");
|
|
1792
|
+
}, A11Y_FOCUS_DELAY_MS);
|
|
1793
|
+
return () => clearTimeout(timer);
|
|
1794
|
+
}, [isVisible, mode]);
|
|
1519
1795
|
useEffect(() => {
|
|
1520
1796
|
if (messages.length > 0) {
|
|
1521
1797
|
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
|
|
@@ -1658,6 +1934,10 @@ function AppilotsChatInner({
|
|
|
1658
1934
|
},
|
|
1659
1935
|
[theme, lastAssistantMessageId, escalation, requestHuman, strings]
|
|
1660
1936
|
);
|
|
1937
|
+
const composerRef = useRef(null);
|
|
1938
|
+
const returnFocusToComposer = useCallback(() => {
|
|
1939
|
+
if (composerRef.current) AccessibilityInfo.sendAccessibilityEvent(composerRef.current, "focus");
|
|
1940
|
+
}, []);
|
|
1661
1941
|
const renderBreadcrumb = useCallback(
|
|
1662
1942
|
(actions) => /* @__PURE__ */ React8__default.createElement(
|
|
1663
1943
|
ActionBreadcrumb,
|
|
@@ -1674,7 +1954,8 @@ function AppilotsChatInner({
|
|
|
1674
1954
|
confirmDestructiveApprove: strings.confirmDestructiveApprove,
|
|
1675
1955
|
confirmApprove: strings.confirmApprove,
|
|
1676
1956
|
confirmCancel: strings.confirmCancel,
|
|
1677
|
-
confirmThisAction: strings.confirmThisAction
|
|
1957
|
+
confirmThisAction: strings.confirmThisAction,
|
|
1958
|
+
confirmExpired: strings.confirmExpired
|
|
1678
1959
|
},
|
|
1679
1960
|
palette: {
|
|
1680
1961
|
textSecondary: theme.colors.textSecondary,
|
|
@@ -1686,7 +1967,8 @@ function AppilotsChatInner({
|
|
|
1686
1967
|
},
|
|
1687
1968
|
requireApprovalFor: requireApproval,
|
|
1688
1969
|
onApprove: approveAction,
|
|
1689
|
-
onReject: rejectAction
|
|
1970
|
+
onReject: rejectAction,
|
|
1971
|
+
onConfirmCardGone: returnFocusToComposer
|
|
1690
1972
|
}
|
|
1691
1973
|
),
|
|
1692
1974
|
[
|
|
@@ -1703,7 +1985,8 @@ function AppilotsChatInner({
|
|
|
1703
1985
|
resolvedLocale,
|
|
1704
1986
|
requireApproval,
|
|
1705
1987
|
approveAction,
|
|
1706
|
-
rejectAction
|
|
1988
|
+
rejectAction,
|
|
1989
|
+
returnFocusToComposer
|
|
1707
1990
|
]
|
|
1708
1991
|
);
|
|
1709
1992
|
const resolvedHeaderTitle = resolvedTitle ?? t("chatTitle");
|
|
@@ -1746,6 +2029,7 @@ function AppilotsChatInner({
|
|
|
1746
2029
|
mode === "fullscreen" && styles5.chatContainerFullscreen,
|
|
1747
2030
|
mode === "sidebar" && styles5.chatContainerSidebar,
|
|
1748
2031
|
mode === "inline" && styles5.chatContainerInline,
|
|
2032
|
+
mode === "bubble" && fontScale >= LARGE_TEXT_FONT_SCALE && styles5.chatContainerFullscreen,
|
|
1749
2033
|
{
|
|
1750
2034
|
backgroundColor: theme.colors.background,
|
|
1751
2035
|
borderTopLeftRadius: theme.radii.lg,
|
|
@@ -1756,6 +2040,8 @@ function AppilotsChatInner({
|
|
|
1756
2040
|
/* @__PURE__ */ React8__default.createElement(View, { style: [styles5.header, { borderBottomColor: theme.colors.border }] }, /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerLeft }, renderAvatar(), /* @__PURE__ */ React8__default.createElement(
|
|
1757
2041
|
Text,
|
|
1758
2042
|
{
|
|
2043
|
+
ref: titleRef,
|
|
2044
|
+
accessibilityRole: "header",
|
|
1759
2045
|
style: [
|
|
1760
2046
|
styles5.headerTitle,
|
|
1761
2047
|
{
|
|
@@ -1882,8 +2168,7 @@ function AppilotsChatInner({
|
|
|
1882
2168
|
color: theme.colors.textSecondary,
|
|
1883
2169
|
fontFamily: theme.typography.fontFamily
|
|
1884
2170
|
}
|
|
1885
|
-
]
|
|
1886
|
-
numberOfLines: 2
|
|
2171
|
+
]
|
|
1887
2172
|
},
|
|
1888
2173
|
resolvedEmptySubtitle
|
|
1889
2174
|
), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.chipsContainer, testID: "assistant-suggested-prompts" }, suggestedPrompts.map((prompt) => /* @__PURE__ */ React8__default.createElement(
|
|
@@ -1912,8 +2197,7 @@ function AppilotsChatInner({
|
|
|
1912
2197
|
fontFamily: theme.typography.fontFamily,
|
|
1913
2198
|
fontSize: theme.typography.fontSizeSm
|
|
1914
2199
|
}
|
|
1915
|
-
]
|
|
1916
|
-
numberOfLines: 1
|
|
2200
|
+
]
|
|
1917
2201
|
},
|
|
1918
2202
|
prompt.text
|
|
1919
2203
|
)
|
|
@@ -1935,16 +2219,17 @@ function AppilotsChatInner({
|
|
|
1935
2219
|
{ color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
|
|
1936
2220
|
]
|
|
1937
2221
|
},
|
|
1938
|
-
strings[loadingStatusKey] ?? strings.thinking
|
|
2222
|
+
stillWorkingSeconds ? strings.stillWorking.replace("{seconds}", String(stillWorkingSeconds)) : strings[loadingStatusKey] ?? strings.thinking
|
|
1939
2223
|
)
|
|
1940
2224
|
) : null
|
|
1941
2225
|
}
|
|
1942
2226
|
),
|
|
1943
|
-
mission && !["completed", "cancelled"].includes(mission.status) && /* @__PURE__ */ React8__default.createElement(View, { style: { padding: 12, gap: 8 }, testID: "appilots-mission-controls" }, /* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text }, testID: "appilots-mission-progress" }, mission.progressText, mission.status === "paused" ? ` \xB7 ${strings.missionPaused}` : ""), /* @__PURE__ */ React8__default.createElement(View, { style:
|
|
2227
|
+
mission && !["completed", "cancelled"].includes(mission.status) && /* @__PURE__ */ React8__default.createElement(View, { style: { padding: 12, gap: 8 }, testID: "appilots-mission-controls" }, /* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text }, testID: "appilots-mission-progress" }, mission.progressText, mission.status === "paused" ? ` \xB7 ${strings.missionPaused}` : ""), /* @__PURE__ */ React8__default.createElement(View, { style: styles5.missionButtons }, mission.status === "running" ? /* @__PURE__ */ React8__default.createElement(
|
|
1944
2228
|
TouchableOpacity,
|
|
1945
2229
|
{
|
|
1946
2230
|
onPress: () => void pauseMission(),
|
|
1947
2231
|
testID: "appilots-mission-pause",
|
|
2232
|
+
style: styles5.missionButton,
|
|
1948
2233
|
accessibilityRole: "button"
|
|
1949
2234
|
},
|
|
1950
2235
|
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionPause)
|
|
@@ -1954,6 +2239,7 @@ function AppilotsChatInner({
|
|
|
1954
2239
|
onPress: () => void resumeMission(),
|
|
1955
2240
|
disabled: isLoading,
|
|
1956
2241
|
testID: "appilots-mission-resume",
|
|
2242
|
+
style: styles5.missionButton,
|
|
1957
2243
|
accessibilityRole: "button"
|
|
1958
2244
|
},
|
|
1959
2245
|
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionResume)
|
|
@@ -1962,6 +2248,7 @@ function AppilotsChatInner({
|
|
|
1962
2248
|
{
|
|
1963
2249
|
onPress: () => void cancelMission(),
|
|
1964
2250
|
testID: "appilots-mission-cancel",
|
|
2251
|
+
style: styles5.missionButton,
|
|
1965
2252
|
accessibilityRole: "button"
|
|
1966
2253
|
},
|
|
1967
2254
|
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionCancel)
|
|
@@ -1980,6 +2267,7 @@ function AppilotsChatInner({
|
|
|
1980
2267
|
/* @__PURE__ */ React8__default.createElement(
|
|
1981
2268
|
TextInput,
|
|
1982
2269
|
{
|
|
2270
|
+
ref: composerRef,
|
|
1983
2271
|
style: [
|
|
1984
2272
|
styles5.input,
|
|
1985
2273
|
{
|
|
@@ -1988,7 +2276,12 @@ function AppilotsChatInner({
|
|
|
1988
2276
|
borderRadius: theme.radii.md,
|
|
1989
2277
|
fontFamily: theme.typography.fontFamily,
|
|
1990
2278
|
fontSize: theme.typography.fontSizeBase,
|
|
1991
|
-
lineHeight: theme.typography.fontSizeBase * 1.35
|
|
2279
|
+
lineHeight: theme.typography.fontSizeBase * 1.35,
|
|
2280
|
+
// The 120pt cap is ~5 lines at default size and barely one at
|
|
2281
|
+
// iOS AX5, where even the placeholder was cut. It grows with
|
|
2282
|
+
// the text, but never past a quarter of the screen, so the
|
|
2283
|
+
// keyboard still leaves room for the transcript.
|
|
2284
|
+
maxHeight: Math.min(INPUT_MAX_HEIGHT * fontScale, SCREEN_HEIGHT * 0.25)
|
|
1992
2285
|
}
|
|
1993
2286
|
],
|
|
1994
2287
|
placeholder: resolvedPlaceholder,
|
|
@@ -2083,6 +2376,7 @@ function AppilotsChatInner({
|
|
|
2083
2376
|
TouchableOpacity,
|
|
2084
2377
|
{
|
|
2085
2378
|
...APPILOTS_SKIP_PROPS,
|
|
2379
|
+
ref: launcherRef,
|
|
2086
2380
|
onPress: openChat,
|
|
2087
2381
|
activeOpacity: 0.8,
|
|
2088
2382
|
accessibilityRole: "button",
|
|
@@ -2096,6 +2390,7 @@ function AppilotsChatInner({
|
|
|
2096
2390
|
TouchableOpacity,
|
|
2097
2391
|
{
|
|
2098
2392
|
...APPILOTS_SKIP_PROPS,
|
|
2393
|
+
ref: launcherRef,
|
|
2099
2394
|
style: [
|
|
2100
2395
|
styles5.fab,
|
|
2101
2396
|
fabPositionStyle,
|
|
@@ -2148,6 +2443,7 @@ function AppilotsChatInner({
|
|
|
2148
2443
|
},
|
|
2149
2444
|
strings: { expandA11y: strings.pillExpandA11y, stopA11y: strings.pillStopA11y },
|
|
2150
2445
|
onExpand: openChat,
|
|
2446
|
+
expandRef: pillRef,
|
|
2151
2447
|
onStop: busy ? cancelMessage : void 0
|
|
2152
2448
|
}
|
|
2153
2449
|
), /* @__PURE__ */ React8__default.createElement(SheetHost, { useModal: presence === "sheet", visible: isVisible, onRequestClose: closeChat }, /* @__PURE__ */ React8__default.createElement(
|
|
@@ -2155,6 +2451,7 @@ function AppilotsChatInner({
|
|
|
2155
2451
|
{
|
|
2156
2452
|
...APPILOTS_SKIP_PROPS,
|
|
2157
2453
|
pointerEvents: presence === "sheet" ? "auto" : "box-none",
|
|
2454
|
+
onAccessibilityEscape: closeChat,
|
|
2158
2455
|
style: [
|
|
2159
2456
|
mode === "fullscreen" ? styles5.modalContainerFullscreen : styles5.modalContainer,
|
|
2160
2457
|
mode === "sidebar" && styles5.modalContainerSidebar,
|
|
@@ -2205,6 +2502,7 @@ function SheetHost({
|
|
|
2205
2502
|
{
|
|
2206
2503
|
...APPILOTS_SKIP_PROPS,
|
|
2207
2504
|
pointerEvents: "box-none",
|
|
2505
|
+
accessibilityViewIsModal: true,
|
|
2208
2506
|
style: [StyleSheet.absoluteFill, styles5.sheetOverlay]
|
|
2209
2507
|
},
|
|
2210
2508
|
children
|
|
@@ -2303,8 +2601,13 @@ var styles5 = StyleSheet.create({
|
|
|
2303
2601
|
maxHeight: "100%",
|
|
2304
2602
|
flex: 1
|
|
2305
2603
|
},
|
|
2604
|
+
// Wraps instead of squeezing: at large text sizes the title alone is
|
|
2605
|
+
// wider than the row, and without the wrap it pushed Clear and ✕ off the
|
|
2606
|
+
// right edge — the chat could not be closed (measured at iOS AX5).
|
|
2306
2607
|
header: {
|
|
2307
2608
|
flexDirection: "row",
|
|
2609
|
+
flexWrap: "wrap",
|
|
2610
|
+
rowGap: 4,
|
|
2308
2611
|
alignItems: "center",
|
|
2309
2612
|
justifyContent: "space-between",
|
|
2310
2613
|
paddingHorizontal: 16,
|
|
@@ -2314,7 +2617,8 @@ var styles5 = StyleSheet.create({
|
|
|
2314
2617
|
headerLeft: {
|
|
2315
2618
|
flexDirection: "row",
|
|
2316
2619
|
alignItems: "center",
|
|
2317
|
-
gap: 8
|
|
2620
|
+
gap: 8,
|
|
2621
|
+
flexShrink: 1
|
|
2318
2622
|
},
|
|
2319
2623
|
headerDot: {
|
|
2320
2624
|
width: 8,
|
|
@@ -2333,24 +2637,30 @@ var styles5 = StyleSheet.create({
|
|
|
2333
2637
|
justifyContent: "center"
|
|
2334
2638
|
},
|
|
2335
2639
|
headerTitle: {
|
|
2336
|
-
fontWeight: "600"
|
|
2640
|
+
fontWeight: "600",
|
|
2641
|
+
flexShrink: 1
|
|
2337
2642
|
},
|
|
2338
2643
|
headerActions: {
|
|
2339
2644
|
flexDirection: "row",
|
|
2340
2645
|
alignItems: "center",
|
|
2341
|
-
gap:
|
|
2646
|
+
gap: 4,
|
|
2647
|
+
// Stays right-aligned when the header wraps it onto its own line.
|
|
2648
|
+
marginLeft: "auto"
|
|
2342
2649
|
},
|
|
2343
2650
|
headerButton: {
|
|
2651
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2652
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2344
2653
|
paddingHorizontal: 8,
|
|
2345
|
-
|
|
2654
|
+
alignItems: "center",
|
|
2655
|
+
justifyContent: "center"
|
|
2346
2656
|
},
|
|
2347
2657
|
headerButtonText: {
|
|
2348
2658
|
fontSize: 13
|
|
2349
2659
|
},
|
|
2350
2660
|
closeButton: {
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
borderRadius:
|
|
2661
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2662
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2663
|
+
borderRadius: MIN_TOUCH_TARGET2 / 2,
|
|
2354
2664
|
alignItems: "center",
|
|
2355
2665
|
justifyContent: "center"
|
|
2356
2666
|
},
|
|
@@ -2432,6 +2742,8 @@ var styles5 = StyleSheet.create({
|
|
|
2432
2742
|
maxWidth: 320
|
|
2433
2743
|
},
|
|
2434
2744
|
chip: {
|
|
2745
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2746
|
+
justifyContent: "center",
|
|
2435
2747
|
paddingHorizontal: 16,
|
|
2436
2748
|
paddingVertical: 10,
|
|
2437
2749
|
borderWidth: 1,
|
|
@@ -2494,16 +2806,16 @@ var styles5 = StyleSheet.create({
|
|
|
2494
2806
|
},
|
|
2495
2807
|
input: {
|
|
2496
2808
|
flex: 1,
|
|
2497
|
-
minHeight:
|
|
2498
|
-
maxHeight:
|
|
2809
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2810
|
+
maxHeight: INPUT_MAX_HEIGHT,
|
|
2499
2811
|
paddingHorizontal: 16,
|
|
2500
2812
|
paddingTop: Platform.OS === "ios" ? 9 : 8,
|
|
2501
2813
|
paddingBottom: Platform.OS === "ios" ? 9 : 8,
|
|
2502
2814
|
textAlignVertical: "top"
|
|
2503
2815
|
},
|
|
2504
2816
|
sendButton: {
|
|
2505
|
-
|
|
2506
|
-
|
|
2817
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2818
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2507
2819
|
alignItems: "center",
|
|
2508
2820
|
justifyContent: "center"
|
|
2509
2821
|
},
|
|
@@ -2512,6 +2824,15 @@ var styles5 = StyleSheet.create({
|
|
|
2512
2824
|
fontSize: 18,
|
|
2513
2825
|
fontWeight: "700"
|
|
2514
2826
|
},
|
|
2827
|
+
missionButtons: {
|
|
2828
|
+
flexDirection: "row",
|
|
2829
|
+
flexWrap: "wrap",
|
|
2830
|
+
columnGap: 12
|
|
2831
|
+
},
|
|
2832
|
+
missionButton: {
|
|
2833
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2834
|
+
justifyContent: "center"
|
|
2835
|
+
},
|
|
2515
2836
|
poweredByContainer: {
|
|
2516
2837
|
alignItems: "center",
|
|
2517
2838
|
paddingVertical: 4
|