@ateam-ai-mobile/ui 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Message, JobProgress, UIAction, TenantMembership } from '@ateam-ai-mobile/core';
2
+ import { Message, JobProgress, UIAction, AdasSession, TenantMembership } from '@ateam-ai-mobile/core';
3
3
  import * as react from 'react';
4
4
  import react__default from 'react';
5
5
  import { PluginSurfaceMeta, PlatformPluginManifest } from '@ateam-ai-mobile/plugin-runtime';
@@ -41,8 +41,11 @@ declare function TypingIndicator(): react_jsx_runtime.JSX.Element;
41
41
 
42
42
  interface Props$6 {
43
43
  progress: JobProgress;
44
+ /** Standalone placeholder (transparent bubble) — drop the top divider so it
45
+ * floats cleanly over the background. */
46
+ standalone?: boolean;
44
47
  }
45
- declare function JobProgressBar({ progress }: Props$6): react_jsx_runtime.JSX.Element;
48
+ declare function JobProgressBar({ progress, standalone }: Props$6): react_jsx_runtime.JSX.Element;
46
49
 
47
50
  interface Props$5 {
48
51
  columns: string[];
@@ -152,12 +155,15 @@ interface Props$1 {
152
155
  declare function WidgetWebView({ visible, title, bundleUrl, onClose }: Props$1): react_jsx_runtime.JSX.Element;
153
156
 
154
157
  interface TenantPickerProps {
155
- /** Called with the picked tenant. Host mints a JWT for it and re-inits. */
156
- onSelect: (tenant: TenantMembership) => void;
158
+ /** Called after a successful SDK-driven switch (host navigates/refreshes). */
159
+ onSwitched?: (session: AdasSession) => void;
160
+ /** Intercept the tap instead of switching — for fully custom host flows.
161
+ * When provided, the SDK does NOT call switchTenant(). */
162
+ onSelect?: (tenant: TenantMembership) => void;
157
163
  /** Highlight the active tenant. Defaults to the SDK config's tenant. */
158
164
  currentTenantId?: string;
159
165
  }
160
- declare function TenantPicker({ onSelect, currentTenantId }: TenantPickerProps): react_jsx_runtime.JSX.Element;
166
+ declare function TenantPicker({ onSwitched, onSelect, currentTenantId }: TenantPickerProps): react_jsx_runtime.JSX.Element;
161
167
 
162
168
  declare function Lightbox(): react_jsx_runtime.JSX.Element | null;
163
169
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Message, JobProgress, UIAction, TenantMembership } from '@ateam-ai-mobile/core';
2
+ import { Message, JobProgress, UIAction, AdasSession, TenantMembership } from '@ateam-ai-mobile/core';
3
3
  import * as react from 'react';
4
4
  import react__default from 'react';
5
5
  import { PluginSurfaceMeta, PlatformPluginManifest } from '@ateam-ai-mobile/plugin-runtime';
@@ -41,8 +41,11 @@ declare function TypingIndicator(): react_jsx_runtime.JSX.Element;
41
41
 
42
42
  interface Props$6 {
43
43
  progress: JobProgress;
44
+ /** Standalone placeholder (transparent bubble) — drop the top divider so it
45
+ * floats cleanly over the background. */
46
+ standalone?: boolean;
44
47
  }
45
- declare function JobProgressBar({ progress }: Props$6): react_jsx_runtime.JSX.Element;
48
+ declare function JobProgressBar({ progress, standalone }: Props$6): react_jsx_runtime.JSX.Element;
46
49
 
47
50
  interface Props$5 {
48
51
  columns: string[];
@@ -152,12 +155,15 @@ interface Props$1 {
152
155
  declare function WidgetWebView({ visible, title, bundleUrl, onClose }: Props$1): react_jsx_runtime.JSX.Element;
153
156
 
154
157
  interface TenantPickerProps {
155
- /** Called with the picked tenant. Host mints a JWT for it and re-inits. */
156
- onSelect: (tenant: TenantMembership) => void;
158
+ /** Called after a successful SDK-driven switch (host navigates/refreshes). */
159
+ onSwitched?: (session: AdasSession) => void;
160
+ /** Intercept the tap instead of switching — for fully custom host flows.
161
+ * When provided, the SDK does NOT call switchTenant(). */
162
+ onSelect?: (tenant: TenantMembership) => void;
157
163
  /** Highlight the active tenant. Defaults to the SDK config's tenant. */
158
164
  currentTenantId?: string;
159
165
  }
160
- declare function TenantPicker({ onSelect, currentTenantId }: TenantPickerProps): react_jsx_runtime.JSX.Element;
166
+ declare function TenantPicker({ onSwitched, onSelect, currentTenantId }: TenantPickerProps): react_jsx_runtime.JSX.Element;
161
167
 
162
168
  declare function Lightbox(): react_jsx_runtime.JSX.Element | null;
163
169
 
package/dist/index.js CHANGED
@@ -81,7 +81,7 @@ var WARM_RED = "#C15545";
81
81
  var WARM_RED_SOFT = "rgba(193, 85, 69, 0.14)";
82
82
  var WARM_AMBER = "#D49A4E";
83
83
  var WARM_AMBER_SOFT = "rgba(212, 154, 78, 0.16)";
84
- function JobProgressBar({ progress }) {
84
+ function JobProgressBar({ progress, standalone }) {
85
85
  const pulseAnim = (0, import_react.useRef)(new import_react_native.Animated.Value(0.5)).current;
86
86
  const [elapsed, setElapsed] = (0, import_react.useState)(0);
87
87
  const isRunning = progress.status === "running";
@@ -95,8 +95,10 @@ function JobProgressBar({ progress }) {
95
95
  }
96
96
  const anim = import_react_native.Animated.loop(
97
97
  import_react_native.Animated.sequence([
98
- import_react_native.Animated.timing(pulseAnim, { toValue: 1, duration: 800, useNativeDriver: true }),
99
- import_react_native.Animated.timing(pulseAnim, { toValue: 0.5, duration: 800, useNativeDriver: true })
98
+ // Gentle breath — a soft fade rather than a hard blink, so the running
99
+ // indicator recedes into the bubble instead of demanding attention.
100
+ import_react_native.Animated.timing(pulseAnim, { toValue: 0.55, duration: 1100, useNativeDriver: true }),
101
+ import_react_native.Animated.timing(pulseAnim, { toValue: 0.22, duration: 1100, useNativeDriver: true })
100
102
  ])
101
103
  );
102
104
  anim.start();
@@ -117,33 +119,37 @@ function JobProgressBar({ progress }) {
117
119
  const statusColor = isDone ? WARM_GREEN : isError ? WARM_RED : isPaused ? WARM_AMBER : import_core.ada.orange;
118
120
  const statusBg = isDone ? WARM_GREEN_SOFT : isError ? WARM_RED_SOFT : isPaused ? WARM_AMBER_SOFT : import_core.ada.orangeSoft;
119
121
  if (isDone || isError) {
120
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
122
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
121
123
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.dot, { backgroundColor: statusColor }] }),
122
124
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [styles.label, { color: statusColor }], children: isDone ? "Completed" : "Failed" })
123
125
  ] }) });
