@ateam-ai-mobile/ui 0.1.1 → 0.1.2
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 +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +24 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/TenantPicker.tsx +36 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ateam-ai-mobile/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Prebuilt ADAS chat experience for React Native \u2014 full-screen chat, chips, widget views. Built on @ateam-ai-mobile/core + @ateam-ai-mobile/plugin-runtime.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"build": "tsup"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@ateam-ai-mobile/core": "0.1.
|
|
13
|
-
"@ateam-ai-mobile/plugin-runtime": "0.1.
|
|
12
|
+
"@ateam-ai-mobile/core": "0.1.2",
|
|
13
|
+
"@ateam-ai-mobile/plugin-runtime": "0.1.2",
|
|
14
14
|
"zustand": "^5.0.0"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
package/src/TenantPicker.tsx
CHANGED
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TenantPicker —
|
|
2
|
+
* TenantPicker — prebuilt team switcher, fully SDK-driven.
|
|
3
3
|
*
|
|
4
|
-
* Lists the user's REAL
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Lists the user's REAL memberships via core's listMyTenants() and, on tap,
|
|
5
|
+
* re-scopes the whole session with core's switchTenant() (which mints the new
|
|
6
|
+
* tenant JWT, persists it through config.onSession, and reconnects chat). The
|
|
7
|
+
* host only reacts via onSwitched (e.g. navigate home). Single-tenant hosts
|
|
8
|
+
* simply never render it.
|
|
9
|
+
*
|
|
10
|
+
* For custom flows, pass `onSelect` to intercept the tap instead of switching.
|
|
8
11
|
*/
|
|
9
12
|
import { useEffect, useState } from 'react';
|
|
10
13
|
import { View, Text, Pressable, ActivityIndicator, StyleSheet, Platform } from 'react-native';
|
|
11
|
-
import { ada, fontSize, borderRadius, listMyTenants, getTenant } from '@ateam-ai-mobile/core';
|
|
12
|
-
import type { TenantMembership } from '@ateam-ai-mobile/core';
|
|
14
|
+
import { ada, fontSize, borderRadius, listMyTenants, switchTenant, getTenant } from '@ateam-ai-mobile/core';
|
|
15
|
+
import type { TenantMembership, AdasSession } from '@ateam-ai-mobile/core';
|
|
13
16
|
|
|
14
17
|
const fontFam = Platform.OS === 'ios' ? 'SF Pro Rounded' : undefined;
|
|
15
18
|
|
|
16
19
|
export interface TenantPickerProps {
|
|
17
|
-
/** Called
|
|
18
|
-
|
|
20
|
+
/** Called after a successful SDK-driven switch (host navigates/refreshes). */
|
|
21
|
+
onSwitched?: (session: AdasSession) => void;
|
|
22
|
+
/** Intercept the tap instead of switching — for fully custom host flows.
|
|
23
|
+
* When provided, the SDK does NOT call switchTenant(). */
|
|
24
|
+
onSelect?: (tenant: TenantMembership) => void;
|
|
19
25
|
/** Highlight the active tenant. Defaults to the SDK config's tenant. */
|
|
20
26
|
currentTenantId?: string;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
|
-
export default function TenantPicker({ onSelect, currentTenantId }: TenantPickerProps) {
|
|
29
|
+
export default function TenantPicker({ onSwitched, onSelect, currentTenantId }: TenantPickerProps) {
|
|
24
30
|
const [tenants, setTenants] = useState<TenantMembership[] | null>(null);
|
|
25
31
|
const [error, setError] = useState<string | null>(null);
|
|
32
|
+
const [switching, setSwitching] = useState<string | null>(null);
|
|
26
33
|
const active = currentTenantId ?? getTenant();
|
|
27
34
|
|
|
28
35
|
useEffect(() => {
|
|
@@ -33,6 +40,21 @@ export default function TenantPicker({ onSelect, currentTenantId }: TenantPicker
|
|
|
33
40
|
return () => { cancelled = true; };
|
|
34
41
|
}, []);
|
|
35
42
|
|
|
43
|
+
const handlePress = async (t: TenantMembership) => {
|
|
44
|
+
if (t.id === active || switching) return;
|
|
45
|
+
if (onSelect) { onSelect(t); return; }
|
|
46
|
+
setError(null);
|
|
47
|
+
setSwitching(t.id);
|
|
48
|
+
try {
|
|
49
|
+
const session = await switchTenant(t.id);
|
|
50
|
+
onSwitched?.(session);
|
|
51
|
+
} catch (e: any) {
|
|
52
|
+
setError(e?.message || 'Could not switch team');
|
|
53
|
+
} finally {
|
|
54
|
+
setSwitching(null);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
36
58
|
if (error) return <Text style={styles.error}>{error}</Text>;
|
|
37
59
|
if (!tenants) {
|
|
38
60
|
return (
|
|
@@ -47,12 +69,14 @@ export default function TenantPicker({ onSelect, currentTenantId }: TenantPicker
|
|
|
47
69
|
<View style={styles.list}>
|
|
48
70
|
{tenants.map(t => {
|
|
49
71
|
const isActive = t.id === active;
|
|
72
|
+
const isSwitching = switching === t.id;
|
|
50
73
|
return (
|
|
51
74
|
<Pressable
|
|
52
75
|
key={t.id}
|
|
53
76
|
accessibilityRole="button"
|
|
54
77
|
accessibilityLabel={`Team ${t.name}${isActive ? ', current' : ''}`}
|
|
55
|
-
|
|
78
|
+
disabled={!!switching}
|
|
79
|
+
onPress={() => handlePress(t)}
|
|
56
80
|
style={[styles.row, isActive && styles.rowActive]}
|
|
57
81
|
>
|
|
58
82
|
<View style={styles.dot} />
|
|
@@ -60,7 +84,7 @@ export default function TenantPicker({ onSelect, currentTenantId }: TenantPicker
|
|
|
60
84
|
<Text style={styles.name}>{t.name}</Text>
|
|
61
85
|
<Text style={styles.slug}>{t.id}</Text>
|
|
62
86
|
</View>
|
|
63
|
-
{isActive
|
|
87
|
+
{isSwitching ? <ActivityIndicator color={ada.orange} /> : isActive ? <Text style={styles.check}>✓</Text> : null}
|
|
64
88
|
</Pressable>
|
|
65
89
|
);
|
|
66
90
|
})}
|