@streamoid/settings 0.6.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -93,9 +93,19 @@ function dataOf(value) {
93
93
  async function loadWorkspaceOrganization(workspaceId, request, signal) {
94
94
  const rows = dataOf(await request("/workspace", signal));
95
95
  if (!Array.isArray(rows)) throw new Error("Invalid workspace list");
96
- const row = rows.find((item) => (item.workspace?._id ?? item._id) === workspaceId);
97
- if (!row) throw new Error("Workspace not found");
98
- const workspace = row.workspace ?? row;
96
+ let row = rows.find((item) => (item.workspace?._id ?? item._id) === workspaceId);
97
+ let workspace = row?.workspace ?? row;
98
+ const ownerId = workspace?.organizationId ?? row?.organizationId;
99
+ const ownerName = workspace?.organizationName ?? row?.organizationName ?? workspace?.organization?.name ?? row?.organization?.name;
100
+ const explicitlyUnowned = workspace?.organizationId === null || workspace?.organization === null;
101
+ if (!workspace || !explicitlyUnowned && ownerId && !ownerName) {
102
+ const detail2 = dataOf(await request(`/workspace/${encodeURIComponent(workspaceId)}`, signal));
103
+ if (!detail2 || (detail2.workspace?._id ?? detail2._id) !== workspaceId) {
104
+ throw new Error("Workspace not found");
105
+ }
106
+ row = detail2;
107
+ workspace = row.workspace ?? row;
108
+ }
99
109
  const owner = workspace.organization !== void 0 ? workspace.organization : row.organization;
100
110
  const ownerRef = workspace.organizationId !== void 0 ? workspace.organizationId : row.organizationId;
101
111
  if (ownerRef === null || owner === null) return null;
@@ -178,10 +188,10 @@ import {
178
188
  SiconBilling,
179
189
  SiconBookOpen,
180
190
  SiconExternalLink as SiconExternalLink2,
181
- SiconSettings,
191
+ SiconSettings as SiconSettings2,
182
192
  SiconRight as SiconRight2,
183
193
  SiconLeft as SiconLeft3,
184
- SiconUserAdd as SiconUserAdd3,
194
+ SiconUserAdd as SiconUserAdd2,
185
195
  SiconLock,
186
196
  SiconDown,
187
197
  SiconGlobe as SiconGlobe3,
@@ -385,8 +395,9 @@ function WorkspaceModal({
385
395
  let cancelled = false;
386
396
  organizationAdapter.list().then((orgs) => {
387
397
  if (cancelled) return;
388
- setAvailableOrgs(orgs);
389
- setSelectedOrgId((prev) => prev || orgs[0]?._id || "");
398
+ const joinable = orgs.filter((org) => org.role !== "guest");
399
+ setAvailableOrgs(joinable);
400
+ setSelectedOrgId((prev) => prev || joinable[0]?._id || "");
390
401
  }).catch(() => {
391
402
  if (!cancelled) setAvailableOrgs([]);
392
403
  });
@@ -501,7 +512,7 @@ function WorkspaceModal({
501
512
  async function handleLeaveOrganization() {
502
513
  if (orgActionSubmitting || !workspaceAdapter.leaveOrganization) return;
503
514
  const confirmed = window.confirm(
504
- "Leave this organization? Members of the organization will lose any implicit access to this workspace."
515
+ "Take this workspace out of the organization? It will no longer be listed in the workspace picker, and org admins will lose access unless they are members."
505
516
  );
506
517
  if (!confirmed) return;
507
518
  setOrgActionSubmitting(true);
@@ -846,7 +857,7 @@ function WorkspaceModal({
846
857
  color: active ? "#ffffff" : T.muted,
847
858
  textAlign: "center"
848
859
  },
849
- children: opt === "private" ? "Private" : "Visible to organization"
860
+ children: opt === "private" ? "Private" : "Listed in picker"
850
861
  }
851
862
  ) })
852
863
  },
@@ -1597,7 +1608,7 @@ var TAB_TO_URL = {
1597
1608
  workspaceList: "workspace/all",
1598
1609
  organization: "organization/people",
1599
1610
  organizationWorkspaces: "organization/workspaces",
1600
- organizationDomains: "organization/domains",
1611
+ organizationDomains: "organization/workspaces",
1601
1612
  referral: "referral",
1602
1613
  billing: "billing",
1603
1614
  apikey: "api-keys"
@@ -1609,7 +1620,8 @@ var URL_TO_TAB = {
1609
1620
  "workspace/all": "workspaceList",
1610
1621
  "organization/people": "organization",
1611
1622
  "organization/workspaces": "organizationWorkspaces",
1612
- "organization/domains": "organizationDomains",
1623
+ /* The Domains tab is gone; its join requests live under Workspaces. */
1624
+ "organization/domains": "organizationWorkspaces",
1613
1625
  /* Unscoped destinations. */
1614
1626
  account: "profile",
1615
1627
  referral: "referral",
@@ -1628,7 +1640,7 @@ var TAB_LABELS = {
1628
1640
  workspaceList: "My workspaces",
1629
1641
  organization: "People",
1630
1642
  organizationWorkspaces: "Workspaces",
1631
- organizationDomains: "Domains & requests",
1643
+ organizationDomains: "Workspaces",
1632
1644
  referral: "Referral",
1633
1645
  /* "Billing & usage", not "Billing". The tab has held usage history as well
1634
1646
  as the plan and invoices since the credits work, and hosts had started
@@ -1642,9 +1654,9 @@ var TAB_DESCRIPTIONS = {
1642
1654
  workspace: "Rename or re-brand this workspace, or leave and delete it",
1643
1655
  workspaceMembers: "Invite people to this workspace and control which apps they can use",
1644
1656
  workspaceList: "Switch between your workspaces, or start a new one",
1645
- organization: "Everyone in the organization, and the invites still waiting to be accepted",
1646
- organizationWorkspaces: "Every workspace that sits under this organization",
1647
- organizationDomains: "Auto-join by email domain, and workspaces asking to join the organization",
1657
+ organization: "Everyone in the organization and their role",
1658
+ organizationWorkspaces: "Every workspace in this organization, and workspaces asking to join it",
1659
+ organizationDomains: "Every workspace in this organization, and workspaces asking to join it",
1648
1660
  referral: "Invite friends to Streamoid and track the rewards you have earned",
1649
1661
  billing: "Workspace plan, credits, invoices and usage history",
1650
1662
  apikey: "Create and revoke keys for calling the Streamoid APIs"
@@ -2263,7 +2275,7 @@ function OrganizationAffiliationCard({
2263
2275
  style: { gap: T5.spMd, opacity: submitting ? 0.6 : 1 },
2264
2276
  children: [
2265
2277
  workspaceAdapter.setOrgVisibility && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-start w-full", style: { gap: T5.spXs }, children: [
2266
- /* @__PURE__ */ jsx10(FieldLabel, { children: "Who in the organization can see this workspace" }),
2278
+ /* @__PURE__ */ jsx10(FieldLabel, { children: "List this workspace in the organization's workspace picker" }),
2267
2279
  /* @__PURE__ */ jsx10(
2268
2280
  "div",
2269
2281
  {
@@ -2294,11 +2306,11 @@ function OrganizationAffiliationCard({
2294
2306
  if (active || !workspaceAdapter.setOrgVisibility) return;
2295
2307
  void run(
2296
2308
  () => workspaceAdapter.setOrgVisibility(opt),
2297
- opt === "private" ? "Workspace is now private" : "Workspace is now visible to the organization",
2309
+ opt === "private" ? "Workspace is now private" : "Workspace is now listed in the workspace picker",
2298
2310
  "Failed to change visibility"
2299
2311
  );
2300
2312
  },
2301
- children: opt === "private" ? "Only workspace members" : "Everyone in the organization"
2313
+ children: opt === "private" ? "Private (invite only)" : "Listed in the workspace picker"
2302
2314
  },
2303
2315
  opt
2304
2316
  );
@@ -2324,7 +2336,7 @@ function OrganizationAffiliationCard({
2324
2336
  },
2325
2337
  onClick: () => {
2326
2338
  const confirmed = window.confirm(
2327
- "Leave this organization? Members of the organization will lose any implicit access to this workspace."
2339
+ "Take this workspace out of the organization? It will no longer be listed in the workspace picker, and org admins will lose access unless they are members."
2328
2340
  );
2329
2341
  if (!confirmed || !workspaceAdapter.leaveOrganization) return;
2330
2342
  void run(
@@ -2731,12 +2743,13 @@ function InviteUpdateModal({
2731
2743
  organizationName,
2732
2744
  allowGuestStanding = true,
2733
2745
  initialOrganizationStanding = "guest",
2746
+ organizationDomain,
2734
2747
  onInvite
2735
2748
  }) {
2736
2749
  useOverlayOpen(open, onClose);
2737
2750
  const [emailValue, setEmailValue] = useState6("");
2738
2751
  const [hasChanges, setHasChanges] = useState6(false);
2739
- const [role, setRole] = useState6("admin");
2752
+ const [role, setRole] = useState6("member");
2740
2753
  const [orgStanding, setOrgStanding] = useState6(
2741
2754
  initialOrganizationStanding
2742
2755
  );
@@ -2775,7 +2788,7 @@ function InviteUpdateModal({
2775
2788
  if (!open) {
2776
2789
  setEmailValue("");
2777
2790
  setHasChanges(false);
2778
- setRole("admin");
2791
+ setRole("member");
2779
2792
  setOrgStanding(initialOrganizationStanding);
2780
2793
  setCanUseCredits(true);
2781
2794
  setCanInviteUser(true);
@@ -2787,6 +2800,14 @@ function InviteUpdateModal({
2787
2800
  setSelectedStores(/* @__PURE__ */ new Set());
2788
2801
  }
2789
2802
  }, [open, initialPermissions, hiddenKey, initialOrganizationStanding]);
2803
+ const orgDomain = (organizationDomain || "").trim().toLowerCase();
2804
+ const inviteeDomains = emailValue.split(/[\s,;]+/).map((email) => email.trim().toLowerCase().split("@")[1] || "").filter(Boolean);
2805
+ const inviteeIsGuest = mode === "invite" && inviteeDomains.some(
2806
+ (domain) => !(orgDomain && domain === orgDomain) && (showOrganizationStanding ? orgStanding === "guest" : !!orgDomain)
2807
+ );
2808
+ useEffect6(() => {
2809
+ if (inviteeIsGuest && role === "admin") setRole("member");
2810
+ }, [inviteeIsGuest, role]);
2790
2811
  if (!open) return null;
2791
2812
  const isInvite = mode === "invite";
2792
2813
  const hasEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailValue.trim());
@@ -2977,12 +2998,15 @@ function InviteUpdateModal({
2977
2998
  /* @__PURE__ */ jsx12(
2978
2999
  "div",
2979
3000
  {
2980
- className: "flex-1 min-w-0 cursor-pointer",
3001
+ className: `flex-1 min-w-0 ${inviteeIsGuest ? "cursor-not-allowed" : "cursor-pointer"}`,
3002
+ "aria-disabled": inviteeIsGuest,
2981
3003
  style: {
2982
3004
  background: role === "admin" ? T6.neutral300 : "transparent",
2983
- borderRadius: T6.rMd
3005
+ borderRadius: T6.rMd,
3006
+ opacity: inviteeIsGuest ? 0.4 : 1
2984
3007
  },
2985
3008
  onClick: () => {
3009
+ if (inviteeIsGuest) return;
2986
3010
  setRole("admin");
2987
3011
  setCanUseCredits(true);
2988
3012
  setCanInviteUser(true);
@@ -3056,6 +3080,19 @@ function InviteUpdateModal({
3056
3080
  ) })
3057
3081
  ]
3058
3082
  }
3083
+ ),
3084
+ inviteeIsGuest && /* @__PURE__ */ jsx12(
3085
+ "span",
3086
+ {
3087
+ style: {
3088
+ fontFamily: T6.font,
3089
+ fontSize: T6.fsXs,
3090
+ fontWeight: 400,
3091
+ lineHeight: T6.lhXs,
3092
+ color: T6.tertiary
3093
+ },
3094
+ children: "Guests can only be Members."
3095
+ }
3059
3096
  )
3060
3097
  ]
3061
3098
  }
@@ -3245,7 +3282,7 @@ function InviteUpdateModal({
3245
3282
  lineHeight: T6.lhXs,
3246
3283
  color: T6.tertiary
3247
3284
  },
3248
- children: orgStanding === "colleague" ? `Joins ${organizationName || "the organization"} as a member \u2014 they'll also see its shared workspaces.` : `This workspace only. They see nothing else in ${organizationName || "the organization"}.`
3285
+ children: orgStanding === "colleague" ? `Joins ${organizationName || "the organization"} as a member \u2014 they can also join its shared workspaces.` : `This workspace only, as a member. They see nothing else in ${organizationName || "the organization"}.`
3249
3286
  }
3250
3287
  )
3251
3288
  ]
@@ -3940,7 +3977,19 @@ function MemberListToolbar({
3940
3977
  className: "flex flex-wrap items-center justify-between shrink-0 w-full",
3941
3978
  style: { gap: "var(--spacing-md)" },
3942
3979
  children: [
3943
- /* @__PURE__ */ jsx13(
3980
+ pendingCount === void 0 ? /* @__PURE__ */ jsx13(
3981
+ "span",
3982
+ {
3983
+ style: {
3984
+ fontFamily: T7.font,
3985
+ fontSize: T7.fsSm,
3986
+ fontWeight: 500,
3987
+ lineHeight: T7.lhSm,
3988
+ color: T7.primary
3989
+ },
3990
+ children: withCount(activeLabel, activeCount)
3991
+ }
3992
+ ) : /* @__PURE__ */ jsx13(
3944
3993
  ScTabSwitcher,
3945
3994
  {
3946
3995
  tabCount: "2",
@@ -4906,9 +4955,9 @@ function TeamsContent({
4906
4955
  lineHeight: "var(--line-height-line-height-xs)"
4907
4956
  },
4908
4957
  children: [
4909
- "This workspace is visible to everyone in ",
4958
+ "Anyone in ",
4910
4959
  organizationName,
4911
- ", and its admins keep access whether or not they are listed here. Change that under Workspace \u203A General."
4960
+ " can join this workspace as a member from the workspace picker, and its org admins keep access whether or not they are listed here. Change that under Workspace \u203A General."
4912
4961
  ]
4913
4962
  }
4914
4963
  ),
@@ -4990,6 +5039,7 @@ function TeamsContent({
4990
5039
  ),
4991
5040
  showOrganizationStanding: mayGrantOrgMembership,
4992
5041
  organizationName: organizationName ?? orgCurrent?.name,
5042
+ organizationDomain: workspaceOrgId && orgCurrent?.id === workspaceOrgId ? orgCurrent?.domain : void 0,
4993
5043
  onInvite: handleInvite
4994
5044
  }
4995
5045
  )
@@ -5058,13 +5108,13 @@ function TeamsContent({
5058
5108
  // src/organization-content.tsx
5059
5109
  import { useCallback as useCallback3, useEffect as useEffect10, useState as useState10 } from "react";
5060
5110
  import { ScButton as ScButton5 } from "@streamoid/ui";
5061
- import { SiconUserAdd as SiconUserAdd2, SiconGlobe as SiconGlobe2 } from "@streamoid/icons";
5111
+ import { SiconCheck, SiconCopy, SiconGlobe as SiconGlobe2, SiconSettings } from "@streamoid/icons";
5062
5112
 
5063
- // src/organization-invite-modal.tsx
5113
+ // src/organization-member-modal.tsx
5064
5114
  import { useEffect as useEffect8, useState as useState8 } from "react";
5065
5115
  import { ScButton as ScButton4 } from "@streamoid/ui";
5066
5116
  import { SiconClose as SiconClose3 } from "@streamoid/icons";
5067
- import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
5117
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
5068
5118
  var T9 = {
5069
5119
  primary: "var(--alias-text---icons-primary)",
5070
5120
  tertiary: "var(--alias-text---icons-tertiary)",
@@ -5091,33 +5141,6 @@ var T9 = {
5091
5141
  r4xl: "var(--radius-4xl)",
5092
5142
  neutral300: "var(--primitives-neutral-300)"
5093
5143
  };
5094
- function CheckboxSvg2({ checked }) {
5095
- return /* @__PURE__ */ jsx15("div", { className: "relative shrink-0", style: { width: 24, height: 24 }, children: /* @__PURE__ */ jsx15("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: checked ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
5096
- /* @__PURE__ */ jsx15(
5097
- "rect",
5098
- {
5099
- x: "0.75",
5100
- y: "0.75",
5101
- width: "22.5",
5102
- height: "22.5",
5103
- rx: "5.65",
5104
- fill: T9.primary,
5105
- stroke: T9.primary,
5106
- strokeWidth: "1.5"
5107
- }
5108
- ),
5109
- /* @__PURE__ */ jsx15(
5110
- "path",
5111
- {
5112
- d: "M7 12.5L10.5 16L17 8",
5113
- stroke: T9.inverse,
5114
- strokeWidth: "1.5",
5115
- strokeLinecap: "round",
5116
- strokeLinejoin: "round"
5117
- }
5118
- )
5119
- ] }) : /* @__PURE__ */ jsx15("path", { d: svg_rodctpja6f_default.p4792500, fill: T9.muted }) }) });
5120
- }
5121
5144
  function FieldLabel3({ text }) {
5122
5145
  return /* @__PURE__ */ jsx15("div", { className: "flex items-center shrink-0 w-full", style: { height: 24 }, children: /* @__PURE__ */ jsx15(
5123
5146
  "div",
@@ -5193,69 +5216,29 @@ function SegmentedToggle({
5193
5216
  }
5194
5217
  );
5195
5218
  }
5196
- function OrganizationInviteModal({
5219
+ function OrganizationMemberModal({
5197
5220
  open,
5198
- mode,
5199
5221
  userEmail = "email@domain.in",
5200
5222
  initialRole,
5201
5223
  lockRole,
5202
- canClaimDomain = true,
5203
- claimableDomain,
5204
5224
  lockedRoleLabel,
5205
- initialInviteAccess,
5206
- allowSubmitWithoutChanges = false,
5207
5225
  canRemove = true,
5208
5226
  onClose,
5209
- onInviteEmail,
5210
- onInviteDomain,
5211
5227
  onUpdate,
5212
5228
  onRemove
5213
5229
  }) {
5214
5230
  useOverlayOpen(open, onClose);
5215
- const [inviteMode, setInviteMode] = useState8("email");
5216
- const [emailValue, setEmailValue] = useState8("");
5217
- const [domainValue, setDomainValue] = useState8(claimableDomain ?? "");
5218
5231
  const [hasChanges, setHasChanges] = useState8(false);
5219
- const [role, setRole] = useState8("admin");
5220
- const [inviteAccess, setInviteAccess] = useState8(false);
5232
+ const [role, setRole] = useState8("member");
5221
5233
  useEffect8(() => {
5222
- if (open && mode === "update") {
5234
+ if (open) {
5223
5235
  setRole(initialRole ?? "member");
5224
- setInviteAccess(initialInviteAccess ?? false);
5225
- }
5226
- if (!open) {
5227
- setInviteMode("email");
5228
- setEmailValue("");
5229
- setDomainValue(claimableDomain ?? "");
5236
+ } else {
5230
5237
  setHasChanges(false);
5231
- setRole("admin");
5232
- setInviteAccess(true);
5233
5238
  }
5234
- }, [open, mode, initialRole, initialInviteAccess, claimableDomain]);
5239
+ }, [open, initialRole]);
5235
5240
  if (!open) return null;
5236
- const isInvite = mode === "invite";
5237
- const isEmailInvite = isInvite && inviteMode === "email";
5238
- const isDomainInvite = isInvite && inviteMode === "domain";
5239
- const hasEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailValue.trim());
5240
- const hasDomain = /^[^\s@]+\.[^\s@]+$/.test(domainValue.trim());
5241
- const isSubmitDisabled = isEmailInvite ? !hasEmail : isDomainInvite ? !hasDomain : (
5242
- // A locked role has nothing this modal can legitimately submit.
5243
- lockRole || !(allowSubmitWithoutChanges || hasChanges)
5244
- );
5245
- function markChanged() {
5246
- setHasChanges(true);
5247
- }
5248
- function handleSubmit() {
5249
- if (isEmailInvite) {
5250
- onInviteEmail?.({ email: emailValue.trim(), role, inviteAccess });
5251
- return;
5252
- }
5253
- if (isDomainInvite) {
5254
- onInviteDomain?.({ domain: domainValue.trim(), autoJoinRole: role });
5255
- return;
5256
- }
5257
- onUpdate?.({ role, inviteAccess });
5258
- }
5241
+ const isSubmitDisabled = lockRole || !hasChanges;
5259
5242
  return /* @__PURE__ */ jsx15(
5260
5243
  "div",
5261
5244
  {
@@ -5273,6 +5256,7 @@ function OrganizationInviteModal({
5273
5256
  borderRadius: T9.r4xl,
5274
5257
  border: `1px solid ${T9.borderSubtle}`,
5275
5258
  width: 480,
5259
+ maxWidth: "calc(100vw - 32px)",
5276
5260
  maxHeight: "85vh"
5277
5261
  },
5278
5262
  children: [
@@ -5302,7 +5286,7 @@ function OrganizationInviteModal({
5302
5286
  fontWeight: 600,
5303
5287
  lineHeight: T9.lhLg
5304
5288
  },
5305
- children: isInvite ? "Invite to organization" : "Update member"
5289
+ children: "Update member"
5306
5290
  }
5307
5291
  ),
5308
5292
  /* @__PURE__ */ jsx15("div", { className: "shrink-0 cursor-pointer", onClick: onClose, children: /* @__PURE__ */ jsx15(SiconClose3, { className: "w-6 h-6", color: T9.primary }) })
@@ -5316,116 +5300,41 @@ function OrganizationInviteModal({
5316
5300
  className: "flex flex-col items-start w-full",
5317
5301
  style: { padding: `${T9.sp3xl} ${T9.sp6xl}`, gap: T9.sp3xl },
5318
5302
  children: [
5319
- isInvite && canClaimDomain && /* @__PURE__ */ jsxs12(
5320
- "div",
5321
- {
5322
- className: "flex flex-col items-start justify-center shrink-0 w-full",
5323
- style: { gap: T9.spXs },
5324
- children: [
5325
- /* @__PURE__ */ jsx15(FieldLabel3, { text: "Invite by" }),
5326
- /* @__PURE__ */ jsx15(
5327
- SegmentedToggle,
5328
- {
5329
- options: [
5330
- { value: "email", label: "Email" },
5331
- { value: "domain", label: "Domain" }
5332
- ],
5333
- value: inviteMode,
5334
- onChange: setInviteMode
5335
- }
5336
- )
5337
- ]
5338
- }
5339
- ),
5340
5303
  /* @__PURE__ */ jsxs12(
5341
5304
  "div",
5342
5305
  {
5343
5306
  className: "flex flex-col items-start justify-center shrink-0 w-full",
5344
5307
  style: { gap: T9.spXs },
5345
5308
  children: [
5346
- /* @__PURE__ */ jsx15(
5347
- FieldLabel3,
5348
- {
5349
- text: isDomainInvite ? "Domain" : isEmailInvite ? "Email ID" : "Email ID"
5350
- }
5351
- ),
5309
+ /* @__PURE__ */ jsx15(FieldLabel3, { text: "Email ID" }),
5352
5310
  /* @__PURE__ */ jsx15(
5353
5311
  "div",
5354
5312
  {
5355
5313
  className: "shrink-0 w-full",
5356
5314
  style: { background: T9.fillPlus, height: 48, borderRadius: T9.r3xl },
5357
- children: /* @__PURE__ */ jsx15("div", { className: "flex flex-row items-center size-full", children: /* @__PURE__ */ jsxs12(
5315
+ children: /* @__PURE__ */ jsx15("div", { className: "flex flex-row items-center size-full", children: /* @__PURE__ */ jsx15(
5358
5316
  "div",
5359
5317
  {
5360
5318
  className: "flex items-center relative size-full",
5361
5319
  style: { padding: `${T9.spXl} ${T9.sp3xl}` },
5362
- children: [
5363
- isEmailInvite && /* @__PURE__ */ jsx15(
5364
- "input",
5365
- {
5366
- className: "flex-1 min-w-0 bg-transparent border-none outline-none",
5367
- style: {
5368
- fontFamily: T9.font,
5369
- fontSize: T9.fsSm,
5370
- fontWeight: 400,
5371
- lineHeight: T9.lhSm,
5372
- color: T9.primary
5373
- },
5374
- placeholder: "email@domain.in",
5375
- value: emailValue,
5376
- onChange: (e) => setEmailValue(e.target.value)
5377
- }
5378
- ),
5379
- isDomainInvite && /* @__PURE__ */ jsx15(
5380
- "span",
5381
- {
5382
- className: "flex-1 min-w-0 truncate",
5383
- style: {
5384
- fontFamily: T9.font,
5385
- fontSize: T9.fsSm,
5386
- fontWeight: 400,
5387
- lineHeight: T9.lhSm,
5388
- color: T9.primary
5389
- },
5390
- children: domainValue
5391
- }
5392
- ),
5393
- !isInvite && /* @__PURE__ */ jsx15(
5394
- "div",
5395
- {
5396
- className: "flex-1 flex flex-col justify-center",
5397
- style: {
5398
- fontFamily: T9.font,
5399
- fontSize: T9.fsSm,
5400
- fontWeight: 400,
5401
- lineHeight: T9.lhSm,
5402
- color: T9.muted,
5403
- opacity: 0.6
5404
- },
5405
- children: userEmail
5406
- }
5407
- )
5408
- ]
5320
+ children: /* @__PURE__ */ jsx15(
5321
+ "div",
5322
+ {
5323
+ className: "flex-1 flex flex-col justify-center truncate",
5324
+ style: {
5325
+ fontFamily: T9.font,
5326
+ fontSize: T9.fsSm,
5327
+ fontWeight: 400,
5328
+ lineHeight: T9.lhSm,
5329
+ color: T9.muted,
5330
+ opacity: 0.6
5331
+ },
5332
+ children: userEmail
5333
+ }
5334
+ )
5409
5335
  }
5410
5336
  ) })
5411
5337
  }
5412
- ),
5413
- isDomainInvite && /* @__PURE__ */ jsxs12(
5414
- "span",
5415
- {
5416
- style: {
5417
- fontFamily: T9.font,
5418
- fontSize: T9.fsSm,
5419
- fontWeight: 400,
5420
- color: T9.muted
5421
- },
5422
- children: [
5423
- "Anyone who signs up or logs in with an @",
5424
- domainValue.trim(),
5425
- " ",
5426
- "address will automatically join this organization from now on."
5427
- ]
5428
- }
5429
5338
  )
5430
5339
  ]
5431
5340
  }
@@ -5436,7 +5345,7 @@ function OrganizationInviteModal({
5436
5345
  className: "flex flex-col items-start justify-center shrink-0 w-full",
5437
5346
  style: { gap: T9.spXs },
5438
5347
  children: [
5439
- /* @__PURE__ */ jsx15(FieldLabel3, { text: isDomainInvite ? "Auto-join role" : "Role" }),
5348
+ /* @__PURE__ */ jsx15(FieldLabel3, { text: "Role" }),
5440
5349
  lockRole ? /* @__PURE__ */ jsxs12(
5441
5350
  "span",
5442
5351
  {
@@ -5448,49 +5357,33 @@ function OrganizationInviteModal({
5448
5357
  },
5449
5358
  children: [
5450
5359
  lockedRoleLabel || "Guest",
5451
- " \u2014 invited to specific workspaces only, with no access to the rest of the organization. Remove them to end that access."
5360
+ " \u2014 invited to specific workspaces only, with no access to the rest of the organization. Guests can't be made members or admins. Remove them to end that access."
5452
5361
  ]
5453
5362
  }
5454
5363
  ) : /* @__PURE__ */ jsx15(
5455
5364
  SegmentedToggle,
5456
5365
  {
5457
5366
  options: [
5458
- { value: "admin", label: "Admin" },
5367
+ { value: "admin", label: "Org admin" },
5459
5368
  { value: "member", label: "Member" }
5460
5369
  ],
5461
5370
  value: role,
5462
5371
  onChange: (v) => {
5463
5372
  setRole(v);
5464
- if (v === "admin") setInviteAccess(true);
5465
- markChanged();
5373
+ setHasChanges(v !== (initialRole ?? "member"));
5466
5374
  }
5467
5375
  }
5468
- )
5469
- ]
5470
- }
5471
- ),
5472
- !isDomainInvite && !lockRole && role === "member" && /* @__PURE__ */ jsxs12(
5473
- "div",
5474
- {
5475
- className: "flex items-center shrink-0 w-full cursor-pointer",
5476
- style: { gap: T9.spMd },
5477
- onClick: () => {
5478
- setInviteAccess(!inviteAccess);
5479
- markChanged();
5480
- },
5481
- children: [
5482
- /* @__PURE__ */ jsx15(CheckboxSvg2, { checked: inviteAccess }),
5483
- /* @__PURE__ */ jsx15(
5376
+ ),
5377
+ !lockRole && /* @__PURE__ */ jsx15(
5484
5378
  "span",
5485
5379
  {
5486
5380
  style: {
5487
5381
  fontFamily: T9.font,
5488
5382
  fontSize: T9.fsSm,
5489
- fontWeight: 400,
5490
5383
  lineHeight: T9.lhSm,
5491
- color: T9.primary
5384
+ color: T9.muted
5492
5385
  },
5493
- children: "Can invite members"
5386
+ children: "Org admins can see and manage every workspace in the organization."
5494
5387
  }
5495
5388
  )
5496
5389
  ]
@@ -5511,10 +5404,10 @@ function OrganizationInviteModal({
5511
5404
  /* @__PURE__ */ jsx15("div", { className: "flex flex-row items-center size-full", children: /* @__PURE__ */ jsxs12(
5512
5405
  "div",
5513
5406
  {
5514
- className: `flex items-center w-full ${isInvite ? "justify-end" : "justify-between"}`,
5407
+ className: "flex items-center w-full justify-between",
5515
5408
  style: { padding: `${T9.sp3xl} ${T9.sp6xl}` },
5516
5409
  children: [
5517
- !isInvite && /* @__PURE__ */ jsx15(
5410
+ /* @__PURE__ */ jsx15(
5518
5411
  ScButton4,
5519
5412
  {
5520
5413
  text: "Remove member",
@@ -5527,11 +5420,11 @@ function OrganizationInviteModal({
5527
5420
  /* @__PURE__ */ jsx15(
5528
5421
  ScButton4,
5529
5422
  {
5530
- text: isEmailInvite ? "Send invite" : isDomainInvite ? "Add domain" : allowSubmitWithoutChanges ? "Resend invite" : "Save changes",
5423
+ text: "Save changes",
5531
5424
  variant: "primary",
5532
5425
  size: "md",
5533
5426
  state: isSubmitDisabled ? "disabled" : "default",
5534
- onClick: !isSubmitDisabled ? handleSubmit : void 0
5427
+ onClick: !isSubmitDisabled ? () => onUpdate?.({ role }) : void 0
5535
5428
  }
5536
5429
  )
5537
5430
  ]
@@ -5547,7 +5440,7 @@ function OrganizationInviteModal({
5547
5440
 
5548
5441
  // src/organization-modal.tsx
5549
5442
  import { useState as useState9, useRef as useRef5, useEffect as useEffect9 } from "react";
5550
- import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
5443
+ import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
5551
5444
  var T10 = {
5552
5445
  primary: "var(--alias-text---icons-primary)",
5553
5446
  muted: "var(--alias-text---icons-muted)",
@@ -5841,7 +5734,7 @@ function OrganizationModal({
5841
5734
  height: 120
5842
5735
  },
5843
5736
  onClick: () => !hasImage && fileInputRef.current?.click(),
5844
- children: /* @__PURE__ */ jsx16("div", { className: "flex items-center justify-center size-full", style: { padding: `var(--spacing-lg) ${T10.spXl}`, gap: T10.spMd }, children: hasImage ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
5737
+ children: /* @__PURE__ */ jsx16("div", { className: "flex items-center justify-center size-full", style: { padding: `var(--spacing-lg) ${T10.spXl}`, gap: T10.spMd }, children: hasImage ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
5845
5738
  /* @__PURE__ */ jsx16(
5846
5739
  "div",
5847
5740
  {
@@ -5876,7 +5769,7 @@ function OrganizationModal({
5876
5769
  e.stopPropagation();
5877
5770
  handleRemoveImage();
5878
5771
  }, children: /* @__PURE__ */ jsx16(CloseIcon4, { color: "var(--primitives-error-500)" }) })
5879
- ] }) : /* @__PURE__ */ jsxs13(Fragment8, { children: [
5772
+ ] }) : /* @__PURE__ */ jsxs13(Fragment7, { children: [
5880
5773
  /* @__PURE__ */ jsx16(UploadIcon2, {}),
5881
5774
  /* @__PURE__ */ jsx16(
5882
5775
  "span",
@@ -5982,7 +5875,7 @@ function OrganizationModal({
5982
5875
  }
5983
5876
 
5984
5877
  // src/organization-content.tsx
5985
- import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
5878
+ import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
5986
5879
  function orgRoleLabel(role) {
5987
5880
  if (role === "admin") return "Org admin";
5988
5881
  if (role === "member") return "Member";
@@ -6025,20 +5918,6 @@ function formatDate(iso) {
6025
5918
  return iso;
6026
5919
  }
6027
5920
  }
6028
- function toDisplayText2(value, fallback = "\u2013") {
6029
- if (typeof value === "string") {
6030
- const trimmed = value.trim();
6031
- return trimmed.length > 0 ? trimmed : fallback;
6032
- }
6033
- if (value && typeof value === "object") {
6034
- const record = value;
6035
- const name = typeof record.name === "string" ? record.name.trim() : "";
6036
- if (name) return name;
6037
- const email = typeof record.email === "string" ? record.email.trim() : "";
6038
- if (email) return email;
6039
- }
6040
- return fallback;
6041
- }
6042
5921
  function VisibilityBadge({ visibility }) {
6043
5922
  const isShared = visibility === "shared";
6044
5923
  return /* @__PURE__ */ jsx17(
@@ -6059,10 +5938,46 @@ function VisibilityBadge({ visibility }) {
6059
5938
  }
6060
5939
  );
6061
5940
  }
5941
+ function RowIconButton({
5942
+ label,
5943
+ onClick,
5944
+ children,
5945
+ visible = true
5946
+ }) {
5947
+ return /* @__PURE__ */ jsx17(
5948
+ "button",
5949
+ {
5950
+ type: "button",
5951
+ "aria-label": label,
5952
+ title: label,
5953
+ className: "flex items-center justify-center shrink-0 cursor-pointer border-none",
5954
+ style: {
5955
+ width: 32,
5956
+ height: 32,
5957
+ borderRadius: T11.rLg,
5958
+ background: "transparent",
5959
+ opacity: visible ? 1 : 0,
5960
+ transition: "opacity 120ms ease"
5961
+ },
5962
+ onMouseEnter: (e) => {
5963
+ e.currentTarget.style.background = T11.fillPlus;
5964
+ },
5965
+ onMouseLeave: (e) => {
5966
+ e.currentTarget.style.background = "transparent";
5967
+ },
5968
+ onClick,
5969
+ children
5970
+ }
5971
+ );
5972
+ }
6062
5973
  function MemberRow({
6063
5974
  member,
6064
- onClick
5975
+ onEdit,
5976
+ onCopyEmail
6065
5977
  }) {
5978
+ const [copied, setCopied] = useState10(false);
5979
+ const [active, setActive] = useState10(false);
5980
+ const noHover = typeof window !== "undefined" && window.matchMedia?.("(hover: none)").matches === true;
6066
5981
  const name = member.user.name?.trim();
6067
5982
  const email = member.user.email || "";
6068
5983
  const displayIdent = name || email.split("@")[0] || "user";
@@ -6074,18 +5989,20 @@ function MemberRow({
6074
5989
  return /* @__PURE__ */ jsxs14(
6075
5990
  "div",
6076
5991
  {
6077
- className: `flex items-center self-stretch shrink-0 ${onClick ? "cursor-pointer" : "cursor-default"}`,
5992
+ className: "flex items-center self-stretch shrink-0 cursor-default",
6078
5993
  style: {
6079
5994
  borderBottom: `1px solid ${T11.borderSubtle}`,
6080
5995
  padding: `${T11.sp5xl} ${T11.sp3xl}`,
6081
- gap: T11.sp6xl
6082
- },
6083
- onClick,
6084
- onMouseEnter: (e) => {
6085
- if (onClick) e.currentTarget.style.background = T11.fillPlus;
5996
+ gap: T11.sp6xl,
5997
+ background: active && onEdit ? T11.fillPlus : "transparent"
6086
5998
  },
6087
- onMouseLeave: (e) => {
6088
- e.currentTarget.style.background = "transparent";
5999
+ onMouseEnter: () => setActive(true),
6000
+ onMouseLeave: () => setActive(false),
6001
+ onFocus: () => setActive(true),
6002
+ onBlur: (e) => {
6003
+ if (!e.currentTarget.contains(e.relatedTarget)) {
6004
+ setActive(false);
6005
+ }
6089
6006
  },
6090
6007
  children: [
6091
6008
  /* @__PURE__ */ jsxs14(
@@ -6164,112 +6081,29 @@ function MemberRow({
6164
6081
  },
6165
6082
  children: formatDate(member.createdAt || member.user.createdAt)
6166
6083
  }
6167
- )
6168
- ]
6169
- }
6170
- );
6171
- }
6172
- function InviteRow({
6173
- invite,
6174
- onCancel,
6175
- onResend
6176
- }) {
6177
- const isDomain = invite.kind === "domain";
6178
- const invitedByText = (() => {
6179
- if (!invite.invitedBy) return "\u2013";
6180
- if (typeof invite.invitedBy === "string") return invite.invitedBy;
6181
- return invite.invitedBy.name || invite.invitedBy.email || "\u2013";
6182
- })();
6183
- const role = isDomain ? invite.autoJoinRole : invite.role;
6184
- return /* @__PURE__ */ jsxs14(
6185
- "div",
6186
- {
6187
- className: "flex items-center self-stretch shrink-0",
6188
- style: {
6189
- borderBottom: `1px solid ${T11.borderSubtle}`,
6190
- padding: `${T11.sp5xl} ${T11.sp3xl}`,
6191
- gap: T11.sp6xl
6192
- },
6193
- children: [
6194
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center min-w-0", style: { flex: 1, gap: T11.spMd }, children: [
6195
- isDomain ? /* @__PURE__ */ jsx17(
6196
- "div",
6197
- {
6198
- className: "shrink-0 flex items-center justify-center",
6199
- style: {
6200
- width: 32,
6201
- height: 32,
6202
- borderRadius: T11.rXl,
6203
- background: T11.fillNeutral
6204
- },
6205
- children: /* @__PURE__ */ jsx17(SiconGlobe2, { className: "w-4 h-4", color: T11.primary })
6206
- }
6207
- ) : /* @__PURE__ */ jsx17(ProfileAvatar, { name: invite.email || "invite", size: 32 }),
6208
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col min-w-0", children: [
6209
- /* @__PURE__ */ jsx17(
6210
- "span",
6211
- {
6212
- className: "truncate",
6213
- style: {
6214
- fontFamily: T11.font,
6215
- fontSize: T11.fsSm,
6216
- fontWeight: 500,
6217
- lineHeight: T11.lhSm,
6218
- color: T11.primary
6219
- },
6220
- children: isDomain ? `Domain: ${invite.domain}` : toDisplayText2(invite.email, "")
6221
- }
6222
- ),
6223
- /* @__PURE__ */ jsx17(
6224
- "span",
6225
- {
6226
- className: "truncate",
6227
- style: {
6228
- fontFamily: T11.font,
6229
- fontSize: T11.fsXs,
6230
- fontWeight: 400,
6231
- lineHeight: T11.lhXs,
6232
- color: T11.muted
6233
- },
6234
- children: isDomain ? "Auto-join by verified domain" : "Email invite"
6235
- }
6236
- )
6237
- ] })
6238
- ] }),
6239
- /* @__PURE__ */ jsx17(
6240
- RoleLabel,
6084
+ ),
6085
+ /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-end shrink-0", style: { width: 32 }, children: onEdit ? /* @__PURE__ */ jsx17(
6086
+ RowIconButton,
6241
6087
  {
6242
- role: role === "admin" ? "admin" : "member",
6243
- label: orgRoleLabel(role)
6088
+ label: `Manage ${email || "member"}`,
6089
+ onClick: onEdit,
6090
+ visible: active || noHover,
6091
+ children: /* @__PURE__ */ jsx17(SiconSettings, { className: "w-4 h-4", color: T11.primary })
6244
6092
  }
6245
- ),
6246
- /* @__PURE__ */ jsx17(
6247
- "div",
6093
+ ) : email && /* @__PURE__ */ jsx17(
6094
+ RowIconButton,
6248
6095
  {
6249
- className: "truncate shrink-0",
6250
- style: {
6251
- width: "7.5rem",
6252
- fontFamily: T11.font,
6253
- fontSize: T11.fsSm,
6254
- fontWeight: 400,
6255
- lineHeight: T11.lhSm,
6256
- color: T11.primary
6096
+ label: copied ? "Copied" : `Copy ${email}`,
6097
+ onClick: () => {
6098
+ void onCopyEmail().then((ok) => {
6099
+ if (!ok) return;
6100
+ setCopied(true);
6101
+ setTimeout(() => setCopied(false), 2e3);
6102
+ });
6257
6103
  },
6258
- children: invitedByText
6104
+ children: copied ? /* @__PURE__ */ jsx17(SiconCheck, { className: "w-4 h-4", color: T11.primary }) : /* @__PURE__ */ jsx17(SiconCopy, { className: "w-4 h-4", color: T11.primary })
6259
6105
  }
6260
- ),
6261
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center shrink-0", style: { gap: T11.spMd }, children: [
6262
- !isDomain && onResend && /* @__PURE__ */ jsx17(ScButton5, { text: "Resend", variant: "tertiary", size: "sm", onClick: onResend }),
6263
- /* @__PURE__ */ jsx17(
6264
- ScButton5,
6265
- {
6266
- text: isDomain ? "Revoke" : "Cancel",
6267
- variant: "error",
6268
- size: "sm",
6269
- onClick: onCancel
6270
- }
6271
- )
6272
- ] })
6106
+ ) })
6273
6107
  ]
6274
6108
  }
6275
6109
  );
@@ -6376,7 +6210,7 @@ function JoinRequestRow({
6376
6210
  )
6377
6211
  ] })
6378
6212
  ] }),
6379
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center shrink-0", style: { gap: T11.spMd }, children: [
6213
+ onApprove && onReject && /* @__PURE__ */ jsxs14("div", { className: "flex items-center shrink-0", style: { gap: T11.spMd }, children: [
6380
6214
  /* @__PURE__ */ jsx17(ScButton5, { text: "Reject", variant: "error", size: "sm", onClick: onReject }),
6381
6215
  /* @__PURE__ */ jsx17(ScButton5, { text: "Approve", variant: "primary", size: "sm", onClick: onApprove })
6382
6216
  ] })
@@ -6432,42 +6266,29 @@ function Section({
6432
6266
  }
6433
6267
  function OrganizationContent({
6434
6268
  embedded = false,
6435
- view = "people",
6436
- onInviteOpen,
6437
- onInviteOpenChange
6269
+ view = "people"
6438
6270
  } = {}) {
6439
6271
  const { organization, toast } = useSettingsAdapters();
6440
6272
  const current = organization.current;
6441
- const [activeTab, setActiveTab] = useState10("active");
6442
6273
  const [members, setMembers] = useState10([]);
6443
- const [invites, setInvites] = useState10([]);
6444
6274
  const [workspaces, setWorkspaces] = useState10([]);
6445
6275
  const [joinRequests, setJoinRequests] = useState10([]);
6446
6276
  const [highestRole, setHighestRole] = useState10("guest");
6447
- const [emailDomain, setEmailDomain] = useState10(null);
6448
- const [canClaimEmailDomain, setCanClaimEmailDomain] = useState10(true);
6449
6277
  const [searchQuery, setSearchQuery] = useState10("");
6450
6278
  const [loadingData, setLoadingData] = useState10(false);
6451
- const [modal, setModal] = useState10({ open: false, mode: "invite" });
6279
+ const [modal, setModal] = useState10({ open: false });
6452
6280
  const fetchData = useCallback3(async () => {
6281
+ if (!organization.current) return;
6453
6282
  setLoadingData(true);
6454
6283
  try {
6455
- const [membersRes, invitesRes, workspacesRes, joinRequestsRes, highestRoleRes] = await Promise.all([
6284
+ const [membersRes, workspacesRes, joinRequestsRes, highestRoleRes] = await Promise.all([
6456
6285
  organization.fetchMembers().catch(() => null),
6457
- organization.fetchInvites().catch(() => null),
6458
6286
  organization.fetchWorkspaces().catch(() => null),
6459
6287
  organization.fetchJoinRequests().catch(() => null),
6460
6288
  organization.getHighestRole?.().catch(() => null) ?? Promise.resolve(null)
6461
6289
  ]);
6462
6290
  if (highestRoleRes?.role) setHighestRole(highestRoleRes.role);
6463
- if (highestRoleRes?.emailDomain !== void 0) {
6464
- setEmailDomain(highestRoleRes.emailDomain ?? null);
6465
- }
6466
- if (highestRoleRes?.canClaimEmailDomain !== void 0) {
6467
- setCanClaimEmailDomain(highestRoleRes.canClaimEmailDomain);
6468
- }
6469
6291
  if (membersRes) setMembers(membersRes.filter((m) => m?.user));
6470
- if (invitesRes) setInvites(invitesRes);
6471
6292
  if (workspacesRes) setWorkspaces(workspacesRes);
6472
6293
  if (joinRequestsRes) setJoinRequests(joinRequestsRes);
6473
6294
  } catch {
@@ -6478,51 +6299,6 @@ function OrganizationContent({
6478
6299
  useEffect10(() => {
6479
6300
  fetchData();
6480
6301
  }, [fetchData]);
6481
- const [domainMatch, setDomainMatch] = useState10(null);
6482
- const [checkingDomainMatch, setCheckingDomainMatch] = useState10(false);
6483
- const [joiningByDomain, setJoiningByDomain] = useState10(false);
6484
- const [createModalOpen, setCreateModalOpen] = useState10(false);
6485
- useEffect10(() => {
6486
- if (current) return;
6487
- let cancelled = false;
6488
- setCheckingDomainMatch(true);
6489
- organization.checkDomainMatch().then((match) => {
6490
- if (!cancelled) setDomainMatch(match);
6491
- }).catch(() => {
6492
- if (!cancelled) setDomainMatch(null);
6493
- }).finally(() => {
6494
- if (!cancelled) setCheckingDomainMatch(false);
6495
- });
6496
- return () => {
6497
- cancelled = true;
6498
- };
6499
- }, [current, organization]);
6500
- const handleJoinByDomain = async () => {
6501
- if (!domainMatch) return;
6502
- setJoiningByDomain(true);
6503
- try {
6504
- await organization.joinByDomain();
6505
- await organization.switch(domainMatch.organizationId);
6506
- toast.success(`Joined ${domainMatch.organizationName}`);
6507
- } catch (err) {
6508
- toast.error(err instanceof Error ? err.message : "Failed to join organization");
6509
- } finally {
6510
- setJoiningByDomain(false);
6511
- }
6512
- };
6513
- const handleCreateOrganization = async (name, imageFile) => {
6514
- try {
6515
- const result = await organization.create({ name, imageFile });
6516
- if (result && "id" in result && result.id) {
6517
- await organization.switch(result.id);
6518
- }
6519
- toast.success("Organization created");
6520
- return true;
6521
- } catch (err) {
6522
- toast.error(err instanceof Error ? err.message : "Failed to create organization");
6523
- return false;
6524
- }
6525
- };
6526
6302
  const [manageModalOpen, setManageModalOpen] = useState10(false);
6527
6303
  const handleUpdateOrganization = async (name, imageFile) => {
6528
6304
  if (!current) return false;
@@ -6546,45 +6322,9 @@ function OrganizationContent({
6546
6322
  return false;
6547
6323
  }
6548
6324
  };
6549
- const openInviteModal = () => setModal({ open: true, mode: "invite" });
6550
- useEffect10(() => {
6551
- if (onInviteOpen) {
6552
- openInviteModal();
6553
- onInviteOpenChange?.(false);
6554
- }
6555
- }, [onInviteOpen]);
6556
- const openUpdateModal = (member) => setModal({ open: true, mode: "update", target: member });
6557
- const closeModal = () => setModal({ open: false, mode: "invite" });
6558
- const handleInviteEmail = async (input) => {
6559
- if (highestRole !== "admin") {
6560
- toast.error("You do not have permission to invite members");
6561
- closeModal();
6562
- return;
6563
- }
6564
- try {
6565
- await organization.inviteMemberByEmail(input);
6566
- toast.success(`Invitation sent to ${input.email}`);
6567
- await fetchData();
6568
- closeModal();
6569
- } catch (err) {
6570
- toast.error(err instanceof Error ? err.message : "Failed to send invite");
6571
- }
6572
- };
6573
- const handleInviteDomain = async (input) => {
6574
- if (highestRole !== "admin") {
6575
- toast.error("You do not have permission to invite members");
6576
- closeModal();
6577
- return;
6578
- }
6579
- try {
6580
- await organization.inviteDomain(input);
6581
- toast.success(`Domain ${input.domain} added`);
6582
- await fetchData();
6583
- closeModal();
6584
- } catch (err) {
6585
- toast.error(err instanceof Error ? err.message : "Failed to add domain");
6586
- }
6587
- };
6325
+ const openUpdateModal = (member) => setModal({ open: true, target: member });
6326
+ const closeModal = () => setModal({ open: false });
6327
+ const adminCount = members.filter((m) => m.role === "admin").length;
6588
6328
  const handleUpdateMember = async (input) => {
6589
6329
  const target = modal.target;
6590
6330
  if (!target) {
@@ -6596,20 +6336,16 @@ function OrganizationContent({
6596
6336
  closeModal();
6597
6337
  return;
6598
6338
  }
6599
- if (target.role === "admin" && input.role === "member") {
6600
- const adminCount = members.filter((m) => m.role === "admin").length;
6601
- if (adminCount <= 1) {
6602
- toast.error(
6603
- "You're the only admin. Promote another member to admin before changing your role."
6604
- );
6605
- return;
6606
- }
6339
+ if (target.role === "admin" && input.role === "member" && adminCount <= 1) {
6340
+ toast.error(
6341
+ "This is the only org admin. Make someone else an org admin first."
6342
+ );
6343
+ return;
6607
6344
  }
6608
6345
  try {
6609
6346
  await organization.updateMemberRole({
6610
6347
  userId: target.user._id,
6611
- role: input.role,
6612
- inviteAccess: input.inviteAccess
6348
+ role: input.role
6613
6349
  });
6614
6350
  toast.success("Member updated");
6615
6351
  await fetchData();
@@ -6629,8 +6365,14 @@ function OrganizationContent({
6629
6365
  closeModal();
6630
6366
  return;
6631
6367
  }
6368
+ if (target.role === "admin" && adminCount <= 1) {
6369
+ toast.error(
6370
+ "This is the only org admin. Make someone else an org admin first."
6371
+ );
6372
+ return;
6373
+ }
6632
6374
  const confirmed = window.confirm(
6633
- `Remove ${target.user.email} from this organization?`
6375
+ `Remove ${target.user.email} from this organization? They'll also be removed from every workspace in it.`
6634
6376
  );
6635
6377
  if (!confirmed) return;
6636
6378
  try {
@@ -6642,44 +6384,6 @@ function OrganizationContent({
6642
6384
  }
6643
6385
  closeModal();
6644
6386
  };
6645
- const handleCancelInvite = async (invite) => {
6646
- if (highestRole !== "admin") {
6647
- toast.error("You do not have permission to manage invites");
6648
- return;
6649
- }
6650
- const label = invite.kind === "domain" ? invite.domain : invite.email;
6651
- const confirmed = window.confirm(
6652
- invite.kind === "domain" ? `Revoke domain invite for ${label}? Members who already joined will keep their access.` : `Cancel invitation for ${label}?`
6653
- );
6654
- if (!confirmed) return;
6655
- try {
6656
- if (invite.kind === "domain") {
6657
- await organization.revokeDomainInvite(invite._id);
6658
- } else if (invite.token) {
6659
- await organization.cancelInvite(invite.token);
6660
- } else {
6661
- await organization.removeMember({ invitationIds: [invite._id] });
6662
- }
6663
- toast.success(invite.kind === "domain" ? "Domain invite revoked" : "Invitation removed");
6664
- await fetchData();
6665
- } catch (err) {
6666
- toast.error(err instanceof Error ? err.message : "Failed to update invite");
6667
- }
6668
- };
6669
- const handleResendInvite = async (invite) => {
6670
- if (invite.kind !== "email") return;
6671
- if (highestRole !== "admin") {
6672
- toast.error("You do not have permission to invite members");
6673
- return;
6674
- }
6675
- try {
6676
- await organization.resendInvite(invite._id);
6677
- toast.success("Invitation resent");
6678
- await fetchData();
6679
- } catch (err) {
6680
- toast.error(err instanceof Error ? err.message : "Failed to resend invitation");
6681
- }
6682
- };
6683
6387
  const handleApproveJoinRequest = async (request) => {
6684
6388
  try {
6685
6389
  await organization.approveJoinRequest(request._id);
@@ -6701,101 +6405,29 @@ function OrganizationContent({
6701
6405
  }
6702
6406
  };
6703
6407
  if (!current) {
6704
- return /* @__PURE__ */ jsxs14(Fragment9, { children: [
6705
- /* @__PURE__ */ jsxs14(
6706
- "div",
6707
- {
6708
- className: "flex flex-col flex-1 min-w-0 min-h-0 w-full items-center justify-center",
6709
- style: { gap: T11.spXl, padding: T11.sp6xl },
6710
- children: [
6711
- /* @__PURE__ */ jsx17(SiconGlobe2, { className: "w-10 h-10", color: T11.muted }),
6712
- domainMatch ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
6713
- /* @__PURE__ */ jsxs14(
6714
- "p",
6715
- {
6716
- className: "text-center",
6717
- style: { color: T11.primary, fontFamily: T11.font, fontSize: T11.fsMd, fontWeight: 600 },
6718
- children: [
6719
- "An organization already exists for ",
6720
- domainMatch.domain
6721
- ]
6722
- }
6723
- ),
6724
- /* @__PURE__ */ jsxs14(
6725
- "p",
6726
- {
6727
- className: "text-center",
6728
- style: { color: T11.muted, fontFamily: T11.font, fontSize: T11.fsSm },
6729
- children: [
6730
- domainMatch.organizationName,
6731
- " \u2014 join it instead of creating a new one and fragmenting your company across multiple orgs."
6732
- ]
6733
- }
6734
- ),
6735
- /* @__PURE__ */ jsx17(
6736
- ScButton5,
6737
- {
6738
- text: joiningByDomain ? "Joining\u2026" : `Join ${domainMatch.organizationName}`,
6739
- variant: "primary",
6740
- size: "md",
6741
- state: joiningByDomain ? "disabled" : "default",
6742
- onClick: handleJoinByDomain
6743
- }
6744
- )
6745
- ] }) : /* @__PURE__ */ jsxs14(Fragment9, { children: [
6746
- /* @__PURE__ */ jsx17(
6747
- "p",
6748
- {
6749
- className: "text-center",
6750
- style: { color: T11.primary, fontFamily: T11.font, fontSize: T11.fsMd, fontWeight: 600 },
6751
- children: "You're not part of an organization yet"
6752
- }
6753
- ),
6754
- /* @__PURE__ */ jsx17(
6755
- "p",
6756
- {
6757
- className: "text-center",
6758
- style: { color: T11.muted, fontFamily: T11.font, fontSize: T11.fsSm },
6759
- children: "Create one to invite your team and manage workspaces together."
6760
- }
6761
- ),
6762
- /* @__PURE__ */ jsx17(
6763
- ScButton5,
6764
- {
6765
- text: "Create organization",
6766
- variant: "primary",
6767
- size: "md",
6768
- styleVariant: "icon-left",
6769
- icon: /* @__PURE__ */ jsx17(SiconUserAdd2, { className: "w-5 h-5", color: T11.inverse }),
6770
- state: checkingDomainMatch ? "disabled" : "default",
6771
- onClick: () => setCreateModalOpen(true)
6772
- }
6773
- )
6774
- ] })
6775
- ]
6776
- }
6777
- ),
6778
- /* @__PURE__ */ jsx17(
6779
- OrganizationModal,
6780
- {
6781
- open: createModalOpen,
6782
- mode: "create",
6783
- onClose: () => setCreateModalOpen(false),
6784
- onCreate: handleCreateOrganization
6785
- }
6786
- )
6787
- ] });
6408
+ return /* @__PURE__ */ jsxs14(
6409
+ "div",
6410
+ {
6411
+ className: "flex flex-col flex-1 min-w-0 min-h-0 w-full items-center justify-center",
6412
+ style: { gap: T11.spXl, padding: T11.sp6xl },
6413
+ children: [
6414
+ /* @__PURE__ */ jsx17(SiconGlobe2, { className: "w-10 h-10", color: T11.muted }),
6415
+ /* @__PURE__ */ jsx17(
6416
+ "p",
6417
+ {
6418
+ className: "text-center",
6419
+ style: { color: T11.primary, fontFamily: T11.font, fontSize: T11.fsMd, fontWeight: 600 },
6420
+ children: "Your workspace isn't part of an organization"
6421
+ }
6422
+ )
6423
+ ]
6424
+ }
6425
+ );
6788
6426
  }
6789
6427
  const q = searchQuery.toLowerCase();
6790
6428
  const filteredMembers = members.filter(
6791
6429
  (m) => (m.user.email || "").toLowerCase().includes(q) || (m.user.name || "").toLowerCase().includes(q) || m.role.toLowerCase().includes(q)
6792
6430
  );
6793
- const filteredInvites = invites.filter((inv) => {
6794
- const label = inv.kind === "domain" ? inv.domain ?? "" : inv.email ?? "";
6795
- return label.toLowerCase().includes(q);
6796
- });
6797
- const emailInvites = filteredInvites.filter((inv) => inv.kind !== "domain");
6798
- const domainInvites = invites.filter((inv) => inv.kind === "domain");
6799
6431
  const scopeHeader = /* @__PURE__ */ jsx17(
6800
6432
  ScopeHeader,
6801
6433
  {
@@ -6844,15 +6476,26 @@ function OrganizationContent({
6844
6476
  )
6845
6477
  }
6846
6478
  );
6847
- const peopleView = /* @__PURE__ */ jsxs14(Fragment9, { children: [
6479
+ const isOrgAdmin = highestRole === "admin";
6480
+ const copyEmail = async (email) => {
6481
+ try {
6482
+ await navigator.clipboard.writeText(email);
6483
+ toast.success("Email copied");
6484
+ return true;
6485
+ } catch {
6486
+ toast.error("Couldn't copy the email");
6487
+ return false;
6488
+ }
6489
+ };
6490
+ const peopleView = /* @__PURE__ */ jsxs14(Fragment8, { children: [
6848
6491
  /* @__PURE__ */ jsx17(
6849
6492
  MemberListToolbar,
6850
6493
  {
6851
- activeTab,
6852
- onTabChange: setActiveTab,
6494
+ activeTab: "active",
6495
+ onTabChange: () => {
6496
+ },
6853
6497
  activeLabel: "Members",
6854
6498
  activeCount: filteredMembers.length,
6855
- pendingCount: emailInvites.length,
6856
6499
  searchQuery,
6857
6500
  onSearchChange: setSearchQuery
6858
6501
  }
@@ -6860,47 +6503,31 @@ function OrganizationContent({
6860
6503
  /* @__PURE__ */ jsx17(
6861
6504
  MemberListFrame,
6862
6505
  {
6863
- isEmpty: activeTab === "active" ? filteredMembers.length === 0 : emailInvites.length === 0,
6864
- emptyText: activeTab === "active" ? "No members yet" : "No pending invites",
6506
+ isEmpty: filteredMembers.length === 0,
6507
+ emptyText: "No members yet",
6865
6508
  grow: "fill",
6866
- children: activeTab === "active" ? filteredMembers.map((m) => /* @__PURE__ */ jsx17(MemberRow, { member: m, onClick: () => openUpdateModal(m) }, m._id)) : emailInvites.map((inv) => /* @__PURE__ */ jsx17(
6867
- InviteRow,
6509
+ children: filteredMembers.map((m) => /* @__PURE__ */ jsx17(
6510
+ MemberRow,
6868
6511
  {
6869
- invite: inv,
6870
- onCancel: () => void handleCancelInvite(inv),
6871
- onResend: () => void handleResendInvite(inv)
6512
+ member: m,
6513
+ onEdit: isOrgAdmin ? () => openUpdateModal(m) : void 0,
6514
+ onCopyEmail: () => copyEmail(m.user.email)
6872
6515
  },
6873
- inv._id
6516
+ m._id
6874
6517
  ))
6875
6518
  }
6876
6519
  )
6877
6520
  ] });
6878
- const workspacesView = /* @__PURE__ */ jsx17(
6879
- Section,
6880
- {
6881
- title: "Workspaces in this organization",
6882
- empty: workspaces.length === 0,
6883
- children: workspaces.map((ws) => /* @__PURE__ */ jsx17(WorkspaceRow, { workspace: ws }, ws._id))
6884
- }
6885
- );
6886
- const domainsView = /* @__PURE__ */ jsxs14(Fragment9, { children: [
6521
+ const workspacesView = /* @__PURE__ */ jsxs14(Fragment8, { children: [
6887
6522
  /* @__PURE__ */ jsx17(
6888
6523
  Section,
6889
6524
  {
6890
- title: "Auto-join by email domain",
6891
- empty: domainInvites.length === 0,
6892
- emptyText: canClaimEmailDomain ? void 0 : `Auto-join needs a company email domain.${emailDomain ? ` ${emailDomain} is a public email provider, so it` : " A public email provider"} can't be claimed \u2014 invite people by email instead.`,
6893
- children: domainInvites.map((inv) => /* @__PURE__ */ jsx17(
6894
- InviteRow,
6895
- {
6896
- invite: inv,
6897
- onCancel: () => void handleCancelInvite(inv)
6898
- },
6899
- inv._id
6900
- ))
6525
+ title: "Workspaces in this organization",
6526
+ empty: workspaces.length === 0,
6527
+ children: workspaces.map((ws) => /* @__PURE__ */ jsx17(WorkspaceRow, { workspace: ws }, ws._id))
6901
6528
  }
6902
6529
  ),
6903
- /* @__PURE__ */ jsx17(
6530
+ (isOrgAdmin || joinRequests.length > 0) && /* @__PURE__ */ jsx17(
6904
6531
  Section,
6905
6532
  {
6906
6533
  title: "Workspaces asking to join",
@@ -6909,37 +6536,29 @@ function OrganizationContent({
6909
6536
  JoinRequestRow,
6910
6537
  {
6911
6538
  request: req,
6912
- onApprove: () => void handleApproveJoinRequest(req),
6913
- onReject: () => void handleRejectJoinRequest(req)
6539
+ onApprove: isOrgAdmin ? () => void handleApproveJoinRequest(req) : void 0,
6540
+ onReject: isOrgAdmin ? () => void handleRejectJoinRequest(req) : void 0
6914
6541
  },
6915
6542
  req._id
6916
6543
  ))
6917
6544
  }
6918
6545
  )
6919
6546
  ] });
6920
- const innerContent = /* @__PURE__ */ jsxs14(Fragment9, { children: [
6547
+ const innerContent = /* @__PURE__ */ jsxs14(Fragment8, { children: [
6921
6548
  scopeHeader,
6922
6549
  loadingData && loadingBlock,
6923
6550
  !loadingData && view === "people" && peopleView,
6924
- !loadingData && view === "workspaces" && workspacesView,
6925
- !loadingData && view === "domains" && domainsView,
6551
+ !loadingData && view !== "people" && workspacesView,
6926
6552
  /* @__PURE__ */ jsx17(
6927
- OrganizationInviteModal,
6553
+ OrganizationMemberModal,
6928
6554
  {
6929
6555
  open: modal.open,
6930
- mode: modal.mode,
6931
6556
  userEmail: modal.target?.user.email,
6932
6557
  initialRole: modal.target?.role === "admin" || modal.target?.role === "member" ? modal.target.role : void 0,
6933
- initialInviteAccess: modal.target?.inviteAccess,
6934
- allowSubmitWithoutChanges: false,
6935
6558
  lockRole: modal.target?.role === "guest",
6936
6559
  lockedRoleLabel: orgRoleLabel(modal.target?.role),
6937
6560
  canRemove: highestRole === "admin",
6938
- canClaimDomain: canClaimEmailDomain,
6939
- claimableDomain: emailDomain,
6940
6561
  onClose: closeModal,
6941
- onInviteEmail: handleInviteEmail,
6942
- onInviteDomain: handleInviteDomain,
6943
6562
  onUpdate: handleUpdateMember,
6944
6563
  onRemove: handleRemoveMember
6945
6564
  }
@@ -6984,34 +6603,20 @@ function OrganizationContent({
6984
6603
  backgroundSize: "24px 24px"
6985
6604
  },
6986
6605
  children: [
6987
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between shrink-0 w-full", children: [
6988
- /* @__PURE__ */ jsx17(
6989
- "p",
6990
- {
6991
- className: "flex-1 min-w-0 truncate",
6992
- style: {
6993
- color: T11.primary,
6994
- fontFamily: T11.font,
6995
- fontSize: "var(--font-size-font-size-xxl)",
6996
- fontWeight: 600,
6997
- lineHeight: "var(--line-height-line-height-xxl)"
6998
- },
6999
- children: current?.name ? `${current.name} \u2014 Organization` : "Organization"
7000
- }
7001
- ),
7002
- /* @__PURE__ */ jsx17(
7003
- ScButton5,
7004
- {
7005
- text: "Invite",
7006
- variant: "primary",
7007
- size: "md",
7008
- styleVariant: "icon-left",
7009
- state: highestRole !== "admin" ? "disabled" : "default",
7010
- icon: /* @__PURE__ */ jsx17(SiconUserAdd2, { className: "w-5 h-5", color: "var(--alias-text---icons-inverse)" }),
7011
- onClick: openInviteModal
7012
- }
7013
- )
7014
- ] }),
6606
+ /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-between shrink-0 w-full", children: /* @__PURE__ */ jsx17(
6607
+ "p",
6608
+ {
6609
+ className: "flex-1 min-w-0 truncate",
6610
+ style: {
6611
+ color: T11.primary,
6612
+ fontFamily: T11.font,
6613
+ fontSize: "var(--font-size-font-size-xxl)",
6614
+ fontWeight: 600,
6615
+ lineHeight: "var(--line-height-line-height-xxl)"
6616
+ },
6617
+ children: current?.name ? `${current.name} \u2014 Organization` : "Organization"
6618
+ }
6619
+ ) }),
7015
6620
  innerContent
7016
6621
  ]
7017
6622
  }
@@ -7945,7 +7550,7 @@ function BuyCreditsModal({
7945
7550
  }
7946
7551
 
7947
7552
  // src/billing-content.tsx
7948
- import { Fragment as Fragment10, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
7553
+ import { Fragment as Fragment9, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
7949
7554
  var DEFAULT_TOPUP_SERVICE = "catalogix";
7950
7555
  var PRIMARY_COLOR2 = "var(--alias-text---icons-primary)";
7951
7556
  var MUTED_COLOR = "var(--alias-text---icons-muted)";
@@ -9509,7 +9114,7 @@ function BillingContent({
9509
9114
  if (embedded) return plansView;
9510
9115
  return /* @__PURE__ */ jsx20("div", { className: "flex-1 h-full min-h-0 min-w-0 relative", children: plansView });
9511
9116
  }
9512
- const billingInnerContent = /* @__PURE__ */ jsxs17(Fragment10, { children: [
9117
+ const billingInnerContent = /* @__PURE__ */ jsxs17(Fragment9, { children: [
9513
9118
  /* @__PURE__ */ jsxs17(
9514
9119
  "div",
9515
9120
  {
@@ -9708,7 +9313,7 @@ import {
9708
9313
  SiconPlus as SiconPlus2,
9709
9314
  SiconClose as SiconClose7
9710
9315
  } from "@streamoid/icons";
9711
- import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
9316
+ import { Fragment as Fragment10, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
9712
9317
  var EXPIRY_OPTIONS = [
9713
9318
  { label: "30 days", value: "30d" },
9714
9319
  { label: "60 days", value: "60d" },
@@ -10140,7 +9745,7 @@ function TokensContent({
10140
9745
  setCreatedToken(token);
10141
9746
  fetchTokens();
10142
9747
  }
10143
- const tokensInnerContent = /* @__PURE__ */ jsxs18(Fragment11, { children: [
9748
+ const tokensInnerContent = /* @__PURE__ */ jsxs18(Fragment10, { children: [
10144
9749
  !embedded && /* @__PURE__ */ jsxs18(
10145
9750
  "div",
10146
9751
  {
@@ -10492,7 +10097,7 @@ function TokenTable({ tokens, deletingId, onRevoke, onDelete }) {
10492
10097
  }
10493
10098
 
10494
10099
  // src/settings-content.tsx
10495
- import { Fragment as Fragment12, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
10100
+ import { Fragment as Fragment11, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
10496
10101
  function deriveInitials(name) {
10497
10102
  return name.split(/\s+/).slice(0, 2).map((part) => part[0]?.toUpperCase() ?? "").join("") || "WS";
10498
10103
  }
@@ -10598,20 +10203,19 @@ function SettingsNav({
10598
10203
  /* @__PURE__ */ jsx22(ScHDivider, {}),
10599
10204
  /* @__PURE__ */ jsxs19("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: [
10600
10205
  /* @__PURE__ */ jsx22("div", { title: workspaceName ?? void 0, style: { padding: "4px 12px", fontSize: 11, fontWeight: 500, color: MUTED_COLOR2, textTransform: "uppercase", letterSpacing: "0.08em" }, children: "Workspace" }),
10601
- item("workspace", (color) => /* @__PURE__ */ jsx22(SiconSettings, { className: "w-5 h-5", color })),
10206
+ item("workspace", (color) => /* @__PURE__ */ jsx22(SiconSettings2, { className: "w-5 h-5", color })),
10602
10207
  item("workspaceMembers", (color) => /* @__PURE__ */ jsx22(SiconTeam, { className: "w-5 h-5", color })),
10603
- isWorkspaceAdmin && /* @__PURE__ */ jsxs19(Fragment12, { children: [
10208
+ isWorkspaceAdmin && /* @__PURE__ */ jsxs19(Fragment11, { children: [
10604
10209
  item("billing", (color) => /* @__PURE__ */ jsx22(SiconBilling, { className: "w-5 h-5", color })),
10605
10210
  item("apikey", (color) => /* @__PURE__ */ jsx22(SiconKey_default, { className: "w-5 h-5", color }))
10606
10211
  ] }),
10607
10212
  !isWorkspaceAdmin && /* @__PURE__ */ jsx22("p", { style: { margin: "4px 12px", fontSize: 12, lineHeight: "18px", color: MUTED_COLOR2 }, children: "Contact your workspace admin for credit top-ups and billing history." })
10608
10213
  ] }),
10609
10214
  /* @__PURE__ */ jsx22(ScHDivider, {}),
10610
- /* @__PURE__ */ jsx22("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: hasOrganization ? /* @__PURE__ */ jsxs19(Fragment12, { children: [
10215
+ /* @__PURE__ */ jsx22("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: hasOrganization ? /* @__PURE__ */ jsxs19(Fragment11, { children: [
10611
10216
  /* @__PURE__ */ jsx22("div", { style: { padding: "4px 12px", fontSize: 11, fontWeight: 500, color: MUTED_COLOR2, textTransform: "uppercase", letterSpacing: "0.08em" }, children: "Organization" }),
10612
10217
  item("organization", (color) => /* @__PURE__ */ jsx22(SiconTeam, { className: "w-5 h-5", color })),
10613
- item("organizationWorkspaces", (color) => /* @__PURE__ */ jsx22(SiconWorkspace2, { className: "w-5 h-5", color })),
10614
- item("organizationDomains", (color) => /* @__PURE__ */ jsx22(SiconLock, { className: "w-5 h-5", color }))
10218
+ item("organizationWorkspaces", (color) => /* @__PURE__ */ jsx22(SiconWorkspace2, { className: "w-5 h-5", color }))
10615
10219
  ] }) : /* @__PURE__ */ jsx22(
10616
10220
  SettingsNavItem,
10617
10221
  {
@@ -10906,7 +10510,7 @@ function LanguageDropdown({
10906
10510
  ScMenuOptions,
10907
10511
  {
10908
10512
  text: lang.label,
10909
- icon: /* @__PURE__ */ jsx22(Fragment12, {}),
10513
+ icon: /* @__PURE__ */ jsx22(Fragment11, {}),
10910
10514
  hover: isActive ? "true" : "false",
10911
10515
  variant: "default",
10912
10516
  role: "option",
@@ -11583,7 +11187,6 @@ function SettingsContentInner({
11583
11187
  const [creatingWorkspace, setCreatingWorkspace] = useState15(false);
11584
11188
  const [updatingWorkspace, setUpdatingWorkspace] = useState15(false);
11585
11189
  const [teamInviteOpen, setTeamInviteOpen] = useState15(false);
11586
- const [organizationInviteOpen, setOrganizationInviteOpen] = useState15(false);
11587
11190
  const [tokenShowRevoked, setTokenShowRevoked] = useState15(false);
11588
11191
  const [tokenCreateOpen, setTokenCreateOpen] = useState15(false);
11589
11192
  const [billingShowPlans, setBillingShowPlans] = useState15(false);
@@ -11945,7 +11548,7 @@ function SettingsContentInner({
11945
11548
  },
11946
11549
  children: [
11947
11550
  /* @__PURE__ */ jsxs19("div", { className: "flex items-center flex-1 min-w-0", style: { gap: 8, paddingLeft: 20 }, children: [
11948
- /* @__PURE__ */ jsx22(SiconSettings, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11551
+ /* @__PURE__ */ jsx22(SiconSettings2, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11949
11552
  /* @__PURE__ */ jsx22(
11950
11553
  "span",
11951
11554
  {
@@ -11959,7 +11562,7 @@ function SettingsContentInner({
11959
11562
  children: "Settings"
11960
11563
  }
11961
11564
  ),
11962
- scopeCrumb && /* @__PURE__ */ jsxs19(Fragment12, { children: [
11565
+ scopeCrumb && /* @__PURE__ */ jsxs19(Fragment11, { children: [
11963
11566
  /* @__PURE__ */ jsx22(SiconRight2, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11964
11567
  /* @__PURE__ */ jsx22(
11965
11568
  "span",
@@ -11992,7 +11595,7 @@ function SettingsContentInner({
11992
11595
  children: leafLabel
11993
11596
  }
11994
11597
  ),
11995
- isBillingPlans && /* @__PURE__ */ jsxs19(Fragment12, { children: [
11598
+ isBillingPlans && /* @__PURE__ */ jsxs19(Fragment11, { children: [
11996
11599
  /* @__PURE__ */ jsx22(SiconRight2, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11997
11600
  /* @__PURE__ */ jsx22(
11998
11601
  "span",
@@ -12079,7 +11682,7 @@ function SettingsContentInner({
12079
11682
  size: "md",
12080
11683
  styleVariant: "icon-left",
12081
11684
  icon: /* @__PURE__ */ jsx22(
12082
- SiconUserAdd3,
11685
+ SiconUserAdd2,
12083
11686
  {
12084
11687
  className: "w-5 h-5",
12085
11688
  color: "var(--alias-text---icons-inverse)"
@@ -12090,31 +11693,6 @@ function SettingsContentInner({
12090
11693
  )
12091
11694
  }
12092
11695
  ),
12093
- activeTab === "organization" && hasOrganization && /* @__PURE__ */ jsx22(
12094
- SettingsTooltip,
12095
- {
12096
- content: "Invite someone into your organization",
12097
- placement: "bottom",
12098
- inline: true,
12099
- children: /* @__PURE__ */ jsx22(
12100
- ScButton7,
12101
- {
12102
- text: "Invite",
12103
- variant: "secondary",
12104
- size: "md",
12105
- styleVariant: "icon-left",
12106
- icon: /* @__PURE__ */ jsx22(
12107
- SiconUserAdd3,
12108
- {
12109
- className: "w-5 h-5",
12110
- color: "var(--alias-text---icons-inverse)"
12111
- }
12112
- ),
12113
- onClick: () => setOrganizationInviteOpen(true)
12114
- }
12115
- )
12116
- }
12117
- ),
12118
11696
  activeTab === "apikey" && isWorkspaceAdmin && /* @__PURE__ */ jsxs19("div", { className: "flex items-center shrink-0", style: { gap: "var(--spacing-md)" }, children: [
12119
11697
  /* @__PURE__ */ jsx22(
12120
11698
  SettingsTooltip,
@@ -12273,9 +11851,7 @@ function SettingsContentInner({
12273
11851
  OrganizationContent,
12274
11852
  {
12275
11853
  embedded: true,
12276
- view: activeTab === "organizationWorkspaces" ? "workspaces" : activeTab === "organizationDomains" ? "domains" : "people",
12277
- onInviteOpen: organizationInviteOpen,
12278
- onInviteOpenChange: setOrganizationInviteOpen
11854
+ view: activeTab === "organizationWorkspaces" || activeTab === "organizationDomains" ? "workspaces" : "people"
12279
11855
  }
12280
11856
  ) }),
12281
11857
  activeTab === "billing" && isWorkspaceAdmin && /* @__PURE__ */ jsx22("div", { className: "flex flex-col flex-1 min-w-0 min-h-0 h-full", children: /* @__PURE__ */ jsx22(
@@ -12413,6 +11989,249 @@ function SettingsContentInner({
12413
11989
  }
12414
11990
  );
12415
11991
  }
11992
+
11993
+ // src/workspace-picker.tsx
11994
+ import { useState as useState16 } from "react";
11995
+ import { ScButton as ScButton8, ScCheckbox } from "@streamoid/ui";
11996
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
11997
+ var T13 = {
11998
+ primary: "var(--alias-text---icons-primary)",
11999
+ muted: "var(--alias-text---icons-muted)",
12000
+ tertiary: "var(--alias-text---icons-tertiary)",
12001
+ surface: "var(--alias-surface-base)",
12002
+ fillPlus: "var(--alias-fill-neutral-neutralplus)",
12003
+ borderSubtle: "var(--alias-border-subtle)",
12004
+ font: "var(--font-family-font-family-body)",
12005
+ fsXs: "var(--font-size-font-size-xs)",
12006
+ fsSm: "var(--font-size-font-size-sm)",
12007
+ fsXl: "var(--font-size-font-size-xl)",
12008
+ lhXs: "var(--line-height-line-height-xs)",
12009
+ lhSm: "var(--line-height-line-height-sm)",
12010
+ lhXl: "var(--line-height-line-height-xl)",
12011
+ spXs: "var(--spacing-xs)",
12012
+ spMd: "var(--spacing-md)",
12013
+ spXl: "var(--spacing-xl)",
12014
+ sp3xl: "var(--spacing-3xl)",
12015
+ sp5xl: "var(--spacing-5xl)",
12016
+ sp6xl: "var(--spacing-6xl)",
12017
+ rLg: "var(--radius-lg)",
12018
+ r3xl: "var(--radius-3xl)"
12019
+ };
12020
+ function WorkspacePicker({
12021
+ organizationName,
12022
+ workspaces,
12023
+ loading = false,
12024
+ onJoin,
12025
+ onCreate
12026
+ }) {
12027
+ const [selected, setSelected] = useState16(/* @__PURE__ */ new Set());
12028
+ const [creating, setCreating] = useState16(false);
12029
+ const [name, setName] = useState16("");
12030
+ const [busy, setBusy] = useState16(false);
12031
+ const hasWorkspaces = workspaces.length > 0;
12032
+ const showCreate = creating || !loading && !hasWorkspaces;
12033
+ const orgLabel = organizationName || "your organization";
12034
+ const toggle = (id) => setSelected((prev) => {
12035
+ const next = new Set(prev);
12036
+ if (next.has(id)) next.delete(id);
12037
+ else next.add(id);
12038
+ return next;
12039
+ });
12040
+ const run = async (action) => {
12041
+ setBusy(true);
12042
+ try {
12043
+ await action();
12044
+ } catch {
12045
+ } finally {
12046
+ setBusy(false);
12047
+ }
12048
+ };
12049
+ return /* @__PURE__ */ jsxs20(
12050
+ "div",
12051
+ {
12052
+ className: "flex flex-col w-full",
12053
+ style: { maxWidth: 520, gap: T13.sp5xl, fontFamily: T13.font },
12054
+ children: [
12055
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-col", style: { gap: T13.spMd }, children: [
12056
+ /* @__PURE__ */ jsx23(
12057
+ "p",
12058
+ {
12059
+ style: {
12060
+ color: T13.primary,
12061
+ fontSize: T13.fsXl,
12062
+ fontWeight: 600,
12063
+ lineHeight: T13.lhXl,
12064
+ margin: 0
12065
+ },
12066
+ children: "Choose your workspaces"
12067
+ }
12068
+ ),
12069
+ /* @__PURE__ */ jsx23("p", { style: { color: T13.muted, fontSize: T13.fsSm, lineHeight: T13.lhSm, margin: 0 }, children: hasWorkspaces || loading ? `Join one or more workspaces in ${orgLabel} as a member, or create your own.` : `There are no workspaces to join in ${orgLabel} yet. Create one to get started.` })
12070
+ ] }),
12071
+ (loading || hasWorkspaces) && /* @__PURE__ */ jsx23(
12072
+ "div",
12073
+ {
12074
+ className: "flex flex-col w-full overflow-y-auto",
12075
+ style: {
12076
+ maxHeight: 360,
12077
+ background: T13.surface,
12078
+ border: `1px solid ${T13.borderSubtle}`,
12079
+ borderRadius: T13.r3xl
12080
+ },
12081
+ children: loading ? /* @__PURE__ */ jsx23(
12082
+ "div",
12083
+ {
12084
+ className: "flex items-center justify-center",
12085
+ style: { padding: T13.sp6xl, color: T13.muted, fontSize: T13.fsSm },
12086
+ children: "Loading workspaces\u2026"
12087
+ }
12088
+ ) : workspaces.map((workspace, index) => {
12089
+ const checked = selected.has(workspace._id);
12090
+ return /* @__PURE__ */ jsxs20(
12091
+ "div",
12092
+ {
12093
+ role: "checkbox",
12094
+ "aria-checked": checked,
12095
+ tabIndex: 0,
12096
+ className: "flex items-center cursor-pointer",
12097
+ style: {
12098
+ gap: T13.spXl,
12099
+ padding: `${T13.spXl} ${T13.sp3xl}`,
12100
+ borderTop: index ? `1px solid ${T13.borderSubtle}` : "none"
12101
+ },
12102
+ onClick: () => toggle(workspace._id),
12103
+ onKeyDown: (e) => {
12104
+ if (e.key === " " || e.key === "Enter") {
12105
+ e.preventDefault();
12106
+ toggle(workspace._id);
12107
+ }
12108
+ },
12109
+ children: [
12110
+ /* @__PURE__ */ jsx23(ScCheckbox, { checked }),
12111
+ /* @__PURE__ */ jsx23(
12112
+ ProfileAvatar,
12113
+ {
12114
+ name: workspace.name,
12115
+ profileImage: workspace.imageUrl,
12116
+ size: 32,
12117
+ borderRadius: T13.rLg
12118
+ }
12119
+ ),
12120
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-col min-w-0", children: [
12121
+ /* @__PURE__ */ jsx23(
12122
+ "span",
12123
+ {
12124
+ className: "truncate",
12125
+ style: {
12126
+ color: T13.primary,
12127
+ fontSize: T13.fsSm,
12128
+ fontWeight: 500,
12129
+ lineHeight: T13.lhSm
12130
+ },
12131
+ children: workspace.name
12132
+ }
12133
+ ),
12134
+ workspace.ownerName && /* @__PURE__ */ jsxs20(
12135
+ "span",
12136
+ {
12137
+ className: "truncate",
12138
+ style: { color: T13.muted, fontSize: T13.fsXs, lineHeight: T13.lhXs },
12139
+ children: [
12140
+ "Created by ",
12141
+ workspace.ownerName
12142
+ ]
12143
+ }
12144
+ )
12145
+ ] })
12146
+ ]
12147
+ },
12148
+ workspace._id
12149
+ );
12150
+ })
12151
+ }
12152
+ ),
12153
+ showCreate ? /* @__PURE__ */ jsxs20("div", { className: "flex flex-col w-full", style: { gap: T13.spMd }, children: [
12154
+ /* @__PURE__ */ jsx23(
12155
+ "label",
12156
+ {
12157
+ htmlFor: "workspace-picker-name",
12158
+ style: { color: T13.tertiary, fontSize: T13.fsSm, lineHeight: T13.lhSm },
12159
+ children: "New workspace name"
12160
+ }
12161
+ ),
12162
+ /* @__PURE__ */ jsx23(
12163
+ "input",
12164
+ {
12165
+ id: "workspace-picker-name",
12166
+ autoFocus: true,
12167
+ value: name,
12168
+ onChange: (e) => setName(e.target.value),
12169
+ onKeyDown: (e) => {
12170
+ if (e.key === "Enter" && name.trim() && !busy) {
12171
+ void run(() => onCreate(name.trim()));
12172
+ }
12173
+ },
12174
+ placeholder: "e.g. Marketing",
12175
+ style: {
12176
+ height: 48,
12177
+ padding: `0 ${T13.sp3xl}`,
12178
+ background: T13.fillPlus,
12179
+ border: "none",
12180
+ outline: "none",
12181
+ borderRadius: T13.r3xl,
12182
+ color: T13.primary,
12183
+ fontFamily: T13.font,
12184
+ fontSize: T13.fsSm
12185
+ }
12186
+ }
12187
+ ),
12188
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-end w-full", style: { gap: T13.spMd }, children: [
12189
+ hasWorkspaces && /* @__PURE__ */ jsx23(
12190
+ ScButton8,
12191
+ {
12192
+ text: "Back",
12193
+ variant: "tertiary",
12194
+ size: "md",
12195
+ onClick: () => setCreating(false)
12196
+ }
12197
+ ),
12198
+ /* @__PURE__ */ jsx23(
12199
+ ScButton8,
12200
+ {
12201
+ text: busy ? "Creating\u2026" : "Create workspace",
12202
+ variant: "primary",
12203
+ size: "md",
12204
+ state: !name.trim() || busy ? "disabled" : "default",
12205
+ onClick: name.trim() && !busy ? () => void run(() => onCreate(name.trim())) : void 0
12206
+ }
12207
+ )
12208
+ ] })
12209
+ ] }) : /* @__PURE__ */ jsxs20("div", { className: "flex flex-wrap items-center justify-between w-full", style: { gap: T13.spMd }, children: [
12210
+ /* @__PURE__ */ jsx23(
12211
+ ScButton8,
12212
+ {
12213
+ text: "Create a workspace",
12214
+ variant: "tertiary",
12215
+ size: "md",
12216
+ state: loading || busy ? "disabled" : "default",
12217
+ onClick: loading || busy ? void 0 : () => setCreating(true)
12218
+ }
12219
+ ),
12220
+ /* @__PURE__ */ jsx23(
12221
+ ScButton8,
12222
+ {
12223
+ text: busy ? "Joining\u2026" : selected.size > 1 ? `Join ${selected.size} workspaces` : "Join workspace",
12224
+ variant: "primary",
12225
+ size: "md",
12226
+ state: !selected.size || busy ? "disabled" : "default",
12227
+ onClick: selected.size && !busy ? () => void run(() => onJoin([...selected])) : void 0
12228
+ }
12229
+ )
12230
+ ] })
12231
+ ]
12232
+ }
12233
+ );
12234
+ }
12416
12235
  export {
12417
12236
  APP_KEYS,
12418
12237
  BillingContent,
@@ -12426,7 +12245,7 @@ export {
12426
12245
  MemberListFrame,
12427
12246
  MemberListToolbar,
12428
12247
  OrganizationContent,
12429
- OrganizationInviteModal,
12248
+ OrganizationMemberModal,
12430
12249
  OrganizationModal,
12431
12250
  ProfileAvatar,
12432
12251
  ProfileTab,
@@ -12448,6 +12267,7 @@ export {
12448
12267
  WorkspaceGeneralTab,
12449
12268
  WorkspaceListTab,
12450
12269
  WorkspaceModal,
12270
+ WorkspacePicker,
12451
12271
  WorkspaceTab,
12452
12272
  countLabel,
12453
12273
  loadWorkspaceOrganization,