124
126
  }
125
127
  if (isPaused) {
126
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
128
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
127
129
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.dot, { backgroundColor: statusColor }] }),
128
130
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [styles.label, { color: statusColor }], children: "Waiting for your reply" })
129
131
  ] }) });
130
132
  }
131
- const elapsedStr = progress.chainStartedAt ? `${Math.floor(elapsed / 60)}:${String(elapsed % 60).padStart(2, "0")}` : null;
133
+ const elapsedStr = progress.chainStartedAt ? elapsed < 60 ? `${elapsed}s` : `${Math.floor(elapsed / 60)}m ${elapsed % 60}s` : null;
132
134
  const metaParts = [
133
135
  progress.iteration != null && progress.iteration > 0 ? `iter ${progress.iteration}` : null,
134
136
  elapsedStr
135
137
  ].filter(Boolean);
138
+ const labels = progress.humanLabels;
139
+ const label = (t) => t && labels?.[t] || t;
140
+ const headline = progress.humanStatus || label(progress.skillSlug) || "Processing...";
141
+ const showRawTool = !progress.humanStatus && !!progress.currentTool;
136
142
  const lp = progress.liveProgress;
137
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.container, children: [
143
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: [styles.container, standalone && styles.containerStandalone], children: [
138
144
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.row, children: [
139
145
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
146
  import_react_native.Animated.View,
141
147
  {
142
- style: [styles.dot, { backgroundColor: import_core.ada.orange, opacity: pulseAnim }]
148
+ style: [styles.dot, styles.dotRunning, { opacity: pulseAnim }]
143
149
  }
144
150
  ),
145
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.skill, numberOfLines: 1, children: progress.skillSlug || "Processing..." }),
146
- !!progress.currentTool && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.tool, numberOfLines: 1, children: ` \u2192 ${progress.currentTool}` }),
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.skill, numberOfLines: 1, children: headline }),
152
+ showRawTool && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.tool, numberOfLines: 1, children: ` \u2192 ${label(progress.currentTool)}` }),
147
153
  metaParts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.meta, numberOfLines: 1, children: ` \xB7 ${metaParts.join(" \xB7 ")}` })
