@basictech/react 0.12.0-beta.2 → 0.12.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1046,6 +1046,120 @@ function useProjectProfile(enabled = true) {
1046
1046
  return useProjectProfileFor(useRequiredClient(), enabled);
1047
1047
  }
1048
1048
 
1049
+ // src/hooks/invites.ts
1050
+ import { useCallback as useCallback6, useRef as useRef3 } from "react";
1051
+ import {
1052
+ BasicError as BasicError6
1053
+ } from "@basictech/core";
1054
+ function useShareInvitesFor(client, enabled = true) {
1055
+ const snapshot = useClientSnapshot(client);
1056
+ const accountId = snapshot.activeAccount?.id;
1057
+ const currentClient = useRef3(client);
1058
+ currentClient.current = client;
1059
+ const gate = useSignInGate(snapshot);
1060
+ const canLoad = enabled && snapshot.isReady && snapshot.isSignedIn;
1061
+ const result = useAsyncResult(
1062
+ async () => {
1063
+ try {
1064
+ return {
1065
+ client,
1066
+ accountId,
1067
+ data: await client.shares.listInvites(),
1068
+ error: null
1069
+ };
1070
+ } catch (error) {
1071
+ return {
1072
+ client,
1073
+ accountId,
1074
+ data: [],
1075
+ error: toBasicError(error)
1076
+ };
1077
+ }
1078
+ },
1079
+ null,
1080
+ canLoad,
1081
+ !enabled || snapshot.isReady,
1082
+ [client, accountId]
1083
+ );
1084
+ const current = result.data?.client === client && result.data.accountId === accountId ? result.data : null;
1085
+ const resolveContactHandle = useCallback6(
1086
+ (did) => client.shares.resolveContactHandle(did),
1087
+ [client]
1088
+ );
1089
+ const checkAccount = () => {
1090
+ if (currentClient.current !== client || client.getSnapshot().activeAccount?.id !== accountId)
1091
+ throw new BasicError6("ACCOUNT_CHANGED");
1092
+ };
1093
+ async function run(action, refresh = true) {
1094
+ checkAccount();
1095
+ try {
1096
+ const value = await action();
1097
+ checkAccount();
1098
+ return value;
1099
+ } catch (error) {
1100
+ checkAccount();
1101
+ throw error;
1102
+ } finally {
1103
+ if (refresh && currentClient.current === client && client.getSnapshot().activeAccount?.id === accountId)
1104
+ result.refresh();
1105
+ }
1106
+ }
1107
+ return {
1108
+ data: canLoad ? current?.data ?? [] : [],
1109
+ isLoading: enabled && (!snapshot.isReady || canLoad && (result.isLoading || !current)),
1110
+ error: enabled ? gate ?? (canLoad ? current?.error ?? null : null) : null,
1111
+ refresh: result.refresh,
1112
+ get: (id) => run(() => client.shares.getInvite(id), false),
1113
+ accept: (id) => run(() => client.shares.acceptInvite(id)),
1114
+ decline: (id) => run(() => client.shares.declineInvite(id)),
1115
+ delete: (id) => run(() => client.shares.deleteInvite(id)),
1116
+ resolveContactHandle
1117
+ };
1118
+ }
1119
+ function useShareInvites(enabled = true) {
1120
+ return useShareInvitesFor(useRequiredClient(), enabled);
1121
+ }
1122
+
1123
+ // src/hooks/recipients.ts
1124
+ function useShareRecipientsFor(client, dids) {
1125
+ const unique = [...new Set(dids)];
1126
+ const key = JSON.stringify(unique);
1127
+ const result = useAsyncResult(
1128
+ async () => {
1129
+ const handles = await Promise.allSettled(
1130
+ unique.map((did) => client.shares.resolveContactHandle(did))
1131
+ );
1132
+ const failed = handles.find((handle) => handle.status === "rejected");
1133
+ return {
1134
+ client,
1135
+ key,
1136
+ data: unique.map((did, index) => {
1137
+ const handle = handles[index];
1138
+ return {
1139
+ did,
1140
+ handle: handle.status === "fulfilled" ? handle.value : null
1141
+ };
1142
+ }),
1143
+ error: failed ? toBasicError(failed.reason) : null
1144
+ };
1145
+ },
1146
+ null,
1147
+ unique.length > 0,
1148
+ true,
1149
+ [client, key]
1150
+ );
1151
+ const current = result.data?.client === client && result.data.key === key ? result.data : null;
1152
+ return {
1153
+ data: current?.data ?? unique.map((did) => ({ did, handle: null })),
1154
+ isLoading: unique.length > 0 && (result.isLoading || !current),
1155
+ error: result.isLoading ? null : current?.error ?? null,
1156
+ refresh: result.refresh
1157
+ };
1158
+ }
1159
+ function useShareRecipients(dids) {
1160
+ return useShareRecipientsFor(useRequiredClient(), dids);
1161
+ }
1162
+
1049
1163
  // src/create-basic.tsx
1050
1164
  import { jsx as jsx2 } from "react/jsx-runtime";
1051
1165
  function createBasic(config) {
@@ -1078,7 +1192,9 @@ function createBasic(config) {
1078
1192
  useFiles: (query = {}, options = {}) => useFilesFor(useBound(), query, options),
1079
1193
  useStorageInfo: () => useStorageInfoFor(useBound()),
1080
1194
  useMounts: (query = {}) => useMountsFor(useBound(), query),
1081
- useOutgoingShares: () => useOutgoingSharesFor(useBound())
1195
+ useOutgoingShares: () => useOutgoingSharesFor(useBound()),
1196
+ useShareInvites: (enabled) => useShareInvitesFor(useBound(), enabled),
1197
+ useShareRecipients: (dids) => useShareRecipientsFor(useBound(), dids)
1082
1198
  };
1083
1199
  }
1084
1200
 
@@ -1090,19 +1206,140 @@ import {
1090
1206
  isValidElement,
1091
1207
  useContext as useContext3,
1092
1208
  useEffect as useEffect4,
1093
- useRef as useRef3,
1209
+ useRef as useRef4,
1094
1210
  useState as useState4
1095
1211
  } from "react";
1096
1212
  import { Avatar } from "@base-ui/react/avatar";
1097
1213
  import { Dialog } from "@base-ui/react/dialog";
1098
1214
  import { Menu } from "@base-ui/react/menu";
1099
1215
  import { Tabs } from "@base-ui/react/tabs";
