@tangle-network/agent-app 0.60.184 → 0.60.185
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/agent-profiles/d1.js +3 -3
- package/dist/agent-profiles/index.js +3 -3
- package/dist/assistant/index.js +9 -9
- package/dist/channels/index.js +1 -1
- package/dist/chat-react/index.js +4 -4
- package/dist/chat-routes/index.js +4 -4
- package/dist/{chunk-YXLN4PXK.js → chunk-2RCPPOQ4.js} +2 -2
- package/dist/{chunk-YESFGM56.js → chunk-5IS3GCMR.js} +3 -3
- package/dist/{chunk-3RHAF2P5.js → chunk-A3CUVYRZ.js} +3 -3
- package/dist/{chunk-LN5RBVGP.js → chunk-AVP5SNIG.js} +4 -4
- package/dist/{chunk-LN5RBVGP.js.map → chunk-AVP5SNIG.js.map} +1 -1
- package/dist/{chunk-7BYY7QKC.js → chunk-E65YV7VV.js} +5 -5
- package/dist/{chunk-7BYY7QKC.js.map → chunk-E65YV7VV.js.map} +1 -1
- package/dist/chunk-EZFBGW23.js +179 -0
- package/dist/chunk-EZFBGW23.js.map +1 -0
- package/dist/{chunk-UDLA3NGY.js → chunk-GNBBY3KN.js} +3 -3
- package/dist/{chunk-KOTNMTHV.js → chunk-HCFVEJQL.js} +3 -3
- package/dist/{chunk-YGBEGBJY.js → chunk-HEPEGY6Q.js} +2 -2
- package/dist/{chunk-AJZ3EJB5.js → chunk-IJAXOQJU.js} +2 -2
- package/dist/{chunk-EQRVOMMS.js → chunk-KMIDRUUH.js} +2 -2
- package/dist/{chunk-BBHVV37T.js → chunk-MSAGTFN4.js} +4 -4
- package/dist/chunk-OBKVNZPH.js +70 -0
- package/dist/chunk-OBKVNZPH.js.map +1 -0
- package/dist/{chunk-75ZIWV4U.js → chunk-QAF7ZTO3.js} +4 -4
- package/dist/{chunk-TJ4DYKF2.js → chunk-XG6FODYO.js} +3 -2
- package/dist/chunk-XG6FODYO.js.map +1 -0
- package/dist/{chunk-6O2NQ7WD.js → chunk-Y2SOQOJE.js} +3 -3
- package/dist/integrations-react/index.js +1 -1
- package/dist/{mention-editor-ZJAOUDEE.js → mention-editor-NOS5R3AU.js} +2 -2
- package/dist/preset-cloudflare/index.js +2 -2
- package/dist/sandbox/index.js +4 -4
- package/dist/settings-react/confirm-action.d.ts +51 -0
- package/dist/settings-react/delete-workspace-section.d.ts +31 -0
- package/dist/settings-react/export-section.d.ts +26 -0
- package/dist/settings-react/index.d.ts +20 -0
- package/dist/settings-react/index.js +1438 -0
- package/dist/settings-react/index.js.map +1 -0
- package/dist/settings-react/members-section.d.ts +66 -0
- package/dist/settings-react/save-status.d.ts +24 -0
- package/dist/settings-react/setting-outcome.d.ts +33 -0
- package/dist/settings-react/settings-layout.d.ts +71 -0
- package/dist/settings-react/settings-save-bar.d.ts +26 -0
- package/dist/settings-react/timezone-picker.d.ts +17 -0
- package/dist/settings-react/use-setting-field.d.ts +70 -0
- package/dist/stories/settings/settings-backend.d.ts +66 -0
- package/dist/stories/settings/settings-demo.d.ts +16 -0
- package/dist/stories/settings/team-panels-demo.d.ts +21 -0
- package/dist/studio-react/index.js +2 -2
- package/dist/teams-react/components/InviteForm.d.ts +2 -2
- package/dist/teams-react/components/MembersPanel.d.ts +9 -5
- package/dist/teams-react/components/RoleSelect.d.ts +10 -8
- package/dist/teams-react/components/invitation-detail.d.ts +8 -0
- package/dist/teams-react/components/member-access.d.ts +17 -0
- package/dist/teams-react/contracts.d.ts +2 -0
- package/dist/teams-react/index.js +119 -242
- package/dist/teams-react/index.js.map +1 -1
- package/dist/theme/tokens.css +43 -2
- package/dist/tools/index.js +4 -4
- package/dist/web-react/agent-profile-editor.js +4 -4
- package/dist/web-react/async/index.js +1 -1
- package/dist/web-react/controls.d.ts +4 -5
- package/dist/web-react/index.js +12 -12
- package/dist/work-product/index.js +2 -2
- package/dist/workspace-export/react.d.ts +26 -0
- package/dist/workspace-export/react.js +6 -169
- package/dist/workspace-export/react.js.map +1 -1
- package/dist/workspace-react/index.js +3 -3
- package/package.json +9 -4
- package/dist/chunk-TJ4DYKF2.js.map +0 -1
- /package/dist/{chunk-YXLN4PXK.js.map → chunk-2RCPPOQ4.js.map} +0 -0
- /package/dist/{chunk-YESFGM56.js.map → chunk-5IS3GCMR.js.map} +0 -0
- /package/dist/{chunk-3RHAF2P5.js.map → chunk-A3CUVYRZ.js.map} +0 -0
- /package/dist/{chunk-UDLA3NGY.js.map → chunk-GNBBY3KN.js.map} +0 -0
- /package/dist/{chunk-KOTNMTHV.js.map → chunk-HCFVEJQL.js.map} +0 -0
- /package/dist/{chunk-YGBEGBJY.js.map → chunk-HEPEGY6Q.js.map} +0 -0
- /package/dist/{chunk-AJZ3EJB5.js.map → chunk-IJAXOQJU.js.map} +0 -0
- /package/dist/{chunk-EQRVOMMS.js.map → chunk-KMIDRUUH.js.map} +0 -0
- /package/dist/{chunk-BBHVV37T.js.map → chunk-MSAGTFN4.js.map} +0 -0
- /package/dist/{chunk-75ZIWV4U.js.map → chunk-QAF7ZTO3.js.map} +0 -0
- /package/dist/{chunk-6O2NQ7WD.js.map → chunk-Y2SOQOJE.js.map} +0 -0
- /package/dist/{mention-editor-ZJAOUDEE.js.map → mention-editor-NOS5R3AU.js.map} +0 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RoleSelect,
|
|
3
|
+
canManageMember,
|
|
4
|
+
invitationDetail,
|
|
5
|
+
isCurrentMember,
|
|
6
|
+
memberRoleLabel
|
|
7
|
+
} from "../chunk-OBKVNZPH.js";
|
|
1
8
|
import {
|
|
2
9
|
INVITATION_EMAIL_HINT,
|
|
3
10
|
isInvitationEmail
|
|
@@ -6,94 +13,19 @@ import {
|
|
|
6
13
|
hasWorkspaceRole
|
|
7
14
|
} from "../chunk-6XIAPIW6.js";
|
|
8
15
|
|
|
16
|
+
// src/teams-react/components/MembersPanel.tsx
|
|
17
|
+
import { Button as Button2, Heading } from "@tangle-network/ui/primitives";
|
|
18
|
+
|
|
9
19
|
// src/teams-react/components/InviteForm.tsx
|
|
10
20
|
import { Button, Input } from "@tangle-network/ui/primitives";
|
|
11
|
-
import { useId, useState
|
|
12
|
-
|
|
13
|
-
// src/teams-react/components/RoleSelect.tsx
|
|
14
|
-
import { useEffect, useRef, useState } from "react";
|
|
21
|
+
import { useId, useState } from "react";
|
|
15
22
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
var ASSIGNABLE_ROLES = [
|
|
17
|
-
{ value: "viewer", label: "Viewer", description: "Can read everything" },
|
|
18
|
-
{ value: "editor", label: "Editor", description: "Can also chat and edit" },
|
|
19
|
-
{ value: "admin", label: "Admin", description: "Can also manage settings and people" }
|
|
20
|
-
];
|
|
21
|
-
function ChevronDownGlyph({ className }) {
|
|
22
|
-
return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
|
|
23
|
-
}
|
|
24
|
-
function RoleSelect({ value, onChange, ariaLabel, disabled }) {
|
|
25
|
-
const [open, setOpen] = useState(false);
|
|
26
|
-
const ref = useRef(null);
|
|
27
|
-
const current = ASSIGNABLE_ROLES.find((option) => option.value === value);
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
if (!open) return;
|
|
30
|
-
function onDocPointer(event) {
|
|
31
|
-
if (ref.current && !ref.current.contains(event.target)) setOpen(false);
|
|
32
|
-
}
|
|
33
|
-
function onKey(event) {
|
|
34
|
-
if (event.key === "Escape") setOpen(false);
|
|
35
|
-
}
|
|
36
|
-
document.addEventListener("pointerdown", onDocPointer);
|
|
37
|
-
document.addEventListener("keydown", onKey);
|
|
38
|
-
return () => {
|
|
39
|
-
document.removeEventListener("pointerdown", onDocPointer);
|
|
40
|
-
document.removeEventListener("keydown", onKey);
|
|
41
|
-
};
|
|
42
|
-
}, [open]);
|
|
43
|
-
return /* @__PURE__ */ jsxs("div", { ref, className: "relative", children: [
|
|
44
|
-
/* @__PURE__ */ jsxs(
|
|
45
|
-
"button",
|
|
46
|
-
{
|
|
47
|
-
type: "button",
|
|
48
|
-
disabled,
|
|
49
|
-
"aria-haspopup": "listbox",
|
|
50
|
-
"aria-expanded": open,
|
|
51
|
-
"aria-label": ariaLabel,
|
|
52
|
-
onClick: () => setOpen((v) => !v),
|
|
53
|
-
className: "flex items-center justify-between gap-1.5 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-1.5 text-sm text-[var(--text-secondary)] hover:border-[var(--brand-primary)] disabled:cursor-default disabled:opacity-40",
|
|
54
|
-
children: [
|
|
55
|
-
/* @__PURE__ */ jsx("span", { children: current?.label ?? value }),
|
|
56
|
-
/* @__PURE__ */ jsx(ChevronDownGlyph, { className: "h-3 w-3 text-[var(--text-muted)]" })
|
|
57
|
-
]
|
|
58
|
-
}
|
|
59
|
-
),
|
|
60
|
-
open ? /* @__PURE__ */ jsx(
|
|
61
|
-
"div",
|
|
62
|
-
{
|
|
63
|
-
role: "listbox",
|
|
64
|
-
"aria-label": ariaLabel,
|
|
65
|
-
className: "absolute right-0 top-full z-50 mt-1 flex w-64 flex-col rounded border border-[var(--card-edge)] bg-[hsl(var(--popover))] py-1 shadow-[var(--shadow-overlay)]",
|
|
66
|
-
children: ASSIGNABLE_ROLES.map((option) => /* @__PURE__ */ jsxs(
|
|
67
|
-
"button",
|
|
68
|
-
{
|
|
69
|
-
type: "button",
|
|
70
|
-
role: "option",
|
|
71
|
-
"aria-selected": option.value === value,
|
|
72
|
-
onClick: () => {
|
|
73
|
-
onChange(option.value);
|
|
74
|
-
setOpen(false);
|
|
75
|
-
},
|
|
76
|
-
className: `flex flex-col px-3 py-2 text-left text-sm hover:bg-[color-mix(in_srgb,var(--brand-primary)_10%,transparent)] ${option.value === value ? "text-[var(--brand-primary)]" : "text-[var(--text-primary)]"}`,
|
|
77
|
-
children: [
|
|
78
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label }),
|
|
79
|
-
/* @__PURE__ */ jsx("span", { className: "text-[var(--text-muted)]", children: option.description })
|
|
80
|
-
]
|
|
81
|
-
},
|
|
82
|
-
option.value
|
|
83
|
-
))
|
|
84
|
-
}
|
|
85
|
-
) : null
|
|
86
|
-
] });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/teams-react/components/InviteForm.tsx
|
|
90
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
91
23
|
function InviteForm({ label, placeholder, onInvite }) {
|
|
92
24
|
const id = useId();
|
|
93
|
-
const [email, setEmail] =
|
|
94
|
-
const [role, setRole] =
|
|
95
|
-
const [inviting, setInviting] =
|
|
96
|
-
const [checked, setChecked] =
|
|
25
|
+
const [email, setEmail] = useState("");
|
|
26
|
+
const [role, setRole] = useState("editor");
|
|
27
|
+
const [inviting, setInviting] = useState(false);
|
|
28
|
+
const [checked, setChecked] = useState(false);
|
|
97
29
|
const valid = isInvitationEmail(email);
|
|
98
30
|
const showHint = checked && email.trim() !== "" && !valid;
|
|
99
31
|
async function submit() {
|
|
@@ -112,10 +44,10 @@ function InviteForm({ label, placeholder, onInvite }) {
|
|
|
112
44
|
setInviting(false);
|
|
113
45
|
}
|
|
114
46
|
}
|
|
115
|
-
return /* @__PURE__ */
|
|
116
|
-
/* @__PURE__ */
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
/* @__PURE__ */
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", { className: "@container/invite flex flex-col gap-1.5", children: [
|
|
48
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `${id}-email`, className: "text-sm font-medium text-[var(--text-secondary)]", children: label }),
|
|
49
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
119
51
|
Input,
|
|
120
52
|
{
|
|
121
53
|
id: `${id}-email`,
|
|
@@ -137,20 +69,19 @@ function InviteForm({ label, placeholder, onInvite }) {
|
|
|
137
69
|
className: "min-w-[12rem] flex-1"
|
|
138
70
|
}
|
|
139
71
|
),
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
-
|
|
142
|
-
/* @__PURE__ */ jsx2(Button, { type: "button", onClick: () => void submit(), disabled: inviting || !valid, children: inviting ? "Inviting\u2026" : "Invite" })
|
|
143
|
-
] })
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "w-72 shrink-0 @max-[36rem]/invite:w-full", children: /* @__PURE__ */ jsx(RoleSelect, { value: role, ariaLabel: "Invite role", onChange: setRole }) }),
|
|
73
|
+
/* @__PURE__ */ jsx(Button, { type: "button", className: "ml-auto", onClick: () => void submit(), disabled: inviting || !valid, children: inviting ? "Inviting\u2026" : "Invite" })
|
|
144
74
|
] }),
|
|
145
|
-
showHint && /* @__PURE__ */
|
|
75
|
+
showHint && /* @__PURE__ */ jsx("p", { id: `${id}-hint`, role: "alert", className: "text-sm text-[var(--surface-danger-text)]", children: INVITATION_EMAIL_HINT })
|
|
146
76
|
] });
|
|
147
77
|
}
|
|
148
78
|
|
|
149
79
|
// src/teams-react/components/MembersPanel.tsx
|
|
150
|
-
import { Fragment, jsx as
|
|
80
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
151
81
|
function MembersPanel({
|
|
152
82
|
members,
|
|
153
83
|
currentRole,
|
|
84
|
+
currentUserId,
|
|
154
85
|
onInvite,
|
|
155
86
|
onChangeRole,
|
|
156
87
|
onRemove,
|
|
@@ -187,73 +118,67 @@ function MembersPanel({
|
|
|
187
118
|
notify("error", err instanceof Error ? err.message : "Failed to remove member");
|
|
188
119
|
}
|
|
189
120
|
}
|
|
190
|
-
return /* @__PURE__ */
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
193
|
-
/* @__PURE__ */
|
|
121
|
+
return /* @__PURE__ */ jsxs2("section", { className: "@container/members flex flex-col gap-4", children: [
|
|
122
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between", children: [
|
|
123
|
+
/* @__PURE__ */ jsx2(Heading, { as: "h4", variant: "subsection", children: "Members" }),
|
|
124
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-sm text-[var(--text-muted)]", children: [
|
|
194
125
|
members.length,
|
|
195
126
|
" total"
|
|
196
127
|
] })
|
|
197
128
|
] }),
|
|
198
|
-
/* @__PURE__ */
|
|
199
|
-
members.map((member) => /* @__PURE__ */
|
|
129
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2", children: [
|
|
130
|
+
members.map((member) => /* @__PURE__ */ jsx2(
|
|
200
131
|
MemberRow,
|
|
201
132
|
{
|
|
202
133
|
member,
|
|
203
|
-
|
|
134
|
+
editable: canManageMember(member, currentRole, currentUserId),
|
|
135
|
+
self: isCurrentMember(member, currentUserId),
|
|
204
136
|
onChangeRole: changeRole,
|
|
205
137
|
onRemove: remove
|
|
206
138
|
},
|
|
207
139
|
member.id
|
|
208
140
|
)),
|
|
209
|
-
members.length === 0 && /* @__PURE__ */
|
|
141
|
+
members.length === 0 && /* @__PURE__ */ jsx2("p", { className: "text-sm text-[var(--text-muted)]", children: "No team members yet." })
|
|
210
142
|
] }),
|
|
211
|
-
canManage && showInviteForm && /* @__PURE__ */
|
|
143
|
+
canManage && showInviteForm && /* @__PURE__ */ jsx2("div", { className: "border-t border-[var(--border-default)] pt-3", children: /* @__PURE__ */ jsx2(InviteForm, { label: "Invite member", placeholder: "Email address", onInvite: invite }) })
|
|
212
144
|
] });
|
|
213
145
|
}
|
|
214
|
-
function MemberRow({ member,
|
|
146
|
+
function MemberRow({ member, editable, self, onChangeRole, onRemove }) {
|
|
215
147
|
const pending = member.acceptedAt == null;
|
|
216
148
|
const label = member.name ?? member.email ?? "Unknown";
|
|
217
149
|
const initial = (member.name?.[0] ?? member.email?.[0] ?? "?").toUpperCase();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
150
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-[var(--border-default)] py-2 last:border-0", children: [
|
|
151
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 items-center gap-3 @max-[36rem]/members:basis-40", children: [
|
|
152
|
+
/* @__PURE__ */ jsx2("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--bg-input)] text-sm font-semibold text-[var(--text-secondary)]", children: initial }),
|
|
153
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
|
|
154
|
+
/* @__PURE__ */ jsxs2("p", { className: "flex flex-wrap items-center gap-x-2 text-sm font-medium text-[var(--text-primary)]", children: [
|
|
155
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0 [overflow-wrap:anywhere]", children: [
|
|
156
|
+
label,
|
|
157
|
+
self && /* @__PURE__ */ jsx2("span", { className: "font-normal text-[var(--text-muted)]", children: " (you)" })
|
|
158
|
+
] }),
|
|
159
|
+
pending && /* @__PURE__ */ jsx2("span", { className: "rounded border border-[var(--border-default)] px-1.5 py-0.5 text-sm font-medium text-[var(--text-muted)]", children: "Pending" })
|
|
227
160
|
] }),
|
|
228
|
-
member.name && member.email && /* @__PURE__ */
|
|
161
|
+
member.name && member.email && /* @__PURE__ */ jsx2("p", { className: "text-sm text-[var(--text-muted)] [overflow-wrap:anywhere]", children: member.email })
|
|
229
162
|
] })
|
|
230
163
|
] }),
|
|
231
|
-
|
|
232
|
-
/* @__PURE__ */
|
|
164
|
+
editable ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
165
|
+
/* @__PURE__ */ jsx2("div", { className: "w-72 shrink-0 @max-[36rem]/members:order-last @max-[36rem]/members:w-full", children: /* @__PURE__ */ jsx2(
|
|
233
166
|
RoleSelect,
|
|
234
167
|
{
|
|
235
168
|
value: member.role,
|
|
236
169
|
ariaLabel: `Role for ${label}`,
|
|
237
170
|
onChange: (role) => onChangeRole(member.id, role)
|
|
238
171
|
}
|
|
239
|
-
),
|
|
240
|
-
/* @__PURE__ */
|
|
241
|
-
|
|
242
|
-
{
|
|
243
|
-
type: "button",
|
|
244
|
-
"aria-label": `Remove ${label}`,
|
|
245
|
-
onClick: () => onRemove(member.id),
|
|
246
|
-
className: "rounded px-2 py-1 text-sm text-[var(--text-danger)] hover:bg-[var(--border-default)]",
|
|
247
|
-
children: "Remove"
|
|
248
|
-
}
|
|
249
|
-
)
|
|
250
|
-
] }) : /* @__PURE__ */ jsx3("span", { className: "rounded border border-[var(--border-default)] px-2 py-0.5 text-sm capitalize text-[var(--text-secondary)]", children: member.role }) })
|
|
172
|
+
) }),
|
|
173
|
+
/* @__PURE__ */ jsx2(Button2, { type: "button", variant: "destructive-outline", "aria-label": `Remove ${label}`, onClick: () => onRemove(member.id), children: "Remove" })
|
|
174
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "ml-auto rounded border border-[var(--border-default)] px-2 py-0.5 text-sm text-[var(--text-secondary)]", children: memberRoleLabel(member) })
|
|
251
175
|
] });
|
|
252
176
|
}
|
|
253
177
|
|
|
254
178
|
// src/teams-react/components/InvitationsPanel.tsx
|
|
255
|
-
import {
|
|
256
|
-
import {
|
|
179
|
+
import { Button as Button3, Heading as Heading2 } from "@tangle-network/ui/primitives";
|
|
180
|
+
import { useState as useState2 } from "react";
|
|
181
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
257
182
|
var BADGE_BASE = "inline-flex items-center rounded border px-2 py-0.5 text-sm font-medium";
|
|
258
183
|
var STATUS = {
|
|
259
184
|
accepted: { label: "Joined", tone: "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" },
|
|
@@ -261,27 +186,6 @@ var STATUS = {
|
|
|
261
186
|
revoked: { label: "Revoked", tone: "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]" },
|
|
262
187
|
expired: { label: "Expired", tone: "border-[var(--border-default)] text-[var(--text-muted)]" }
|
|
263
188
|
};
|
|
264
|
-
function capitalize(text) {
|
|
265
|
-
return text.length === 0 ? text : text[0].toUpperCase() + text.slice(1);
|
|
266
|
-
}
|
|
267
|
-
function shortDate(value) {
|
|
268
|
-
return new Date(value).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
269
|
-
}
|
|
270
|
-
function invitationDetail(invitation) {
|
|
271
|
-
const role = capitalize(invitation.permissions);
|
|
272
|
-
switch (invitation.status) {
|
|
273
|
-
case "accepted":
|
|
274
|
-
return invitation.acceptedAt ? `${role} \xB7 joined ${shortDate(invitation.acceptedAt)}` : role;
|
|
275
|
-
case "pending": {
|
|
276
|
-
const delivery = invitation.emailStatus === "sent" ? "email sent" : invitation.emailStatus === "not_sent" ? "email not sent yet" : null;
|
|
277
|
-
return [role, delivery, `expires ${shortDate(invitation.expiresAt)}`].filter(Boolean).join(" \xB7 ");
|
|
278
|
-
}
|
|
279
|
-
case "expired":
|
|
280
|
-
return `${role} \xB7 expired ${shortDate(invitation.expiresAt)}`;
|
|
281
|
-
case "revoked":
|
|
282
|
-
return role;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
189
|
function InvitationsPanel({
|
|
286
190
|
invitations,
|
|
287
191
|
currentRole,
|
|
@@ -291,7 +195,7 @@ function InvitationsPanel({
|
|
|
291
195
|
onCopy,
|
|
292
196
|
onNotice
|
|
293
197
|
}) {
|
|
294
|
-
const [busyId, setBusyId] =
|
|
198
|
+
const [busyId, setBusyId] = useState2(null);
|
|
295
199
|
const canManage = hasWorkspaceRole(currentRole, "admin");
|
|
296
200
|
function notify(kind, message) {
|
|
297
201
|
onNotice?.({ kind, message });
|
|
@@ -337,17 +241,17 @@ function InvitationsPanel({
|
|
|
337
241
|
setBusyId(null);
|
|
338
242
|
}
|
|
339
243
|
}
|
|
340
|
-
return /* @__PURE__ */
|
|
341
|
-
canManage && /* @__PURE__ */
|
|
342
|
-
/* @__PURE__ */
|
|
343
|
-
/* @__PURE__ */
|
|
344
|
-
/* @__PURE__ */
|
|
345
|
-
/* @__PURE__ */
|
|
244
|
+
return /* @__PURE__ */ jsxs3("section", { className: "flex flex-col gap-4", children: [
|
|
245
|
+
canManage && /* @__PURE__ */ jsx3(InviteForm, { label: "Invite by email", placeholder: "colleague@example.com", onInvite: invite }),
|
|
246
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2 border-t border-[var(--border-default)] pt-3", children: [
|
|
247
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
|
|
248
|
+
/* @__PURE__ */ jsx3(Heading2, { as: "h4", variant: "subsection", children: "Invitation history" }),
|
|
249
|
+
/* @__PURE__ */ jsxs3("span", { className: "text-sm text-[var(--text-muted)]", children: [
|
|
346
250
|
invitations.length,
|
|
347
251
|
" total"
|
|
348
252
|
] })
|
|
349
253
|
] }),
|
|
350
|
-
invitations.length === 0 ? /* @__PURE__ */
|
|
254
|
+
invitations.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "text-sm text-[var(--text-muted)]", children: "No invitations yet." }) : invitations.map((invitation) => /* @__PURE__ */ jsx3(
|
|
351
255
|
InvitationRow,
|
|
352
256
|
{
|
|
353
257
|
invitation,
|
|
@@ -365,58 +269,31 @@ function InvitationsPanel({
|
|
|
365
269
|
function InvitationRow({ invitation, canManage, busy, onCopy, onResend, onRevoke }) {
|
|
366
270
|
const isPending = invitation.status === "pending";
|
|
367
271
|
const status = STATUS[invitation.status];
|
|
368
|
-
return /* @__PURE__ */
|
|
369
|
-
/* @__PURE__ */
|
|
370
|
-
/* @__PURE__ */
|
|
371
|
-
/* @__PURE__ */
|
|
372
|
-
/* @__PURE__ */
|
|
373
|
-
isPending && invitation.emailStatus === "failed" && /* @__PURE__ */
|
|
272
|
+
return /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-[var(--border-default)] bg-[var(--bg-input)] p-3", children: [
|
|
273
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between gap-3", children: [
|
|
274
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
275
|
+
/* @__PURE__ */ jsx3("p", { className: "truncate text-sm font-medium text-[var(--text-primary)]", title: invitation.email, children: invitation.email }),
|
|
276
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm text-[var(--text-muted)]", children: invitationDetail(invitation) }),
|
|
277
|
+
isPending && invitation.emailStatus === "failed" && /* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-[var(--surface-danger-text)]", children: "The email was not delivered. Copy the link and send it yourself." })
|
|
374
278
|
] }),
|
|
375
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ jsx3("span", { className: `${BADGE_BASE} ${status.tone} shrink-0`, children: status.label })
|
|
376
280
|
] }),
|
|
377
|
-
canManage && isPending && /* @__PURE__ */
|
|
378
|
-
/* @__PURE__ */
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
type: "button",
|
|
382
|
-
onClick: onCopy,
|
|
383
|
-
disabled: busy,
|
|
384
|
-
className: "rounded border border-[var(--border-default)] px-2.5 py-1 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] disabled:opacity-50",
|
|
385
|
-
children: "Copy link"
|
|
386
|
-
}
|
|
387
|
-
),
|
|
388
|
-
/* @__PURE__ */ jsx4(
|
|
389
|
-
"button",
|
|
390
|
-
{
|
|
391
|
-
type: "button",
|
|
392
|
-
onClick: onResend,
|
|
393
|
-
disabled: busy,
|
|
394
|
-
className: "rounded border border-[var(--border-default)] px-2.5 py-1 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] disabled:opacity-50",
|
|
395
|
-
children: busy ? "Working\u2026" : "Resend"
|
|
396
|
-
}
|
|
397
|
-
),
|
|
398
|
-
/* @__PURE__ */ jsx4(
|
|
399
|
-
"button",
|
|
400
|
-
{
|
|
401
|
-
type: "button",
|
|
402
|
-
onClick: onRevoke,
|
|
403
|
-
disabled: busy,
|
|
404
|
-
className: "rounded px-2.5 py-1 text-sm text-[var(--text-danger)] hover:bg-[var(--border-default)] disabled:opacity-50",
|
|
405
|
-
children: "Revoke"
|
|
406
|
-
}
|
|
407
|
-
)
|
|
281
|
+
canManage && isPending && /* @__PURE__ */ jsxs3("div", { className: "mt-3 flex flex-wrap items-center justify-end gap-2", children: [
|
|
282
|
+
/* @__PURE__ */ jsx3(Button3, { type: "button", variant: "outline", onClick: onCopy, disabled: busy, children: "Copy link" }),
|
|
283
|
+
/* @__PURE__ */ jsx3(Button3, { type: "button", variant: "outline", onClick: onResend, disabled: busy, children: busy ? "Working\u2026" : "Resend" }),
|
|
284
|
+
/* @__PURE__ */ jsx3(Button3, { type: "button", variant: "destructive-outline", onClick: onRevoke, disabled: busy, children: "Revoke" })
|
|
408
285
|
] })
|
|
409
286
|
] });
|
|
410
287
|
}
|
|
411
288
|
|
|
412
289
|
// src/teams-react/components/InviteAcceptPage.tsx
|
|
413
|
-
import { useState as
|
|
290
|
+
import { useState as useState3 } from "react";
|
|
414
291
|
|
|
415
292
|
// src/teams-react/components/BrandMark.tsx
|
|
416
293
|
import { lazy, Suspense } from "react";
|
|
417
|
-
import { jsx as
|
|
294
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
418
295
|
function MarkSpacer({ size }) {
|
|
419
|
-
return /* @__PURE__ */
|
|
296
|
+
return /* @__PURE__ */ jsx4("span", { "aria-hidden": true, style: { display: "inline-block", width: size, height: size } });
|
|
420
297
|
}
|
|
421
298
|
var LazyKnot = lazy(async () => {
|
|
422
299
|
try {
|
|
@@ -427,57 +304,57 @@ var LazyKnot = lazy(async () => {
|
|
|
427
304
|
}
|
|
428
305
|
});
|
|
429
306
|
function BrandMark({ size, className }) {
|
|
430
|
-
return /* @__PURE__ */
|
|
307
|
+
return /* @__PURE__ */ jsx4(Suspense, { fallback: /* @__PURE__ */ jsx4(MarkSpacer, { size }), children: /* @__PURE__ */ jsx4(LazyKnot, { size, className }) });
|
|
431
308
|
}
|
|
432
309
|
|
|
433
310
|
// src/teams-react/components/InviteAcceptPage.tsx
|
|
434
|
-
import { jsx as
|
|
311
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
435
312
|
function InviteAcceptPage({ details, onAccept, onNavigate, onResendVerification }) {
|
|
436
|
-
const [accepting, setAccepting] =
|
|
437
|
-
const [acceptError, setAcceptError] =
|
|
438
|
-
const [accepted, setAccepted] =
|
|
439
|
-
const [resendingVerification, setResendingVerification] =
|
|
440
|
-
const [verificationSent, setVerificationSent] =
|
|
313
|
+
const [accepting, setAccepting] = useState3(false);
|
|
314
|
+
const [acceptError, setAcceptError] = useState3(null);
|
|
315
|
+
const [accepted, setAccepted] = useState3(false);
|
|
316
|
+
const [resendingVerification, setResendingVerification] = useState3(false);
|
|
317
|
+
const [verificationSent, setVerificationSent] = useState3(false);
|
|
441
318
|
if (details.status === "invalid") {
|
|
442
|
-
return /* @__PURE__ */
|
|
319
|
+
return /* @__PURE__ */ jsx5(Shell, { title: "Invalid invitation", body: "This link is invalid or already used. Ask the workspace admin to send a new one.", children: /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "sign-in" }), children: "Go to sign in" }) });
|
|
443
320
|
}
|
|
444
321
|
if (details.status === "already-accepted") {
|
|
445
|
-
return /* @__PURE__ */
|
|
322
|
+
return /* @__PURE__ */ jsx5(Shell, { title: "Already accepted", body: "This invitation has already been accepted.", children: /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "open-app" }), children: "Open workspace" }) });
|
|
446
323
|
}
|
|
447
324
|
if (details.status === "expired") {
|
|
448
|
-
return /* @__PURE__ */
|
|
325
|
+
return /* @__PURE__ */ jsx5(Shell, { title: "Invitation expired", body: "This invitation has expired. Ask the workspace admin to send a new one.", children: /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "sign-in" }), children: "Go to sign in" }) });
|
|
449
326
|
}
|
|
450
327
|
if (details.status === "revoked") {
|
|
451
|
-
return /* @__PURE__ */
|
|
328
|
+
return /* @__PURE__ */ jsx5(Shell, { title: "Invitation revoked", body: "This invitation has been revoked. Ask the workspace admin to send a new one.", children: /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "sign-in" }), children: "Go to sign in" }) });
|
|
452
329
|
}
|
|
453
330
|
const workspaceName = details.workspaceName ?? "a workspace";
|
|
454
331
|
const inviterPrefix = details.inviterName ? `${details.inviterName} invited you` : "You've been invited";
|
|
455
332
|
const roleSuffix = details.role ? ` as ${details.role}` : "";
|
|
456
333
|
if (!details.currentUserEmail) {
|
|
457
|
-
return /* @__PURE__ */
|
|
458
|
-
/* @__PURE__ */
|
|
334
|
+
return /* @__PURE__ */ jsxs4(Shell, { title: "You've been invited", children: [
|
|
335
|
+
/* @__PURE__ */ jsxs4("p", { className: "mb-4 text-sm text-[var(--text-secondary)]", children: [
|
|
459
336
|
inviterPrefix,
|
|
460
337
|
" to join ",
|
|
461
|
-
/* @__PURE__ */
|
|
338
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-[var(--text-primary)]", children: workspaceName }),
|
|
462
339
|
roleSuffix,
|
|
463
340
|
"."
|
|
464
341
|
] }),
|
|
465
|
-
details.inviteEmail && /* @__PURE__ */
|
|
342
|
+
details.inviteEmail && /* @__PURE__ */ jsxs4("p", { className: "mb-6 text-sm text-[var(--text-secondary)]", children: [
|
|
466
343
|
"Sign in or create an account with",
|
|
467
344
|
" ",
|
|
468
|
-
/* @__PURE__ */
|
|
345
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-[var(--text-primary)]", children: details.inviteEmail }),
|
|
469
346
|
" to accept."
|
|
470
347
|
] }),
|
|
471
|
-
/* @__PURE__ */
|
|
472
|
-
/* @__PURE__ */
|
|
473
|
-
/* @__PURE__ */
|
|
348
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
|
|
349
|
+
/* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "sign-in" }), children: "Sign in" }),
|
|
350
|
+
/* @__PURE__ */ jsx5(SecondaryButton, { onClick: () => onNavigate({ kind: "sign-up" }), children: "Create account" })
|
|
474
351
|
] })
|
|
475
352
|
] });
|
|
476
353
|
}
|
|
477
354
|
if (accepted) {
|
|
478
|
-
return /* @__PURE__ */
|
|
355
|
+
return /* @__PURE__ */ jsx5(Shell, { title: "Welcome!", children: /* @__PURE__ */ jsxs4("p", { className: "text-sm text-[var(--text-secondary)]", children: [
|
|
479
356
|
"You've joined ",
|
|
480
|
-
/* @__PURE__ */
|
|
357
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-[var(--text-primary)]", children: workspaceName }),
|
|
481
358
|
"."
|
|
482
359
|
] }) });
|
|
483
360
|
}
|
|
@@ -511,36 +388,36 @@ function InviteAcceptPage({ details, onAccept, onNavigate, onResendVerification
|
|
|
511
388
|
setResendingVerification(false);
|
|
512
389
|
}
|
|
513
390
|
}
|
|
514
|
-
return /* @__PURE__ */
|
|
515
|
-
/* @__PURE__ */
|
|
391
|
+
return /* @__PURE__ */ jsxs4(Shell, { title: "Join workspace", children: [
|
|
392
|
+
/* @__PURE__ */ jsxs4("p", { className: "mb-4 text-sm text-[var(--text-secondary)]", children: [
|
|
516
393
|
inviterPrefix,
|
|
517
394
|
" to join ",
|
|
518
|
-
/* @__PURE__ */
|
|
395
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-[var(--text-primary)]", children: workspaceName }),
|
|
519
396
|
roleSuffix,
|
|
520
397
|
"."
|
|
521
398
|
] }),
|
|
522
|
-
/* @__PURE__ */
|
|
399
|
+
/* @__PURE__ */ jsxs4("p", { className: "mb-4 text-sm text-[var(--text-secondary)]", children: [
|
|
523
400
|
"Signed in as ",
|
|
524
|
-
/* @__PURE__ */
|
|
401
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-[var(--text-primary)]", children: details.currentUserEmail })
|
|
525
402
|
] }),
|
|
526
|
-
expiryLabel && /* @__PURE__ */
|
|
403
|
+
expiryLabel && /* @__PURE__ */ jsxs4("p", { className: "mb-4 text-xs text-[var(--text-muted)]", children: [
|
|
527
404
|
"This invitation expires on ",
|
|
528
405
|
expiryLabel,
|
|
529
406
|
"."
|
|
530
407
|
] }),
|
|
531
|
-
emailMismatch && /* @__PURE__ */
|
|
408
|
+
emailMismatch && /* @__PURE__ */ jsxs4(
|
|
532
409
|
"div",
|
|
533
410
|
{
|
|
534
411
|
role: "alert",
|
|
535
412
|
className: "mb-4 rounded-md border border-[var(--border-default)] px-4 py-2 text-sm text-[var(--text-warning)]",
|
|
536
413
|
children: [
|
|
537
414
|
"This invitation was sent to ",
|
|
538
|
-
/* @__PURE__ */
|
|
415
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium", children: details.inviteEmail }),
|
|
539
416
|
". Switch to that account to accept it."
|
|
540
417
|
]
|
|
541
418
|
}
|
|
542
419
|
),
|
|
543
|
-
needsVerification && /* @__PURE__ */
|
|
420
|
+
needsVerification && /* @__PURE__ */ jsx5(
|
|
544
421
|
"div",
|
|
545
422
|
{
|
|
546
423
|
role: "alert",
|
|
@@ -548,33 +425,33 @@ function InviteAcceptPage({ details, onAccept, onNavigate, onResendVerification
|
|
|
548
425
|
children: verificationSent ? "Verification email sent \u2014 check your inbox, then refresh this page to accept." : "Verify your email address before you can accept this invitation."
|
|
549
426
|
}
|
|
550
427
|
),
|
|
551
|
-
acceptError && /* @__PURE__ */
|
|
552
|
-
/* @__PURE__ */
|
|
553
|
-
emailMismatch ? /* @__PURE__ */
|
|
428
|
+
acceptError && /* @__PURE__ */ jsx5("p", { role: "alert", className: "mb-4 text-sm text-[var(--text-danger)]", children: acceptError }),
|
|
429
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
|
|
430
|
+
emailMismatch ? /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "switch-account" }), children: "Switch account" }) : needsVerification ? onResendVerification ? /* @__PURE__ */ jsx5(
|
|
554
431
|
PrimaryButton,
|
|
555
432
|
{
|
|
556
433
|
onClick: () => void handleResendVerification(),
|
|
557
434
|
disabled: resendingVerification || verificationSent,
|
|
558
435
|
children: verificationSent ? "Verification sent" : resendingVerification ? "Sending\u2026" : "Resend verification email"
|
|
559
436
|
}
|
|
560
|
-
) : /* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
437
|
+
) : /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => onNavigate({ kind: "open-app" }), children: "Open app" }) : /* @__PURE__ */ jsx5(PrimaryButton, { onClick: () => void handleAccept(), disabled: accepting, children: accepting ? "Accepting\u2026" : "Accept invitation" }),
|
|
438
|
+
/* @__PURE__ */ jsx5(SecondaryButton, { onClick: () => onNavigate({ kind: "open-app" }), children: "Not now" })
|
|
562
439
|
] })
|
|
563
440
|
] });
|
|
564
441
|
}
|
|
565
442
|
function Shell({ title, body, children }) {
|
|
566
|
-
return /* @__PURE__ */
|
|
567
|
-
/* @__PURE__ */
|
|
568
|
-
/* @__PURE__ */
|
|
569
|
-
/* @__PURE__ */
|
|
443
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-auto flex w-full max-w-sm flex-col", children: [
|
|
444
|
+
/* @__PURE__ */ jsxs4("span", { className: "mb-4 flex items-center gap-2 text-[var(--text-muted)]", children: [
|
|
445
|
+
/* @__PURE__ */ jsx5(BrandMark, { size: 22, className: "shrink-0" }),
|
|
446
|
+
/* @__PURE__ */ jsx5("span", { className: "text-xs font-semibold uppercase tracking-[0.05em]", children: "Tangle Teams" })
|
|
570
447
|
] }),
|
|
571
|
-
/* @__PURE__ */
|
|
572
|
-
body && /* @__PURE__ */
|
|
448
|
+
/* @__PURE__ */ jsx5("h1", { className: "mb-1 text-xl font-semibold tracking-tight text-[var(--text-primary)]", children: title }),
|
|
449
|
+
body && /* @__PURE__ */ jsx5("p", { className: "mb-6 text-sm text-[var(--text-secondary)]", children: body }),
|
|
573
450
|
children
|
|
574
451
|
] });
|
|
575
452
|
}
|
|
576
453
|
function PrimaryButton({ children, onClick, disabled }) {
|
|
577
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ jsx5(
|
|
578
455
|
"button",
|
|
579
456
|
{
|
|
580
457
|
type: "button",
|
|
@@ -586,7 +463,7 @@ function PrimaryButton({ children, onClick, disabled }) {
|
|
|
586
463
|
);
|
|
587
464
|
}
|
|
588
465
|
function SecondaryButton({ children, onClick }) {
|
|
589
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsx5(
|
|
590
467
|
"button",
|
|
591
468
|
{
|
|
592
469
|
type: "button",
|