148
154
  ] }),
149
155
  !!lp?.message && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles.liveProgressRow, children: [
@@ -156,10 +162,10 @@ function JobProgressBar({ progress }) {
156
162
  ] }),
157
163
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles.liveProgressMsg, numberOfLines: 1, children: lp.message })
158
164
  ] }),
159
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: [styles.progressTrack, { backgroundColor: statusBg }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.progressTrack, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
160
166
  import_react_native.Animated.View,
161
167
  {
162
- style: [styles.progressFill, { backgroundColor: import_core.ada.orange, opacity: pulseAnim }]
168
+ style: [styles.progressFill, { opacity: pulseAnim }]
163
169
  }
164
170
  ) })
165
171
  ] });
@@ -171,6 +177,12 @@ var styles = import_react_native.StyleSheet.create({
171
177
  borderTopWidth: 1,
172
178
  borderTopColor: import_core.ada.border
173
179
  },
180
+ // Standalone (transparent-bubble) placeholder — no divider/top spacing.
181
+ containerStandalone: {
182
+ marginTop: 0,
183
+ paddingTop: 0,
184
+ borderTopWidth: 0
185
+ },
174
186
  row: {
175
187
  flexDirection: "row",
176
188
  alignItems: "center",
@@ -178,21 +190,26 @@ var styles = import_react_native.StyleSheet.create({
178
190
  overflow: "hidden"
179
191
  },
180
192
  dot: {
181
- width: 7,
182
- height: 7,
183
- borderRadius: 4,
193
+ width: 6,
194
+ height: 6,
195
+ borderRadius: 3,
184
196
  marginRight: 6,
185
197
  flexShrink: 0
186
198
  },
199
+ // Running dot: soft orange, not the full-saturation accent.
200
+ dotRunning: {
201
+ backgroundColor: "rgba(255, 122, 40, 0.6)"
202
+ },
187
203
  label: {
188
204
  fontSize: import_core.fontSize.xs,
189
205
  fontWeight: "600"
190
206
  },
191
- // Running state text segments
207
+ // Running state text segments — muted so the indicator blends into the
208
+ // bubble rather than shouting in orange.
192
209
  skill: {
193
210
  fontSize: import_core.fontSize.xs,
194
- fontWeight: "600",
195
- color: import_core.ada.orange,
211
+ fontWeight: "500",
212
+ color: import_core.ada.inkSoft,
196
213
  flexShrink: 1
197
214
  },
198
215
  tool: {
@@ -218,19 +235,23 @@ var styles = import_react_native.StyleSheet.create({
218
235
  },
219
236
  liveProgressMsg: {
220
237
  fontSize: import_core.fontSize.xs,
221
- color: import_core.ada.orange,
238
+ color: import_core.ada.inkSoft,
222
239
  flex: 1
223
240
  },
224
241
  progressTrack: {
225
- height: 3,
226
- borderRadius: 2,
227
- marginTop: 6,
228
- overflow: "hidden"
242
+ height: 2,
243
+ borderRadius: 1,
244
+ marginTop: 8,
245
+ overflow: "hidden",
246
+ // Barely-there rail so the bar reads as a hint, not a status meter.
247
+ backgroundColor: "rgba(26, 20, 16, 0.05)"
229
248
  },
230
249
  progressFill: {
231
250
  height: "100%",
232
- width: "60%",
233
- borderRadius: 2
251
+ width: "55%",
252
+ borderRadius: 1,
253
+ // Muted orange — present but recessive.
254
+ backgroundColor: "rgba(255, 122, 40, 0.4)"
234
255
  }
235
256
  });
236
257
 
@@ -1140,6 +1161,8 @@ function MessageBubble({ message }) {
1140
1161
  const isUser = message.role === "user";
1141
1162
  const isSystem = message.role === "system";
1142
1163
  const isNotification = !isUser && message.kind === "notification";
1164
+ const st = message.jobProgress?.status;
1165
+ const isProgressOnly = !isUser && (st === "running" || st === "paused") && (!message.content?.trim() || message.content === "Working on it...");
1143
1166
  const [copied, setCopied] = (0, import_react7.useState)("");
1144
1167
  const showCopied = (0, import_react7.useCallback)((label) => {
1145
1168
  setCopied(label);
@@ -1175,7 +1198,8 @@ function MessageBubble({ message }) {
1175
1198
  styles6.bubble,
1176
1199
  isUser && styles6.bubbleUser,
1177
1200
  isSystem && styles6.bubbleSystem,
1178
- isNotification && styles6.bubbleNotification
1201
+ isNotification && styles6.bubbleNotification,
1202
+ isProgressOnly && styles6.bubbleProgress
1179
1203
  ],
1180
1204
  children: [
1181
1205
  isNotification && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native7.View, { style: styles6.notificationHeader, children: [
@@ -1208,12 +1232,15 @@ function MessageBubble({ message }) {
1208
1232
  isUser ? (
1209
1233
  // Hide the "See attachment" placeholder when the bubble already shows the photo.
1210
1234
  message.content && !(message.content === "See attachment" && message.attachments?.length) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { selectable: true, style: styles6.userText, children: message.content }) : null
1235
+ ) : isProgressOnly ? (
1236
+ // No "Working on it…" text — the indicator below is the whole message.
1237
+ null
1211
1238
  ) : renderAssistantContent(message.content, copyText),
1212
1239
  !!copied && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.View, { style: styles6.copiedBadge, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: styles6.copiedText, children: copied }) }),
1213
1240
  message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToolCallsBadge, { calls: message.toolCalls }),
1214
- message.jobProgress && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(JobProgressBar, { progress: message.jobProgress }),
1241
+ message.jobProgress && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(JobProgressBar, { progress: message.jobProgress, standalone: isProgressOnly }),
1215
1242
  !isUser && message.actions && message.actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(UIActionsRow, { actions: message.actions }),
1216
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles6.timeText, isUser && styles6.timeTextUser], children: formatTime(message.timestamp) })
1243
+ !isProgressOnly && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native7.Text, { style: [styles6.timeText, isUser && styles6.timeTextUser], children: formatTime(message.timestamp) })
1217
1244
  ]