1100
- import { BasicError as BasicError6 } from "@basictech/core";
1101
- import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
1216
+ import { BasicError as BasicError7 } from "@basictech/core";
1217
+
1218
+ // src/avatar-marble.tsx
1219
+ import { useId } from "react";
1220
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1221
+ var ELEMENTS = 3;
1222
+ var SIZE = 80;
1223
+ var COLORS = ["#92A1C6", "#146A7C", "#F0AB3D", "#C271B4", "#C20D90"];
1224
+ function hashCode(value) {
1225
+ let hash = 0;
1226
+ for (let index = 0; index < value.length; index += 1) {
1227
+ hash = (hash << 5) - hash + value.charCodeAt(index);
1228
+ hash &= hash;
1229
+ }
1230
+ return Math.abs(hash);
1231
+ }
1232
+ function getDigit(value, position) {
1233
+ return Math.floor(value / 10 ** position % 10);
1234
+ }
1235
+ function getUnit(value, range, position) {
1236
+ const unit = value % range;
1237
+ return position && getDigit(value, position) % 2 === 0 ? -unit : unit;
1238
+ }
1239
+ function generateProperties(seed) {
1240
+ const value = hashCode(seed);
1241
+ return Array.from({ length: ELEMENTS }, (_, index) => ({
1242
+ color: COLORS[(value + index) % COLORS.length],
1243
+ translateX: getUnit(value * (index + 1), SIZE / 10, 1),
1244
+ translateY: getUnit(value * (index + 1), SIZE / 10, 2),
1245
+ scale: 1.2 + getUnit(value * (index + 1), SIZE / 20) / 10,
1246
+ rotate: getUnit(value * (index + 1), 360, 1)
1247
+ }));
1248
+ }
1249
+ function MarbleAvatar({ seed }) {
1250
+ const properties = generateProperties(seed);
1251
+ const instanceId = useId().replaceAll(":", "");
1252
+ const maskId = `basic-avatar-mask-${instanceId}`;
1253
+ const filterId = `basic-avatar-filter-${instanceId}`;
1254
+ return /* @__PURE__ */ jsxs(
1255
+ "svg",
1256
+ {
1257
+ viewBox: `0 0 ${SIZE} ${SIZE}`,
1258
+ width: "100%",
1259
+ height: "100%",
1260
+ fill: "none",
1261
+ xmlns: "http://www.w3.org/2000/svg",
1262
+ "aria-hidden": "true",
1263
+ focusable: "false",
1264
+ children: [
1265
+ /* @__PURE__ */ jsx3(
1266
+ "mask",
1267
+ {
1268
+ id: maskId,
1269
+ maskUnits: "userSpaceOnUse",
1270
+ x: "0",
1271
+ y: "0",
1272
+ width: SIZE,
1273
+ height: SIZE,
1274
+ children: /* @__PURE__ */ jsx3("rect", { width: SIZE, height: SIZE, rx: SIZE * 2, fill: "#FFFFFF" })
1275
+ }
1276
+ ),
1277
+ /* @__PURE__ */ jsxs("g", { mask: `url(#${maskId})`, children: [
1278
+ /* @__PURE__ */ jsx3("rect", { width: SIZE, height: SIZE, fill: properties[0].color }),
1279
+ /* @__PURE__ */ jsx3(
1280
+ "path",
1281
+ {
1282
+ filter: `url(#${filterId})`,
1283
+ d: "M32.414 59.35L50.376 70.5H72.5v-71H33.728L26.5 13.381l19.057 27.08L32.414 59.35z",
1284
+ fill: properties[1].color,
1285
+ transform: `translate(${properties[1].translateX} ${properties[1].translateY}) rotate(${properties[1].rotate} ${SIZE / 2} ${SIZE / 2}) scale(${properties[2].scale})`
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsx3(
1289
+ "path",
1290
+ {
1291
+ filter: `url(#${filterId})`,
1292
+ style: { mixBlendMode: "overlay" },
1293
+ d: "M22.216 24L0 46.75l14.108 38.129L78 86l-3.081-59.276-22.378 4.005 12.972 20.186-23.35 27.395L22.215 24z",
1294
+ fill: properties[2].color,
1295
+ transform: `translate(${properties[2].translateX} ${properties[2].translateY}) rotate(${properties[2].rotate} ${SIZE / 2} ${SIZE / 2}) scale(${properties[2].scale})`
1296
+ }
1297
+ )
1298
+ ] }),
1299
+ /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs(
1300
+ "filter",
1301
+ {
1302
+ id: filterId,
1303
+ filterUnits: "userSpaceOnUse",
1304
+ colorInterpolationFilters: "sRGB",
1305
+ children: [
1306
+ /* @__PURE__ */ jsx3("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
1307
+ /* @__PURE__ */ jsx3(
1308
+ "feBlend",
1309
+ {
1310
+ in: "SourceGraphic",
1311
+ in2: "BackgroundImageFix",
1312
+ result: "shape"
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ jsx3("feGaussianBlur", { stdDeviation: "7", result: "effect1_foregroundBlur" })
1316
+ ]
1317
+ }
1318
+ ) })
1319
+ ]
1320
+ }
1321
+ );
1322
+ }
1323
+
1324
+ // src/components.tsx
1325
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1102
1326
  var AppearanceContext = createContext2({});
1327
+ function accentText(accent) {
1328
+ if (!/^#([\da-f]{3}|[\da-f]{6})$/i.test(accent)) return "#fff";
1329
+ const hex = accent.length === 4 ? accent.slice(1).split("").map((digit) => digit + digit).join("") : accent.slice(1);
1330
+ const [red, green, blue] = [0, 2, 4].map((offset) => {
1331
+ const channel = parseInt(hex.slice(offset, offset + 2), 16) / 255;
1332
+ return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
1333
+ });
1334
+ return 0.2126 * red + 0.7152 * green + 0.0722 * blue > 0.179 ? "#000" : "#fff";
1335
+ }
1103
1336
  function appearanceStyle(appearance) {
1104
1337
  return {
1105
- ...appearance.accent ? { "--basic-accent": appearance.accent } : {},
1338
+ ...appearance.base ? { "--basic-surface": appearance.base } : {},
1339
+ ...appearance.accent ? {
1340
+ "--basic-accent": appearance.accent,
1341
+ "--basic-accent-text": accentText(appearance.accent)
1342
+ } : {},
1106
1343
  ...appearance.radius ? { "--basic-radius": appearance.radius } : {}
1107
1344
  };
1108
1345
  }
@@ -1112,7 +1349,7 @@ function BasicUIProvider({
1112
1349
  }) {
1113
1350
  const parent = useContext3(AppearanceContext);
1114
1351
  const value = { ...parent, ...appearance };
1115
- return /* @__PURE__ */ jsx3(AppearanceContext.Provider, { value, children: /* @__PURE__ */ jsx3(
1352
+ return /* @__PURE__ */ jsx4(AppearanceContext.Provider, { value, children: /* @__PURE__ */ jsx4(
1116
1353
  "div",
1117
1354
  {
1118
1355
  className: "basic-ui",
@@ -1133,7 +1370,7 @@ function useAppearanceProps() {
1133
1370
  }
1134
1371
  var BasicButton = forwardRef(
1135
1372
  function BasicButton2({ variant = "outline", className = "", type = "button", ...props }, ref) {
1136
- return /* @__PURE__ */ jsx3(
1373
+ return /* @__PURE__ */ jsx4(
1137
1374
  "button",
1138
1375
  {
1139
1376
  ...props,
@@ -1148,8 +1385,8 @@ var BasicButton = forwardRef(
1148
1385
  function useAction() {
1149
1386
  const [pending, setPending] = useState4(false);
1150
1387
  const [error, setError] = useState4(null);
1151
- const busy = useRef3(false);
1152
- const mounted = useRef3(true);
1388
+ const busy = useRef4(false);
1389
+ const mounted = useRef4(true);
1153
1390
  useEffect4(() => {
1154
1391
  mounted.current = true;
1155
1392
  return () => {
@@ -1166,7 +1403,7 @@ function useAction() {
1166
1403
  } catch (cause) {
1167
1404
  if (mounted.current)
1168
1405
  setError(
1169
- cause instanceof BasicError6 && cause.code === "REDIRECT_URI_NOT_REGISTERED" ? "Sign-in is unavailable on this URL. Ask the app owner to register its callback URL in project settings." : cause instanceof Error ? cause.message : "The action failed. Please try again."
1406
+ cause instanceof BasicError7 && cause.code === "REDIRECT_URI_NOT_REGISTERED" ? "Sign-in is unavailable on this URL. Ask the app owner to register its callback URL in project settings." : cause instanceof Error ? cause.message : "The action failed. Please try again."
1170
1407
  );
1171
1408
  } finally {
1172
1409
  busy.current = false;
@@ -1188,8 +1425,8 @@ function AuthButton({
1188
1425
  const auth = supplied ?? live;
1189
1426
  const action = useAction();
1190
1427
  const expired = auth.status === "expired";
1191
- return /* @__PURE__ */ jsxs("span", { className: "basic-action", children: [
1192
- /* @__PURE__ */ jsx3(
1428
+ return /* @__PURE__ */ jsxs2("span", { className: "basic-action", children: [
1429
+ /* @__PURE__ */ jsx4(
1193
1430
  BasicButton,
1194
1431
  {
1195
1432
  ...props,
@@ -1205,29 +1442,44 @@ function AuthButton({
1205
1442
  children: action.pending ? "Please wait\u2026" : children ?? (signOut ? "Sign out" : expired ? "Sign in again" : "Sign in")
1206
1443
  }
1207
1444
  ),
1208
- /* @__PURE__ */ jsx3(ActionError, { error: action.error, onClose: action.clearError })
1445
+ /* @__PURE__ */ jsx4(ActionError, { error: action.error, onClose: action.clearError })
1209
1446
  ] });
1210
1447
  }
1211
1448
  function SignInButton(props) {
1212
- return /* @__PURE__ */ jsx3(AuthButton, { ...props });
1449
+ return /* @__PURE__ */ jsx4(AuthButton, { ...props });
1213
1450
  }
1214
1451
  function SignOutButton(props) {
1215
- return /* @__PURE__ */ jsx3(AuthButton, { ...props, signOut: true });
1452
+ return /* @__PURE__ */ jsx4(AuthButton, { ...props, signOut: true });
1453
+ }
1454
+ var ANONYMOUS_ACCOUNT_NAME = "Local User";
1455
+ function accountName(profile, emptyFallback = "Guest") {
1456
+ if (!profile) return emptyFallback;
1457
+ return profile.name || (profile.kind === "anon" ? ANONYMOUS_ACCOUNT_NAME : displayHandle(profile.handle) || profile.email || "Account");
1458
+ }
1459
+ function avatarSeed(profile) {
1460
+ if (!profile) return "guest";
1461
+ return profile.did || profile.id && `account:${profile.id}` || profile.handle || profile.email || profile.name || "guest";
1216
1462
  }
1217
1463
  function UserAvatar({
1218
1464
  accounts,
1219
1465
  auth,
1220
1466
  projectProfile,
1467
+ invites,
1468
+ showInvites,
1221
1469
  allowAddAccount,
1470
+ menuItems,
1222
1471
  ...avatarProps
1223
1472
  }) {
1224
- return /* @__PURE__ */ jsx3(
1473
+ return /* @__PURE__ */ jsx4(
1225
1474
  UserMenu,
1226
1475
  {
1227
1476
  accounts,
1228
1477
  auth,
1229
1478
  projectProfile,
1479
+ invites,
1480
+ showInvites,
1230
1481
  allowAddAccount,
1482
+ menuItems,
1231
1483
  sync: avatarProps.sync,
1232
1484
  showSyncBadge: avatarProps.showSyncBadge,
1233
1485
  avatarProps
@@ -1239,25 +1491,34 @@ function AccountAvatar({
1239
1491
  size = 32,
1240
1492
  showSyncBadge,
1241
1493
  sync,
1242
- className = "",
1243
- style,
1244
1494
  ...props
1245
1495
  }) {
1246
1496
  const accounts = useAccounts();
1247
1497
  const client = useRequiredClient();
1248
1498
  const profile = supplied === void 0 ? accounts.activeAccount : supplied;
1249
- const name = profile?.name || (profile?.kind === "anon" ? "Local account" : profile?.handle || profile?.email || "Guest");
1250
- const initials = name.trim().split(/\s+/).slice(0, 2).map((part) => Array.from(part)[0]).join("").toUpperCase();
1251
- const avatar = /* @__PURE__ */ jsxs(
1499
+ const avatar = /* @__PURE__ */ jsx4(ProfileAvatar, { ...props, profile, size });
1500
+ return showSyncBadge ?? client.mode === "sync" ? /* @__PURE__ */ jsxs2("span", { className: "basic-avatar-container", children: [
1501
+ avatar,
1502
+ /* @__PURE__ */ jsx4(SyncStatus, { sync, className: "basic-avatar-sync" })
1503
+ ] }) : avatar;
1504
+ }
1505
+ function ProfileAvatar({
1506
+ profile,
1507
+ size = 32,
1508
+ className = "",
1509
+ style,
1510
+ ...props
1511
+ }) {
1512
+ return /* @__PURE__ */ jsxs2(
1252
1513
  Avatar.Root,
1253
1514
  {
1254
1515
  ...props,
1255
1516
  className: `basic-avatar ${className}`,
1256
1517
  style: { width: size, height: size, ...style },
1257
1518
  role: "img",
1258
- "aria-label": props["aria-label"] ?? name,
1519
+ "aria-label": props["aria-label"] ?? accountName(profile),
1259
1520
  children: [
1260
- profile?.picture && /* @__PURE__ */ jsx3(
1521
+ profile?.picture && /* @__PURE__ */ jsx4(
1261
1522
  Avatar.Image,
1262
1523
  {
1263
1524
  src: profile.picture,
@@ -1266,14 +1527,100 @@ function AccountAvatar({
1266
1527
  referrerPolicy: "no-referrer"
1267
1528
  }
1268
1529
  ),
1269
- /* @__PURE__ */ jsx3(Avatar.Fallback, { className: "basic-avatar-fallback", children: initials || "?" })
1530
+ /* @__PURE__ */ jsx4(Avatar.Fallback, { className: "basic-avatar-fallback", children: /* @__PURE__ */ jsx4(MarbleAvatar, { seed: avatarSeed(profile) }) })
1531
+ ]
1532
+ }
1533
+ );
1534
+ }
1535
+ function ShareRecipientAvatar({
1536
+ recipient,
1537
+ ...props
1538
+ }) {
1539
+ return /* @__PURE__ */ jsx4(
1540
+ ProfileAvatar,
1541
+ {
1542
+ title: displayHandle(recipient.handle) || recipient.name || recipient.did,
1543
+ ...props,
1544
+ profile: {
1545
+ ...recipient,
1546
+ name: recipient.name || displayHandle(recipient.handle) || recipient.did,
1547
+ kind: "account"
1548
+ }
1549
+ }
1550
+ );
1551
+ }
1552
+ function ShareRecipientLabel({
1553
+ recipient,
1554
+ size = 24,
1555
+ className = "",
1556
+ ...props
1557
+ }) {
1558
+ const label = displayHandle(recipient.handle) || recipient.name || "Unknown user";
1559
+ return /* @__PURE__ */ jsxs2(
1560
+ "span",
1561
+ {
1562
+ title: recipient.did,
1563
+ ...props,
1564
+ className: `basic-recipient-label ${className}`,
1565
+ children: [
1566
+ /* @__PURE__ */ jsx4(
1567
+ ShareRecipientAvatar,
1568
+ {
1569
+ recipient,
1570
+ size,
1571
+ "aria-hidden": "true",
1572
+ title: void 0
1573
+ }
1574
+ ),
1575
+ /* @__PURE__ */ jsx4("span", { className: "basic-recipient-handle", children: label })
1576
+ ]
1577
+ }
1578
+ );
1579
+ }
1580
+ function ShareRecipientAvatars({
1581
+ recipients,
1582
+ size = 32,
1583
+ max = 4,
1584
+ className = "",
1585
+ ...props
1586
+ }) {
1587
+ const unique = [
1588
+ ...new Map(
1589
+ recipients.map((recipient) => [recipient.did, recipient])
1590
+ ).values()
1591
+ ];
1592
+ const visible = unique.slice(0, Math.max(1, max));
1593
+ const remaining = unique.length - visible.length;
1594
+ return /* @__PURE__ */ jsxs2(
1595
+ "span",
1596
+ {
1597
+ ...props,
1598
+ className: `basic-recipient-avatars ${className}`,
1599
+ role: "group",
1600
+ "aria-label": props["aria-label"] ?? `Shared with ${unique.length} recipients`,
1601
+ children: [
1602
+ visible.map((recipient) => /* @__PURE__ */ jsx4(
1603
+ ShareRecipientAvatar,
1604
+ {
1605
+ recipient,
1606
+ size
1607
+ },
1608
+ recipient.did
1609
+ )),
1610
+ remaining > 0 && /* @__PURE__ */ jsxs2(
1611
+ "span",
1612
+ {
1613
+ className: "basic-recipient-overflow",
1614
+ "aria-label": `${remaining} more recipients`,
1615
+ children: [
1616
+ "+",
1617
+ remaining
1618
+ ]
1619
+ }
1620
+ )
1270
1621
  ]
1271
1622
  }
1272
1623
  );
1273
- return showSyncBadge ?? client.mode === "sync" ? /* @__PURE__ */ jsxs("span", { className: "basic-avatar-container", children: [
1274
- avatar,
1275
- /* @__PURE__ */ jsx3(SyncStatus, { sync, className: "basic-avatar-sync" })
1276
- ] }) : avatar;
1277
1624
  }
1278
1625
  function AuthStatus({
1279
1626
  auth: supplied,
@@ -1284,7 +1631,7 @@ function AuthStatus({
1284
1631
  const auth = supplied ?? live;
1285
1632
  const expired = auth.status === "expired";
1286
1633
  const label = !auth.isReady || auth.status === "bootstrapping" ? "Checking session" : expired ? "Session expired" : auth.status === "recovering" ? "Reconnecting session" : auth.isSignedIn ? "Signed in" : auth.isAnonymous ? "Guest \xB7 local only" : "Signed out";
1287
- return /* @__PURE__ */ jsxs(
1634
+ return /* @__PURE__ */ jsxs2(
1288
1635
  "span",
1289
1636
  {
1290
1637
  ...props,
@@ -1292,7 +1639,7 @@ function AuthStatus({
1292
1639
  className: `basic-status ${className}`,
1293
1640
  "data-tone": expired || auth.error ? "warning" : auth.isSignedIn ? "success" : "neutral",
1294
1641
  children: [
1295
- /* @__PURE__ */ jsx3("span", { className: "basic-dot" }),
1642
+ /* @__PURE__ */ jsx4("span", { className: "basic-dot" }),
1296
1643
  label
1297
1644
  ]
1298
1645
  }
@@ -1322,7 +1669,7 @@ function SyncStatus({
1322
1669
  ended: "Access ended"
1323
1670
  };
1324
1671
  const label = issues ? `${issues} sync ${issues === 1 ? "issue" : "issues"}` : sync.status === "online" && sync.pendingCount ? "Syncing" : labels[sync.status];
1325
- return /* @__PURE__ */ jsxs(
1672
+ return /* @__PURE__ */ jsxs2(
1326
1673
  "span",
1327
1674
  {
1328
1675
  ...props,
@@ -1331,7 +1678,7 @@ function SyncStatus({
1331
1678
  className: `basic-status ${className}`,
1332
1679
  "data-tone": issues || ["error", "stale", "ended"].includes(sync.status) ? "warning" : sync.status === "online" && !sync.pendingCount ? "success" : ["bootstrapping", "connecting"].includes(sync.status) || sync.status === "online" && sync.pendingCount > 0 ? "progress" : "neutral",
1333
1680
  children: [
1334
- /* @__PURE__ */ jsx3("span", { className: "basic-dot" }),
1681
+ /* @__PURE__ */ jsx4("span", { className: "basic-dot" }),
1335
1682
  label,
1336
1683
  sync.pendingCount > 0 && ` \xB7 ${sync.pendingCount} pending`
1337
1684
  ]
@@ -1342,7 +1689,7 @@ function displayHandle(handle) {
1342
1689
  return handle ? `@${handle.replace(/^@+/, "")}` : "";
1343
1690
  }
1344
1691
  function UserButton(props) {
1345
- return /* @__PURE__ */ jsx3(UserMenu, { ...props, trigger: "button" });
1692
+ return /* @__PURE__ */ jsx4(UserMenu, { ...props, trigger: "button" });
1346
1693
  }
1347
1694
  function UserMenu({
1348
1695
  accounts: supplied,
@@ -1354,9 +1701,12 @@ function UserMenu({
1354
1701
  trigger = "avatar",
1355
1702
  avatarProps,
1356
1703
  projectProfile,
1704
+ invites,
1705
+ showInvites,
1357
1706
  allowAddAccount = true,
1358
1707
  className = "",
1359
- accountSettingsUrl
1708
+ accountSettingsUrl,
1709
+ menuItems = []
1360
1710
  }) {
1361
1711
  const liveAccounts = useAccounts();
1362
1712
  const liveAuth = useAuth();
@@ -1365,17 +1715,17 @@ function UserMenu({
1365
1715
  const action = useAction();
1366
1716
  const [settingsOpen, setSettingsOpen] = useState4(false);
1367
1717
  const [clearAccountId, setClearAccountId] = useState4(null);
1368
- const triggerRef = useRef3(null);
1718
+ const triggerRef = useRef4(null);
1369
1719
  const appearance = useAppearanceProps();
1370
1720
  const expired = auth.status === "expired";
1371
1721
  const active = accounts.activeAccount;
1372
1722
  const otherAccounts = accounts.accounts.filter(
1373
1723
  (account) => account.id !== active?.id
1374
1724
  );
1375
- const name = active?.name || active?.kind !== "anon" && displayHandle(active?.handle) || "Local account";
1376
- return /* @__PURE__ */ jsxs("span", { className: `basic-action ${className}`, children: [
1377
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
1378
- /* @__PURE__ */ jsxs(
1725
+ const name = active ? accountName(active) : "Local account";
1726
+ return /* @__PURE__ */ jsxs2("span", { className: `basic-action ${className}`, children: [
1727
+ /* @__PURE__ */ jsxs2(Menu.Root, { children: [
1728
+ /* @__PURE__ */ jsxs2(
1379
1729
  Menu.Trigger,
1380
1730
  {
1381
1731
  ref: triggerRef,
@@ -1384,7 +1734,7 @@ function UserMenu({
1384
1734
  disabled: !auth.isReady || action.pending,
1385
1735
  "aria-label": "Open user menu",
1386
1736
  children: [
1387
- /* @__PURE__ */ jsx3(
1737
+ /* @__PURE__ */ jsx4(
1388
1738
  AccountAvatar,
1389
1739
  {
1390
1740
  profile: accounts.activeAccount,
@@ -1393,12 +1743,12 @@ function UserMenu({
1393
1743
  ...avatarProps
1394
1744
  }
1395
1745
  ),
1396
- trigger === "button" && /* @__PURE__ */ jsxs(Fragment2, { children: [
1397
- /* @__PURE__ */ jsxs("span", { className: "basic-identity", children: [
1398
- /* @__PURE__ */ jsx3("strong", { children: name }),
1399
- active?.kind !== "anon" && active?.handle && /* @__PURE__ */ jsx3("small", { children: displayHandle(active.handle) })
1746
+ trigger === "button" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1747
+ /* @__PURE__ */ jsxs2("span", { className: "basic-identity", children: [
1748
+ /* @__PURE__ */ jsx4("strong", { children: name }),
1749
+ active?.kind !== "anon" && active?.handle && /* @__PURE__ */ jsx4("small", { children: displayHandle(active.handle) })
1400
1750
  ] }),
1401
- /* @__PURE__ */ jsx3(
1751
+ /* @__PURE__ */ jsx4(
1402
1752
  "svg",
1403
1753
  {
1404
1754
  className: "basic-chevron",
@@ -1411,16 +1761,16 @@ function UserMenu({
1411
1761
  strokeLinecap: "round",
1412
1762
  strokeLinejoin: "round",
1413
1763
  "aria-hidden": "true",
1414
- children: /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" })
1764
+ children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" })
1415
1765
  }
1416
1766
  )
1417
1767
  ] })
1418
1768
  ]
1419
1769
  }
1420
1770
  ),
1421
- /* @__PURE__ */ jsx3(Menu.Portal, { children: /* @__PURE__ */ jsx3(Menu.Positioner, { sideOffset: 8, className: "basic-positioner", children: /* @__PURE__ */ jsxs(Menu.Popup, { ...appearance, className: "basic-ui basic-menu", children: [
1422
- /* @__PURE__ */ jsxs("div", { className: "basic-menu-profile", children: [
1423
- /* @__PURE__ */ jsx3(
1771
+ /* @__PURE__ */ jsx4(Menu.Portal, { children: /* @__PURE__ */ jsx4(Menu.Positioner, { sideOffset: 8, className: "basic-positioner", children: /* @__PURE__ */ jsxs2(Menu.Popup, { ...appearance, className: "basic-ui basic-menu", children: [
1772
+ /* @__PURE__ */ jsxs2("div", { className: "basic-menu-profile", children: [
1773
+ /* @__PURE__ */ jsx4(
1424
1774
  AccountAvatar,
1425
1775
  {
1426
1776
  profile: active,
@@ -1429,16 +1779,16 @@ function UserMenu({
1429
1779
  showSyncBadge: false
1430
1780
  }
1431
1781
  ),
1432
- /* @__PURE__ */ jsxs("span", { className: "basic-identity", children: [
1433
- /* @__PURE__ */ jsx3("strong", { children: active ? name : "No active account" }),
1434
- active?.kind !== "anon" && active?.handle && /* @__PURE__ */ jsx3("small", { children: displayHandle(active.handle) }),
1435
- /* @__PURE__ */ jsxs("span", { className: "basic-account-statuses", children: [
1436
- expired && /* @__PURE__ */ jsx3("span", { className: "basic-status", "data-tone": "warning", children: "Expired" }),
1437
- showSyncStatus && /* @__PURE__ */ jsx3(SyncStatus, { sync })
1782
+ /* @__PURE__ */ jsxs2("span", { className: "basic-identity", children: [
1783
+ /* @__PURE__ */ jsx4("strong", { children: active ? name : "No active account" }),
1784
+ active?.kind !== "anon" && active?.handle && /* @__PURE__ */ jsx4("small", { children: displayHandle(active.handle) }),
1785
+ /* @__PURE__ */ jsxs2("span", { className: "basic-account-statuses", children: [
1786
+ expired && /* @__PURE__ */ jsx4("span", { className: "basic-status", "data-tone": "warning", children: "Expired" }),
1787
+ showSyncStatus && /* @__PURE__ */ jsx4(SyncStatus, { sync })
1438
1788
  ] })
1439
1789
  ] })
1440
1790
  ] }),
1441
- expired && /* @__PURE__ */ jsx3(
1791
+ expired && /* @__PURE__ */ jsx4(
1442
1792
  Menu.Item,
1443
1793
  {
1444
1794
  className: "basic-menu-item basic-menu-reauth",
@@ -1447,13 +1797,13 @@ function UserMenu({
1447
1797
  children: "Sign in again"
1448
1798
  }
1449
1799
  ),
1450
- /* @__PURE__ */ jsxs(
1800
+ /* @__PURE__ */ jsxs2(
1451
1801
  Menu.Item,
1452
1802
  {
1453
1803
  className: "basic-menu-item basic-manage-account",
1454
1804
  onClick: () => setSettingsOpen(true),
1455
1805
  children: [
1456
- /* @__PURE__ */ jsxs(
1806
+ /* @__PURE__ */ jsxs2(
1457
1807
  "svg",
1458
1808
  {
1459
1809
  className: "basic-menu-icon",
@@ -1467,8 +1817,8 @@ function UserMenu({
1467
1817
  strokeLinejoin: "round",
1468
1818
  "aria-hidden": "true",
1469
1819
  children: [
1470
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "7", r: "4" }),
1471
- /* @__PURE__ */ jsx3("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" })
1820
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "7", r: "4" }),
1821
+ /* @__PURE__ */ jsx4("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" })
1472
1822
  ]
1473
1823
  }
1474
1824
  ),
@@ -1476,14 +1826,30 @@ function UserMenu({
1476
1826
  ]
1477
1827
  }
1478
1828
  ),
1479
- (auth.isSignedIn || expired || active?.kind === "anon") && /* @__PURE__ */ jsxs(
1829
+ menuItems.map((item) => /* @__PURE__ */ jsxs2(
1830
+ Menu.Item,
1831
+ {
1832
+ className: "basic-menu-item",
1833
+ render: item.href !== void 0 ? /* @__PURE__ */ jsx4("a", { href: item.href }) : void 0,
1834
+ disabled: item.disabled || action.pending,
1835
+ onClick: () => {
1836
+ if (item.onClick) void action.run(item.onClick);
1837
+ },
1838
+ children: [
1839
+ /* @__PURE__ */ jsx4("span", { className: "basic-menu-icon", "aria-hidden": "true", children: item.icon }),
1840
+ item.label
1841
+ ]
1842
+ },
1843
+ item.id
1844
+ )),
1845
+ (auth.isSignedIn || expired || active?.kind === "anon") && /* @__PURE__ */ jsxs2(
1480
1846
  Menu.Item,
1481
1847
  {
1482
1848
  className: "basic-menu-item basic-menu-signout",
1483
1849
  disabled: action.pending,
1484
1850
  onClick: () => active?.kind === "anon" ? setClearAccountId(active.id) : void action.run(() => auth.signOut()),
1485
1851
  children: [
1486
- /* @__PURE__ */ jsx3(
1852
+ /* @__PURE__ */ jsx4(
1487
1853
  "svg",
1488
1854
  {
1489
1855
  className: "basic-menu-icon",
@@ -1496,25 +1862,25 @@ function UserMenu({
1496
1862
  strokeLinecap: "round",
1497
1863
  strokeLinejoin: "round",
1498
1864
  "aria-hidden": "true",
1499
- children: /* @__PURE__ */ jsx3("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9" })
1865
+ children: /* @__PURE__ */ jsx4("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9" })
1500
1866
  }
1501
1867
  ),
1502
1868
  active?.kind === "anon" ? "Clear account" : "Sign out"
1503
1869
  ]
1504
1870
  }
1505
1871
  ),
1506
- otherAccounts.length > 0 && /* @__PURE__ */ jsxs(Fragment2, { children: [
1507
- /* @__PURE__ */ jsx3(Menu.Separator, { className: "basic-separator" }),
1508
- /* @__PURE__ */ jsx3("div", { className: "basic-menu-heading", children: "Switch accounts" })
1872
+ otherAccounts.length > 0 && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1873
+ /* @__PURE__ */ jsx4(Menu.Separator, { className: "basic-separator" }),
1874
+ /* @__PURE__ */ jsx4("div", { className: "basic-menu-heading", children: "Switch accounts" })
1509
1875
  ] }),
1510
- otherAccounts.map((account) => /* @__PURE__ */ jsxs(
1876
+ otherAccounts.map((account) => /* @__PURE__ */ jsxs2(
1511
1877
  Menu.Item,
1512
1878
  {
1513
1879
  className: "basic-menu-item",
1514
1880
  disabled: action.pending,
1515
1881
  onClick: () => void action.run(() => accounts.switchAccount(account.id)),
1516
1882
  children: [
1517
- /* @__PURE__ */ jsx3(
1883
+ /* @__PURE__ */ jsx4(
1518
1884
  AccountAvatar,
1519
1885
  {
1520
1886
  profile: account,
@@ -1523,16 +1889,16 @@ function UserMenu({
1523
1889
  showSyncBadge: false
1524
1890
  }
1525
1891
  ),
1526
- /* @__PURE__ */ jsxs("span", { className: "basic-identity", children: [
1527
- /* @__PURE__ */ jsx3("strong", { children: account.name || account.kind !== "anon" && displayHandle(account.handle) || (account.kind === "anon" ? "Local account" : "Account") }),
1528
- account.kind !== "anon" && account.handle && /* @__PURE__ */ jsx3("small", { children: displayHandle(account.handle) })
1892
+ /* @__PURE__ */ jsxs2("span", { className: "basic-identity", children: [
1893
+ /* @__PURE__ */ jsx4("strong", { children: accountName(account, "Account") }),
1894
+ account.kind !== "anon" && account.handle && /* @__PURE__ */ jsx4("small", { children: displayHandle(account.handle) })
1529
1895
  ] }),
1530
- /* @__PURE__ */ jsx3("span", { className: "basic-account-statuses", children: account.auth.status === "expired" ? /* @__PURE__ */ jsx3("span", { className: "basic-status", "data-tone": "warning", children: "Expired" }) : null })
1896
+ /* @__PURE__ */ jsx4("span", { className: "basic-account-statuses", children: account.auth.status === "expired" ? /* @__PURE__ */ jsx4("span", { className: "basic-status", "data-tone": "warning", children: "Expired" }) : null })
1531
1897
  ]
1532
1898
  },
1533
1899
  account.id
1534
1900
  )),
1535
- (allowAddAccount || !auth.isSignedIn && !expired) && /* @__PURE__ */ jsx3(
1901
+ (allowAddAccount || !auth.isSignedIn && !expired) && /* @__PURE__ */ jsxs2(
1536
1902
  Menu.Item,
1537
1903
  {
1538
1904
  className: "basic-menu-item",
@@ -1540,12 +1906,29 @@ function UserMenu({
1540
1906
  onClick: () => void action.run(
1541
1907
  () => allowAddAccount ? accounts.addAccount({ signIn: true }) : auth.signIn()
1542
1908
  ),
1543
- children: "\uFF0B Add account"
1909
+ children: [
1910
+ /* @__PURE__ */ jsx4(
1911
+ "svg",
1912
+ {
1913
+ className: "basic-menu-icon",
1914
+ width: "16",
1915
+ height: "16",
1916
+ viewBox: "0 0 24 24",
1917
+ fill: "none",
1918
+ stroke: "currentColor",
1919
+ strokeWidth: "1.75",
1920
+ strokeLinecap: "round",
1921
+ "aria-hidden": "true",
1922
+ children: /* @__PURE__ */ jsx4("path", { d: "M12 5v14M5 12h14" })
1923
+ }
1924
+ ),
1925
+ "Add account"
1926
+ ]
1544
1927
  }
1545
1928
  )
1546
1929
  ] }) }) })
1547
1930
  ] }),
1548
- /* @__PURE__ */ jsx3(
1931
+ /* @__PURE__ */ jsx4(
1549
1932
  ActionError,
1550
1933
  {
1551
1934
  error: action.error,
@@ -1553,7 +1936,7 @@ function UserMenu({
1553
1936
  finalFocus: triggerRef
1554
1937
  }
1555
1938
  ),
1556
- /* @__PURE__ */ jsx3(
1939
+ /* @__PURE__ */ jsx4(
1557
1940
  Modal,
1558
1941
  {
1559
1942
  open: clearAccountId !== null,
@@ -1564,8 +1947,8 @@ function UserMenu({
1564
1947
  finalFocus: triggerRef,
1565
1948
  title: "Clear local account?",
1566
1949
  description: "This deletes this account\u2019s local data, including unsynced changes. This cannot be undone.",
1567
- children: /* @__PURE__ */ jsxs("div", { className: "basic-actions", children: [
1568
- /* @__PURE__ */ jsx3(
1950
+ children: /* @__PURE__ */ jsxs2("div", { className: "basic-actions", children: [
1951
+ /* @__PURE__ */ jsx4(
1569
1952
  BasicButton,
1570
1953
  {
1571
1954
  disabled: action.pending,
@@ -1573,7 +1956,7 @@ function UserMenu({
1573
1956
  children: "Cancel"
1574
1957
  }
1575
1958
  ),
1576
- /* @__PURE__ */ jsx3(
1959
+ /* @__PURE__ */ jsx4(
1577
1960
  BasicButton,
1578
1961
  {
1579
1962
  disabled: action.pending,
@@ -1589,7 +1972,7 @@ function UserMenu({
1589
1972
  ] })
1590
1973
  }
1591
1974
  ),
1592
- /* @__PURE__ */ jsx3(
1975
+ /* @__PURE__ */ jsx4(
1593
1976
  AccountSettingsModal,
1594
1977
  {
1595
1978
  auth,
@@ -1600,6 +1983,8 @@ function UserMenu({
1600
1983
  finalFocus: triggerRef,
1601
1984
  accountSettingsUrl,
1602
1985
  projectProfile,
1986
+ invites,
1987
+ showInvites,
1603
1988
  sync
1604
1989
  }
1605
1990
  )
@@ -1610,7 +1995,7 @@ function ActionError({
1610
1995
  onClose,
1611
1996
  finalFocus
1612
1997
  }) {
1613
- return /* @__PURE__ */ jsxs(
1998
+ return /* @__PURE__ */ jsxs2(
1614
1999
  Modal,
1615
2000
  {
1616
2001
  open: !!error,
@@ -1622,8 +2007,8 @@ function ActionError({
1622
2007
  title: "Unable to complete action",
1623
2008
  description: "Your request could not be completed.",
1624
2009
  children: [
1625
- /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: error }),
1626
- /* @__PURE__ */ jsx3(BasicButton, { onClick: onClose, children: "Dismiss" })
2010
+ /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: error }),
2011
+ /* @__PURE__ */ jsx4(BasicButton, { onClick: onClose, children: "Dismiss" })
1627
2012
  ]
1628
2013
  }
1629
2014
  );
@@ -1635,29 +2020,36 @@ function Modal({
1635
2020
  finalFocus,
1636
2021
  title,
1637
2022
  description,
2023
+ hideTitle = false,
1638
2024
  header,
1639
2025
  sectionLabel,
1640
2026
  children
1641
2027
  }) {
1642
2028
  const appearance = useAppearanceProps();
1643
- return /* @__PURE__ */ jsxs(Dialog.Root, { open, onOpenChange, children: [
1644
- trigger !== null && (isValidElement(trigger) ? /* @__PURE__ */ jsx3(Dialog.Trigger, { render: trigger }) : /* @__PURE__ */ jsx3(Dialog.Trigger, { render: /* @__PURE__ */ jsx3(BasicButton, {}), children: trigger ?? title })),
1645
- /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
1646
- /* @__PURE__ */ jsx3(Dialog.Backdrop, { className: "basic-backdrop" }),
1647
- /* @__PURE__ */ jsxs(
2029
+ return /* @__PURE__ */ jsxs2(Dialog.Root, { open, onOpenChange, children: [
2030
+ trigger !== null && (isValidElement(trigger) ? /* @__PURE__ */ jsx4(Dialog.Trigger, { render: trigger }) : /* @__PURE__ */ jsx4(Dialog.Trigger, { render: /* @__PURE__ */ jsx4(BasicButton, {}), children: trigger ?? title })),
2031
+ /* @__PURE__ */ jsxs2(Dialog.Portal, { children: [
2032
+ /* @__PURE__ */ jsx4(Dialog.Backdrop, { className: "basic-backdrop" }),
2033
+ /* @__PURE__ */ jsxs2(
1648
2034
  Dialog.Popup,
1649
2035
  {
1650
2036
  ...appearance,
1651
2037
  finalFocus,
1652
2038
  className: "basic-ui basic-dialog",
1653
2039
  children: [
1654
- /* @__PURE__ */ jsxs(
2040
+ /* @__PURE__ */ jsxs2(
1655
2041
  "div",
1656
2042
  {
1657
- className: `basic-dialog-heading${header ? " basic-dialog-heading-overlay" : ""}`,
2043
+ className: `basic-dialog-heading${header || hideTitle ? " basic-dialog-heading-overlay" : ""}`,
1658
2044
  children: [
1659
- /* @__PURE__ */ jsx3(Dialog.Title, { className: header ? "basic-sr-only" : "basic-title", children: title }),
1660
- /* @__PURE__ */ jsx3(
2045
+ /* @__PURE__ */ jsx4(
2046
+ Dialog.Title,
2047
+ {
2048
+ className: header || hideTitle ? "basic-sr-only" : "basic-title",
2049
+ children: title
2050
+ }
2051
+ ),
2052
+ /* @__PURE__ */ jsx4(
1661
2053
  Dialog.Close,
1662
2054
  {
1663
2055
  className: "basic-button",
@@ -1669,14 +2061,14 @@ function Modal({
1669
2061
  }
1670
2062
  ),
1671
2063
  header,
1672
- /* @__PURE__ */ jsx3(
2064
+ description && /* @__PURE__ */ jsx4(
1673
2065
  Dialog.Description,
1674
2066
  {
1675
2067
  className: header ? "basic-sr-only" : "basic-muted",
1676
2068
  children: description
1677
2069
  }
1678
2070
  ),
1679
- sectionLabel && /* @__PURE__ */ jsx3("div", { className: "basic-modal-section", children: sectionLabel }),
2071
+ sectionLabel && /* @__PURE__ */ jsx4("div", { className: "basic-modal-section", children: sectionLabel }),
1680
2072
  children
1681
2073
  ]
1682
2074
  }
@@ -1689,6 +2081,8 @@ function AccountSettingsModal({
1689
2081
  accounts: suppliedAccounts,
1690
2082
  accountSettingsUrl,
1691
2083
  projectProfile,
2084
+ invites,
2085
+ showInvites = true,
1692
2086
  sync,
1693
2087
  children,
1694
2088
  ...props
@@ -1727,27 +2121,28 @@ function AccountSettingsModal({
1727
2121
  ["Conflicts", String(syncState.conflicts.length)]
1728
2122
  ];
1729
2123
  const diagnostics = JSON.stringify(Object.fromEntries(details), null, 2);
1730
- return /* @__PURE__ */ jsx3(
2124
+ return /* @__PURE__ */ jsx4(
1731
2125
  Modal,
1732
2126
  {
1733
2127
  ...props,
1734
2128
  title: "Account settings",
1735
2129
  description: "Your identity and session on this device.",
1736
- header: /* @__PURE__ */ jsx3(AccountHeader, { account: accounts.activeAccount, sync }),
1737
- children: /* @__PURE__ */ jsxs(Tabs.Root, { defaultValue: "profile", children: [
1738
- /* @__PURE__ */ jsxs(
2130
+ header: /* @__PURE__ */ jsx4(AccountHeader, { account: accounts.activeAccount, sync }),
2131
+ children: /* @__PURE__ */ jsxs2(Tabs.Root, { defaultValue: "profile", children: [
2132
+ /* @__PURE__ */ jsxs2(
1739
2133
  Tabs.List,
1740
2134
  {
1741
2135
  className: "basic-tabs",
1742
2136
  "aria-label": "Account settings sections",
1743
2137
  children: [
1744
- /* @__PURE__ */ jsx3(Tabs.Tab, { value: "profile", children: "Profile" }),
1745
- /* @__PURE__ */ jsx3(Tabs.Tab, { value: "advanced", children: "Advanced" })
2138
+ /* @__PURE__ */ jsx4(Tabs.Tab, { value: "profile", children: "Profile" }),
2139
+ showInvites && /* @__PURE__ */ jsx4(Tabs.Tab, { value: "invites", children: "Share Invites" }),
2140
+ /* @__PURE__ */ jsx4(Tabs.Tab, { value: "advanced", children: "Advanced" })
1746
2141
  ]
1747
2142
  }
1748
2143
  ),
1749
- /* @__PURE__ */ jsxs(Tabs.Panel, { value: "profile", keepMounted: true, children: [
1750
- auth.isSignedIn && /* @__PURE__ */ jsx3(
2144
+ /* @__PURE__ */ jsxs2(Tabs.Panel, { value: "profile", keepMounted: true, children: [
2145
+ auth.isSignedIn && /* @__PURE__ */ jsx4(
1751
2146
  ProjectProfileEditor,
1752
2147
  {
1753
2148
  profile: projectProfile,
@@ -1755,18 +2150,19 @@ function AccountSettingsModal({
1755
2150
  },
1756
2151
  accounts.activeAccount?.id ?? auth.did
1757
2152
  ),
1758
- accountSettingsUrl && /* @__PURE__ */ jsx3("a", { className: "basic-link", href: accountSettingsUrl, children: "Manage profile and security \u2197" }),
2153
+ accountSettingsUrl && /* @__PURE__ */ jsx4("a", { className: "basic-link", href: accountSettingsUrl, children: "Manage profile and security \u2197" }),
1759
2154
  children,
1760
- !auth.isSignedIn && /* @__PURE__ */ jsx3("div", { className: "basic-actions", children: /* @__PURE__ */ jsx3(SignInButton, { auth }) })
2155
+ !auth.isSignedIn && /* @__PURE__ */ jsx4("div", { className: "basic-actions", children: /* @__PURE__ */ jsx4(SignInButton, { auth }) })
1761
2156
  ] }),
1762
- /* @__PURE__ */ jsxs(Tabs.Panel, { value: "advanced", children: [
1763
- /* @__PURE__ */ jsx3("p", { className: "basic-muted", children: "Read-only diagnostics for this account." }),
1764
- /* @__PURE__ */ jsx3("dl", { className: "basic-details", children: details.map(([label, value]) => /* @__PURE__ */ jsxs(Fragment, { children: [
1765
- /* @__PURE__ */ jsx3("dt", { children: label }),
1766
- /* @__PURE__ */ jsx3("dd", { children: value })
2157
+ showInvites && /* @__PURE__ */ jsx4(Tabs.Panel, { value: "invites", children: /* @__PURE__ */ jsx4(ShareInvites, { auth, accounts, invites }) }),
2158
+ /* @__PURE__ */ jsxs2(Tabs.Panel, { value: "advanced", children: [
2159
+ /* @__PURE__ */ jsx4("p", { className: "basic-muted", children: "Read-only diagnostics for this account." }),
2160
+ /* @__PURE__ */ jsx4("dl", { className: "basic-details", children: details.map(([label, value]) => /* @__PURE__ */ jsxs2(Fragment, { children: [
2161
+ /* @__PURE__ */ jsx4("dt", { children: label }),
2162
+ /* @__PURE__ */ jsx4("dd", { children: value })
1767
2163
  ] }, label)) }),
1768
- /* @__PURE__ */ jsxs("div", { className: "basic-actions", children: [
1769
- /* @__PURE__ */ jsx3(
2164
+ /* @__PURE__ */ jsxs2("div", { className: "basic-actions", children: [
2165
+ /* @__PURE__ */ jsx4(
1770
2166
  BasicButton,
1771
2167
  {
1772
2168
  disabled: copyAction.pending,
@@ -1782,9 +2178,9 @@ function AccountSettingsModal({
1782
2178
  children: "Copy to clipboard"
1783
2179
  }
1784
2180
  ),
1785
- copied === diagnostics && /* @__PURE__ */ jsx3("span", { role: "status", className: "basic-muted", children: "Copied" })
2181
+ copied === diagnostics && /* @__PURE__ */ jsx4("span", { role: "status", className: "basic-muted", children: "Copied" })
1786
2182
  ] }),
1787
- copyAction.error && /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: copyAction.error })
2183
+ copyAction.error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: copyAction.error })
1788
2184
  ] })
1789
2185
  ] })
1790
2186
  }
@@ -1794,8 +2190,8 @@ function AccountHeader({
1794
2190
  account,
1795
2191
  sync
1796
2192
  }) {
1797
- return /* @__PURE__ */ jsxs("div", { className: "basic-profile", children: [
1798
- /* @__PURE__ */ jsx3(
2193
+ return /* @__PURE__ */ jsxs2("div", { className: "basic-profile", children: [
2194
+ /* @__PURE__ */ jsx4(
1799
2195
  AccountAvatar,
1800
2196
  {
1801
2197
  profile: account,
@@ -1804,10 +2200,10 @@ function AccountHeader({
1804
2200
  showSyncBadge: false
1805
2201
  }
1806
2202
  ),
1807
- /* @__PURE__ */ jsxs("span", { className: "basic-identity", children: [
1808
- /* @__PURE__ */ jsx3("strong", { children: account?.name || account?.kind !== "anon" && displayHandle(account?.handle) || "Local account" }),
1809
- account?.kind !== "anon" && account?.handle && /* @__PURE__ */ jsx3("small", { children: displayHandle(account.handle) }),
1810
- /* @__PURE__ */ jsx3("span", { className: "basic-account-statuses", children: /* @__PURE__ */ jsx3(SyncStatus, { sync }) })
2203
+ /* @__PURE__ */ jsxs2("span", { className: "basic-identity", children: [
2204
+ /* @__PURE__ */ jsx4("strong", { children: account ? accountName(account) : "Local account" }),
2205
+ account?.kind !== "anon" && account?.handle && /* @__PURE__ */ jsx4("small", { children: displayHandle(account.handle) }),
2206
+ /* @__PURE__ */ jsx4("span", { className: "basic-account-statuses", children: /* @__PURE__ */ jsx4(SyncStatus, { sync }) })
1811
2207
  ] })
1812
2208
  ] });
1813
2209
  }
@@ -1820,7 +2216,7 @@ function ProjectProfileEditor({
1820
2216
  const action = useAction();
1821
2217
  const [draft, setDraft] = useState4({});
1822
2218
  const [saved, setSaved] = useState4(false);
1823
- return /* @__PURE__ */ jsxs(
2219
+ return /* @__PURE__ */ jsxs2(
1824
2220
  "form",
1825
2221
  {
1826
2222
  className: "basic-profile-editor",
@@ -1834,15 +2230,15 @@ function ProjectProfileEditor({
1834
2230
  });
1835
2231
  },
1836
2232
  children: [
1837
- /* @__PURE__ */ jsx3("h3", { className: "basic-section-label", children: "Personal information" }),
1838
- /* @__PURE__ */ jsx3("p", { className: "basic-muted", children: "Only this app sees these overrides. Clear a field to use your universal profile value." }),
1839
- profile.isLoading ? /* @__PURE__ */ jsx3("p", { role: "status", children: "Loading project profile\u2026" }) : profile.error ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1840
- /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: profile.error.message }),
1841
- /* @__PURE__ */ jsx3(BasicButton, { onClick: profile.refresh, children: "Retry profile" })
1842
- ] }) : profile.data && /* @__PURE__ */ jsxs("fieldset", { disabled: !canWrite || action.pending, children: [
1843
- /* @__PURE__ */ jsxs("label", { className: "basic-field", children: [
2233
+ /* @__PURE__ */ jsx4("h3", { className: "basic-section-label", children: "Personal information" }),
2234
+ /* @__PURE__ */ jsx4("p", { className: "basic-muted", children: "Only this app sees these overrides. Clear a field to use your universal profile value." }),
2235
+ profile.isLoading ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Loading project profile\u2026" }) : profile.error ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
2236
+ /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: profile.error.message }),
2237
+ /* @__PURE__ */ jsx4(BasicButton, { onClick: profile.refresh, children: "Retry profile" })
2238
+ ] }) : profile.data && /* @__PURE__ */ jsxs2("fieldset", { disabled: !canWrite || action.pending, children: [
2239
+ /* @__PURE__ */ jsxs2("label", { className: "basic-field", children: [
1844
2240
  "Display name",
1845
- /* @__PURE__ */ jsx3(
2241
+ /* @__PURE__ */ jsx4(
1846
2242
  "input",
1847
2243
  {
1848
2244
  className: "basic-input",
@@ -1859,8 +2255,8 @@ function ProjectProfileEditor({
1859
2255
  }
1860
2256
  )
1861
2257
  ] }),
1862
- /* @__PURE__ */ jsxs("div", { className: "basic-actions basic-modal-footer", children: [
1863
- /* @__PURE__ */ jsx3(
2258
+ /* @__PURE__ */ jsxs2("div", { className: "basic-actions basic-modal-footer", children: [
2259
+ /* @__PURE__ */ jsx4(
1864
2260
  BasicButton,
1865
2261
  {
1866
2262
  variant: "ghost",
@@ -1871,7 +2267,7 @@ function ProjectProfileEditor({
1871
2267
  children: "Cancel"
1872
2268
  }
1873
2269
  ),
1874
- /* @__PURE__ */ jsx3(
2270
+ /* @__PURE__ */ jsx4(
1875
2271
  BasicButton,
1876
2272
  {
1877
2273
  type: "submit",
@@ -1882,17 +2278,205 @@ function ProjectProfileEditor({
1882
2278
  )
1883
2279
  ] })
1884
2280
  ] }),
1885
- action.error && /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: action.error }),
1886
- saved && /* @__PURE__ */ jsx3("p", { role: "status", children: "Project profile saved." })
2281
+ action.error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: action.error }),
2282
+ saved && /* @__PURE__ */ jsx4("p", { role: "status", children: "Project profile saved." })
1887
2283
  ]
1888
2284
  }
1889
2285
  );
1890
2286
  }
2287
+ function ShareInvites({
2288
+ auth: suppliedAuth,
2289
+ accounts: suppliedAccounts,
2290
+ invites,
2291
+ className = "",
2292
+ ...props
2293
+ }) {
2294
+ const liveAuth = useAuth();
2295
+ const liveAccounts = useAccounts();
2296
+ const auth = suppliedAuth ?? liveAuth;
2297
+ const accounts = suppliedAccounts ?? liveAccounts;
2298
+ return /* @__PURE__ */ jsxs2(
2299
+ "section",
2300
+ {
2301
+ ...props,
2302
+ className: `basic-invites ${className}`,
2303
+ "aria-label": props["aria-label"] ?? "Share Invites",
2304
+ children: [
2305
+ (!auth.isReady || !auth.isSignedIn) && /* @__PURE__ */ jsx4("h3", { className: "basic-title", children: "Share Invites" }),
2306
+ !auth.isReady ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Checking session\u2026" }) : !auth.isSignedIn ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
2307
+ /* @__PURE__ */ jsx4("p", { className: "basic-muted", children: "Sign in to view invites." }),
2308
+ /* @__PURE__ */ jsx4(SignInButton, { auth })
2309
+ ] }) : /* @__PURE__ */ jsx4(
2310
+ ShareInvitesContent,
2311
+ {
2312
+ invites,
2313
+ canWrite: auth.canWrite
2314
+ },
2315
+ accounts.activeAccount?.id ?? auth.did
2316
+ )
2317
+ ]
2318
+ }
2319
+ );
2320
+ }
2321
+ function ShareInvitesContent({
2322
+ invites: supplied,
2323
+ canWrite
2324
+ }) {
2325
+ const live = useShareInvites(supplied === void 0);
2326
+ const invites = supplied ?? live;
2327
+ const action = useAction();
2328
+ const [message, setMessage] = useState4("");
2329
+ const visible = invites.data.filter((invite) => invite.state !== "deleted");
2330
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
2331
+ /* @__PURE__ */ jsxs2("div", { className: "basic-section-heading", children: [
2332
+ /* @__PURE__ */ jsx4("h3", { className: "basic-title", children: "Share Invites" }),
2333
+ /* @__PURE__ */ jsx4(
2334
+ BasicButton,
2335
+ {
2336
+ disabled: invites.isLoading || action.pending,
2337
+ onClick: invites.refresh,
2338
+ children: "Refresh"
2339
+ }
2340
+ )
2341
+ ] }),
2342
+ !canWrite && /* @__PURE__ */ jsx4("p", { className: "basic-error", children: "Read-only session. Invite changes are disabled." }),
2343
+ action.error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: action.error }),
2344
+ message && /* @__PURE__ */ jsx4("p", { role: "status", children: message }),
2345
+ action.pending && /* @__PURE__ */ jsx4("p", { role: "status", children: "Updating invite\u2026" }),
2346
+ invites.isLoading ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Loading invites\u2026" }) : invites.error ? /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: invites.error.message }) : !visible.length ? /* @__PURE__ */ jsx4("p", { className: "basic-empty", children: "No share invites." }) : /* @__PURE__ */ jsx4("ul", { className: "basic-share-list basic-invite-list", children: visible.map((invite) => {
2347
+ const title = invite.display.shareName || invite.display.repoName || "Shared data";
2348
+ return /* @__PURE__ */ jsx4(
2349
+ ShareInviteRow,
2350
+ {
2351
+ invite,
2352
+ title,
2353
+ resolveContactHandle: invites.resolveContactHandle,
2354
+ disabled: !canWrite || action.pending,
2355
+ onDecision: (decision) => void action.run(async () => {
2356
+ setMessage("");
2357
+ await invites[decision](invite.id);
2358
+ setMessage(
2359
+ `${decision === "accept" ? "Accepted" : "Declined"} \u201C${title}\u201D.`
2360
+ );
2361
+ })
2362
+ },
2363
+ invite.id
2364
+ );
2365
+ }) })
2366
+ ] });
2367
+ }
2368
+ function ShareInviteRow({
2369
+ invite,
2370
+ title,
2371
+ resolveContactHandle,
2372
+ disabled,
2373
+ onDecision
2374
+ }) {
2375
+ const did = invite.originOwnerDid;
2376
+ const [sender, setSender] = useState4(null);
2377
+ useEffect4(() => {
2378
+ let active = true;
2379
+ void resolveContactHandle(did).then(
2380
+ (handle2) => {
2381
+ if (active) setSender({ did, handle: handle2 });
2382
+ },
2383
+ () => {
2384
+ if (active) setSender({ did, handle: null });
2385
+ }
2386
+ );
2387
+ return () => {
2388
+ active = false;
2389
+ };
2390
+ }, [did, resolveContactHandle]);
2391
+ const handle = sender?.did === did ? sender.handle : null;
2392
+ const pending = invite.state === "pending";
2393
+ const accepting = invite.state === "accepting";
2394
+ const expiresAt = new Date(invite.acceptBy);
2395
+ const expired = expiresAt.getTime() <= Date.now();
2396
+ const blocked = invite.compatibility.state === "app_connection_required" ? "Connect this app to accept." : invite.compatibility.state === "compatible_repo_required" ? "A compatible repository is required." : null;
2397
+ const status = pending && !expired ? null : (pending || accepting) && expired ? "Expired" : accepting ? "Retry to finish accepting" : invite.state === "accepted" ? "Accepted" : invite.state === "declined" ? "Declined" : "Acceptance rejected";
2398
+ return /* @__PURE__ */ jsxs2("li", { children: [
2399
+ /* @__PURE__ */ jsx4(
2400
+ ShareRecipientAvatar,
2401
+ {
2402
+ recipient: {
2403
+ did,
2404
+ name: handle ? displayHandle(handle) : "Unknown sender"
2405
+ },
2406
+ size: 32
2407
+ }
2408
+ ),
2409
+ /* @__PURE__ */ jsxs2("div", { className: "basic-identity", children: [
2410
+ /* @__PURE__ */ jsx4("strong", { children: title }),
2411
+ /* @__PURE__ */ jsx4("small", { children: handle ? displayHandle(handle) : "Unknown sender" }),
2412
+ /* @__PURE__ */ jsx4("small", { children: invite.role === "editor" ? "Can edit" : "Can view" }),
2413
+ status && /* @__PURE__ */ jsx4("span", { className: "basic-invite-state", children: status }),
2414
+ blocked && (pending || accepting) && /* @__PURE__ */ jsx4("p", { className: "basic-error", children: blocked })
2415
+ ] }),
2416
+ (pending || accepting) && /* @__PURE__ */ jsxs2("div", { className: "basic-invite-actions", children: [
2417
+ /* @__PURE__ */ jsx4(
2418
+ BasicButton,
2419
+ {
2420
+ variant: "solid",
2421
+ disabled: disabled || expired || !!blocked,
2422
+ onClick: () => onDecision("accept"),
2423
+ children: accepting ? "Retry acceptance" : "Accept"
2424
+ }
2425
+ ),
2426
+ pending && /* @__PURE__ */ jsx4(
2427
+ BasicButton,
2428
+ {
2429
+ disabled,
2430
+ onClick: () => onDecision("decline"),
2431
+ children: "Decline"
2432
+ }
2433
+ )
2434
+ ] }),
2435
+ /* @__PURE__ */ jsxs2("details", { className: "basic-invite-details", children: [
2436
+ /* @__PURE__ */ jsx4("summary", { children: "Details" }),
2437
+ /* @__PURE__ */ jsxs2("div", { className: "basic-invite-scope", children: [
2438
+ invite.scope.map((scope, index) => /* @__PURE__ */ jsxs2("div", { children: [
2439
+ /* @__PURE__ */ jsx4("strong", { children: scope.table }),
2440
+ " \xB7",
2441
+ " ",
2442
+ scope.recordIds ? `${scope.recordIds.length} selected records` : "all records",
2443
+ scope.recordIds && /* @__PURE__ */ jsx4("code", { children: scope.recordIds.join(", ") })
2444
+ ] }, index)),
2445
+ /* @__PURE__ */ jsxs2("small", { children: [
2446
+ "Sender DID: ",
2447
+ did
2448
+ ] }),
2449
+ /* @__PURE__ */ jsxs2("small", { children: [
2450
+ "Expires",
2451
+ " ",
2452
+ /* @__PURE__ */ jsxs2("time", { dateTime: invite.acceptBy, children: [
2453
+ expiresAt.toLocaleString("en-US", {
2454
+ dateStyle: "medium",
2455
+ timeStyle: "short",
2456
+ timeZone: "UTC"
2457
+ }),
2458
+ " ",
2459
+ "UTC"
2460
+ ] })
2461
+ ] })
2462
+ ] })
2463
+ ] })
2464
+ ] });
2465
+ }
2466
+ function ShareInvitesModal({
2467
+ auth,
2468
+ accounts,
2469
+ invites,
2470
+ ...props
2471
+ }) {
2472
+ return /* @__PURE__ */ jsx4(Modal, { ...props, title: "Share Invites", hideTitle: true, children: /* @__PURE__ */ jsx4(ShareInvites, { auth, accounts, invites }) });
2473
+ }
1891
2474
  function SharesModal({
1892
2475
  auth: supplied,
1893
2476
  accounts: suppliedAccounts,
1894
2477
  sync,
1895
2478
  shares,
2479
+ invites,
1896
2480
  scope,
1897
2481
  repo = "default",
1898
2482
  ...props
@@ -1900,37 +2484,43 @@ function SharesModal({
1900
2484
  const live = useAuth();
1901
2485
  const liveAccounts = useAccounts();
1902
2486
  const auth = supplied ?? live;
1903
- return /* @__PURE__ */ jsx3(
2487
+ return /* @__PURE__ */ jsx4(
1904
2488
  Modal,
1905
2489
  {
1906
2490
  ...props,
1907
2491
  title: "Shares",
1908
2492
  description: "Manage incoming invitations and share access to selected data.",
1909
- header: /* @__PURE__ */ jsx3(
2493
+ header: /* @__PURE__ */ jsx4(
1910
2494
  AccountHeader,
1911
2495
  {
1912
2496
  account: (suppliedAccounts ?? liveAccounts).activeAccount,
1913
2497
  sync
1914
2498
  }
1915
2499
  ),
1916
- children: !auth.isReady ? /* @__PURE__ */ jsx3("p", { role: "status", children: "Checking session\u2026" }) : !auth.isSignedIn ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1917
- /* @__PURE__ */ jsx3("p", { className: "basic-muted", children: "Sign in to share data." }),
1918
- /* @__PURE__ */ jsx3(SignInButton, { auth })
1919
- ] }) : /* @__PURE__ */ jsx3(
2500
+ children: !auth.isReady ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Checking session\u2026" }) : !auth.isSignedIn ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
2501
+ /* @__PURE__ */ jsx4("p", { className: "basic-muted", children: "Sign in to share data." }),
2502
+ /* @__PURE__ */ jsx4(SignInButton, { auth })
2503
+ ] }) : /* @__PURE__ */ jsx4(
1920
2504
  SharesContent,
1921
2505
  {
1922
2506
  shares,
2507
+ invites,
2508
+ auth,
2509
+ accounts: suppliedAccounts ?? liveAccounts,
1923
2510
  scope,
1924
2511
  repo,
1925
2512
  canWrite: auth.canWrite
1926
2513
  },
1927
- auth.did ?? "account"
2514
+ (suppliedAccounts ?? liveAccounts).activeAccount?.id ?? auth.did
1928
2515
  )
1929
2516
  }
1930
2517
  );
1931
2518
  }
1932
2519
  function SharesContent({
1933
2520
  shares: supplied,
2521
+ invites,
2522
+ auth,
2523
+ accounts,
1934
2524
  scope,
1935
2525
  repo,
1936
2526
  canWrite
@@ -1945,29 +2535,25 @@ function SharesContent({
1945
2535
  const scopeValid = scope.length > 0 && scope.every(
1946
2536
  (item) => item.table.trim() && (item.recordIds === void 0 || item.recordIds.length > 0)
1947
2537
  );
1948
- return /* @__PURE__ */ jsxs(Tabs.Root, { defaultValue: "outgoing", className: "basic-shares", children: [
1949
- /* @__PURE__ */ jsxs(Tabs.List, { className: "basic-tabs", "aria-label": "Share direction", children: [
1950
- /* @__PURE__ */ jsx3(Tabs.Tab, { value: "outgoing", children: "Outgoing" }),
1951
- /* @__PURE__ */ jsx3(Tabs.Tab, { value: "incoming", children: "Incoming invitations" })
2538
+ return /* @__PURE__ */ jsxs2(Tabs.Root, { defaultValue: "outgoing", className: "basic-shares", children: [
2539
+ /* @__PURE__ */ jsxs2(Tabs.List, { className: "basic-tabs", "aria-label": "Share direction", children: [
2540
+ /* @__PURE__ */ jsx4(Tabs.Tab, { value: "outgoing", children: "Outgoing" }),
2541
+ /* @__PURE__ */ jsx4(Tabs.Tab, { value: "incoming", children: "Share Invites" })
1952
2542
  ] }),
1953
- /* @__PURE__ */ jsx3(Tabs.Panel, { value: "incoming", children: /* @__PURE__ */ jsxs("section", { "aria-label": "Incoming invitations", children: [
1954
- /* @__PURE__ */ jsx3("h3", { className: "basic-title", children: "Incoming invitations" }),
1955
- /* @__PURE__ */ jsx3("p", { className: "basic-muted", children: "View, accept, or decline incoming invitations in Basic ID. Your app session cannot access the account-wide inbox." }),
1956
- /* @__PURE__ */ jsx3("a", { className: "basic-link", href: shares.manageUrl(), children: "Open incoming invitations in Basic ID \u2197" })
1957
- ] }) }),
1958
- /* @__PURE__ */ jsxs(Tabs.Panel, { value: "outgoing", children: [
1959
- /* @__PURE__ */ jsx3("p", { className: "basic-muted", children: "Revoking access stops future requests. It cannot retract data the recipient already downloaded." }),
1960
- /* @__PURE__ */ jsxs("div", { className: "basic-scope", children: [
1961
- /* @__PURE__ */ jsx3("strong", { children: "New invitation permissions" }),
1962
- scope.map((item, index) => /* @__PURE__ */ jsxs("span", { children: [
2543
+ /* @__PURE__ */ jsx4(Tabs.Panel, { value: "incoming", children: /* @__PURE__ */ jsx4(ShareInvites, { invites, auth, accounts }) }),
2544
+ /* @__PURE__ */ jsxs2(Tabs.Panel, { value: "outgoing", children: [
2545
+ /* @__PURE__ */ jsx4("p", { className: "basic-muted", children: "Revoking access stops future requests. It cannot retract data the recipient already downloaded." }),
2546
+ /* @__PURE__ */ jsxs2("div", { className: "basic-scope", children: [
2547
+ /* @__PURE__ */ jsx4("strong", { children: "New invitation permissions" }),
2548
+ scope.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
1963
2549
  item.table,
1964
2550
  " \xB7",
1965
2551
  " ",
1966
2552
  item.recordIds ? `${item.recordIds.length} selected records` : "all records"
1967
2553
  ] }, index))
1968
2554
  ] }),
1969
- !canWrite && /* @__PURE__ */ jsx3("p", { className: "basic-error", children: "This session is read only. Sharing changes are disabled." }),
1970
- /* @__PURE__ */ jsxs(
2555
+ !canWrite && /* @__PURE__ */ jsx4("p", { className: "basic-error", children: "This session is read only. Sharing changes are disabled." }),
2556
+ /* @__PURE__ */ jsxs2(
1971
2557
  "form",
1972
2558
  {
1973
2559
  className: "basic-share-form",
@@ -1987,9 +2573,9 @@ function SharesContent({
1987
2573
  });
1988
2574
  },
1989
2575
  children: [
1990
- /* @__PURE__ */ jsxs("label", { className: "basic-field", children: [
2576
+ /* @__PURE__ */ jsxs2("label", { className: "basic-field", children: [
1991
2577
  "Recipient handle or DID",
1992
- /* @__PURE__ */ jsx3(
2578
+ /* @__PURE__ */ jsx4(
1993
2579
  "input",
1994
2580
  {
1995
2581
  className: "basic-input",
@@ -2001,9 +2587,9 @@ function SharesContent({
2001
2587
  }
2002
2588
  )
2003
2589
  ] }),
2004
- /* @__PURE__ */ jsxs("label", { className: "basic-field", children: [
2590
+ /* @__PURE__ */ jsxs2("label", { className: "basic-field", children: [
2005
2591
  "Permission",
2006
- /* @__PURE__ */ jsxs(
2592
+ /* @__PURE__ */ jsxs2(
2007
2593
  "select",
2008
2594
  {
2009
2595
  className: "basic-input",
@@ -2011,13 +2597,13 @@ function SharesContent({
2011
2597
  onChange: (event) => setRole(event.target.value),
2012
2598
  disabled: action.pending || !canWrite,
2013
2599
  children: [
2014
- /* @__PURE__ */ jsx3("option", { value: "viewer", children: "Can view" }),
2015
- /* @__PURE__ */ jsx3("option", { value: "editor", children: "Can edit" })
2600
+ /* @__PURE__ */ jsx4("option", { value: "viewer", children: "Can view" }),
2601
+ /* @__PURE__ */ jsx4("option", { value: "editor", children: "Can edit" })
2016
2602
  ]
2017
2603
  }
2018
2604
  )
2019
2605
  ] }),
2020
- /* @__PURE__ */ jsx3(
2606
+ /* @__PURE__ */ jsx4(
2021
2607
  BasicButton,
2022
2608
  {
2023
2609
  type: "submit",
@@ -2029,12 +2615,12 @@ function SharesContent({
2029
2615
  ]
2030
2616
  }
2031
2617
  ),
2032
- !scopeValid && /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: "Select at least one table or record to share." }),
2033
- action.error && /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: action.error }),
2034
- message && /* @__PURE__ */ jsx3("p", { role: "status", className: "basic-muted", children: message }),
2035
- /* @__PURE__ */ jsxs("div", { className: "basic-section-heading", children: [
2036
- /* @__PURE__ */ jsx3("h3", { className: "basic-title", children: "Outgoing shares \xB7 all permissions" }),
2037
- /* @__PURE__ */ jsx3(
2618
+ !scopeValid && /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: "Select at least one table or record to share." }),
2619
+ action.error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: action.error }),
2620
+ message && /* @__PURE__ */ jsx4("p", { role: "status", className: "basic-muted", children: message }),
2621
+ /* @__PURE__ */ jsxs2("div", { className: "basic-section-heading", children: [
2622
+ /* @__PURE__ */ jsx4("h3", { className: "basic-title", children: "Outgoing shares \xB7 all permissions" }),
2623
+ /* @__PURE__ */ jsx4(
2038
2624
  BasicButton,
2039
2625
  {
2040
2626
  disabled: action.pending || shares.isLoading,
@@ -2043,10 +2629,15 @@ function SharesContent({
2043
2629
  }
2044
2630
  )
2045
2631
  ] }),
2046
- shares.isLoading ? /* @__PURE__ */ jsx3("p", { role: "status", children: "Loading shares\u2026" }) : shares.error ? /* @__PURE__ */ jsx3("p", { role: "alert", className: "basic-error", children: shares.error.message }) : !shares.data.length ? /* @__PURE__ */ jsx3("p", { className: "basic-empty", children: "No outgoing shares yet." }) : /* @__PURE__ */ jsx3("ul", { className: "basic-share-list", children: shares.data.map((share) => /* @__PURE__ */ jsxs("li", { children: [
2047
- /* @__PURE__ */ jsxs("div", { className: "basic-identity", children: [
2048
- /* @__PURE__ */ jsx3("strong", { children: share.display.shareName || share.recipientDid }),
2049
- /* @__PURE__ */ jsxs("small", { children: [
2632
+ shares.isLoading ? /* @__PURE__ */ jsx4("p", { role: "status", children: "Loading shares\u2026" }) : shares.error ? /* @__PURE__ */ jsx4("p", { role: "alert", className: "basic-error", children: shares.error.message }) : !shares.data.length ? /* @__PURE__ */ jsx4("p", { className: "basic-empty", children: "No outgoing shares yet." }) : /* @__PURE__ */ jsx4("ul", { className: "basic-share-list", children: shares.data.map((share) => /* @__PURE__ */ jsxs2("li", { children: [
2633
+ /* @__PURE__ */ jsx4(ShareRecipientAvatar, { recipient: { did: share.recipientDid } }),
2634
+ /* @__PURE__ */ jsxs2("div", { className: "basic-identity", children: [
2635
+ /* @__PURE__ */ jsx4("strong", { children: share.display.shareName || share.recipientDid }),
2636
+ share.display.shareName && /* @__PURE__ */ jsxs2("small", { children: [
2637
+ "To ",
2638
+ share.recipientDid
2639
+ ] }),
2640
+ /* @__PURE__ */ jsxs2("small", { children: [
2050
2641
  share.role === "viewer" ? "Can view" : "Can edit",
2051
2642
  " \xB7",
2052
2643
  " ",
@@ -2056,9 +2647,9 @@ function SharesContent({
2056
2647
  share.scope.map((item) => item.table).join(", ")
2057
2648
  ] })
2058
2649
  ] }),
2059
- share.state !== "ended" && (confirmation === share.id ? /* @__PURE__ */ jsxs("div", { className: "basic-actions", children: [
2060
- /* @__PURE__ */ jsx3("span", { children: "Remove access?" }),
2061
- /* @__PURE__ */ jsxs(
2650
+ share.state !== "ended" && (confirmation === share.id ? /* @__PURE__ */ jsxs2("div", { className: "basic-actions", children: [
2651
+ /* @__PURE__ */ jsx4("span", { children: "Remove access?" }),
2652
+ /* @__PURE__ */ jsxs2(
2062
2653
  BasicButton,
2063
2654
  {
2064
2655
  disabled: action.pending || !canWrite,
@@ -2077,7 +2668,7 @@ function SharesContent({
2077
2668
  ]
2078
2669
  }
2079
2670
  ),
2080
- /* @__PURE__ */ jsx3(
2671
+ /* @__PURE__ */ jsx4(
2081
2672
  BasicButton,
2082
2673
  {
2083
2674
  disabled: action.pending,
@@ -2085,7 +2676,7 @@ function SharesContent({
2085
2676
  children: "Keep access"
2086
2677
  }
2087
2678
  )
2088
- ] }) : /* @__PURE__ */ jsx3(
2679
+ ] }) : /* @__PURE__ */ jsx4(
2089
2680
  BasicButton,
2090
2681
  {
2091
2682
  disabled: action.pending || !canWrite,
@@ -2106,6 +2697,11 @@ export {
2106
2697
  BrowserKeyValueStorage,
2107
2698
  BrowserTokenStore,
2108
2699
  PersistenceStore,
2700
+ ShareInvites,
2701
+ ShareInvitesModal,
2702
+ ShareRecipientAvatar,
2703
+ ShareRecipientAvatars,
2704
+ ShareRecipientLabel,
2109
2705
  SharesModal,
2110
2706
  SignInButton,
2111
2707
  SignOutButton,
@@ -2134,6 +2730,8 @@ export {
2134
2730
  useQuery,
2135
2731
  useRepos,
2136
2732
  useSchemaStatus,
2733
+ useShareInvites,
2734
+ useShareRecipients,
2137
2735
  useStorageInfo,
2138
2736
  useSyncStatus
2139
2737
  };