1218
1245
  }
1219
1246
  ),
@@ -1336,6 +1363,14 @@ var styles6 = import_react_native7.StyleSheet.create({
1336
1363
  backgroundColor: import_core9.ada.userBubble,
1337
1364
  borderColor: "transparent"
1338
1365
  },
1366
+ // Live-chain placeholder: no fill, no border, tighter padding — the
1367
+ // indicator floats over the background instead of sitting in a bubble.
1368
+ bubbleProgress: {
1369
+ backgroundColor: "transparent",
1370
+ borderColor: "transparent",
1371
+ paddingHorizontal: 4,
1372
+ paddingVertical: 2
1373
+ },
1339
1374
  bubbleSystem: {
1340
1375
  backgroundColor: import_core9.ada.orangeSoft,
1341
1376
  borderColor: import_core9.ada.orange,
@@ -1918,9 +1953,10 @@ var import_react_native13 = require("react-native");
1918
1953
  var import_core15 = require("@ateam-ai-mobile/core");
1919
1954
  var import_jsx_runtime14 = require("react/jsx-runtime");
1920
1955
  var fontFam5 = import_react_native13.Platform.OS === "ios" ? "SF Pro Rounded" : void 0;
1921
- function TenantPicker({ onSelect, currentTenantId }) {
1956
+ function TenantPicker({ onSwitched, onSelect, currentTenantId }) {
1922
1957
  const [tenants, setTenants] = (0, import_react11.useState)(null);
1923
1958
  const [error, setError] = (0, import_react11.useState)(null);
1959
+ const [switching, setSwitching] = (0, import_react11.useState)(null);
1924
1960
  const active = currentTenantId ?? (0, import_core15.getTenant)();
1925
1961
  (0, import_react11.useEffect)(() => {
1926
1962
  let cancelled = false;
@@ -1933,6 +1969,23 @@ function TenantPicker({ onSelect, currentTenantId }) {
1933
1969
  cancelled = true;
1934
1970
  };
1935
1971
  }, []);
1972
+ const handlePress = async (t) => {
1973
+ if (t.id === active || switching) return;
1974
+ if (onSelect) {
1975
+ onSelect(t);
1976
+ return;
1977
+ }
1978
+ setError(null);
1979
+ setSwitching(t.id);
1980
+ try {
1981
+ const session = await (0, import_core15.switchTenant)(t.id);
1982
+ onSwitched?.(session);
1983
+ } catch (e) {
1984
+ setError(e?.message || "Could not switch team");
1985
+ } finally {
1986
+ setSwitching(null);
1987
+ }
1988
+ };
1936
1989
  if (error) return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.error, children: error });
1937
1990
  if (!tenants) {
1938
1991
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.View, { style: styles12.loading, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.ActivityIndicator, { color: import_core15.ada.orange }) });
@@ -1940,12 +1993,14 @@ function TenantPicker({ onSelect, currentTenantId }) {
1940
1993
  if (tenants.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.empty, children: "No teams found for this account." });
1941
1994
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.View, { style: styles12.list, children: tenants.map((t) => {
1942
1995
  const isActive = t.id === active;
1996
+ const isSwitching = switching === t.id;
1943
1997
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1944
1998
  import_react_native13.Pressable,
1945
1999
  {
1946
2000
  accessibilityRole: "button",
1947
2001
  accessibilityLabel: `Team ${t.name}${isActive ? ", current" : ""}`,
1948
- onPress: () => onSelect(t),
2002
+ disabled: !!switching,
2003
+ onPress: () => handlePress(t),
1949
2004
  style: [styles12.row, isActive && styles12.rowActive],
1950
2005
  children: [
1951
2006
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.View, { style: styles12.dot }),
@@ -1953,7 +2008,7 @@ function TenantPicker({ onSelect, currentTenantId }) {
1953
2008
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.name, children: t.name }),
1954
2009
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.slug, children: t.id })
1955
2010
  ] }),
1956
- isActive && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.check, children: "\u2713" })
2011
+ isSwitching ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.ActivityIndicator, { color: import_core15.ada.orange }) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.Text, { style: styles12.check, children: "\u2713" }) : null
1957
2012
  ]
1958
2013
  },
1959
2014
  t.id