@streamoid/settings 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -179,6 +179,9 @@ interface SettingsWorkspaceListItem {
179
179
  plan?: string;
180
180
  /** Optional owner email shown in the workspace list. */
181
181
  ownerEmail?: string;
182
+ /** The organization this workspace belongs to, if any. My workspaces groups
183
+ * the list under each organization (named from `organization.list()`). */
184
+ organizationId?: string;
182
185
  }
183
186
  interface SettingsWorkspaceAdapter {
184
187
  /** Same authenticated transport used by the sidebar owner lookup. */
@@ -940,7 +943,25 @@ declare function ProfileTab(): react.JSX.Element;
940
943
  */
941
944
  /** Workspaces shown per page in My workspaces. */
942
945
  declare const WORKSPACE_LIST_PAGE_SIZE = 10;
943
- declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreateClick, onEditClick, onSwitchClick, onLeaveClick, fetchPlans, pageSize, }: {
946
+ /** An organization as My workspaces needs it to group the list. */
947
+ interface WorkspaceListOrganization {
948
+ _id: string;
949
+ name: string;
950
+ role?: string;
951
+ }
952
+ interface WorkspaceListGroup {
953
+ key: string;
954
+ label: string;
955
+ workspaces: WorkspaceInfo[];
956
+ }
957
+ /**
958
+ * The same grouping as CXO's workspace switcher: the viewer's own
959
+ * organizations first, then those they are only a guest of (labelled so), and
960
+ * workspaces in no organization — or in one the viewer isn't a member of —
961
+ * last. Groups keep the order the organizations came in.
962
+ */
963
+ declare function groupWorkspaceList(workspaces: WorkspaceInfo[], organizations?: WorkspaceListOrganization[]): WorkspaceListGroup[];
964
+ declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreateClick, onEditClick, onSwitchClick, onLeaveClick, fetchPlans, organizations, pageSize, }: {
944
965
  workspaces: WorkspaceInfo[];
945
966
  loading: boolean;
946
967
  onCreateClick: () => void;
@@ -949,6 +970,8 @@ declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreat
949
970
  onLeaveClick: (ws: WorkspaceInfo) => void;
950
971
  /** See SettingsWorkspaceAdapter.fetchPlans. */
951
972
  fetchPlans?: (workspaceIds: string[]) => Promise<Record<string, string>>;
973
+ /** The viewer's organizations, to group the list under. */
974
+ organizations?: WorkspaceListOrganization[];
952
975
  pageSize?: number;
953
976
  }): react.JSX.Element;
954
977
  /**
@@ -1414,4 +1437,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1414
1437
  */
1415
1438
  declare function useSettingsAdapters(): SettingsAdapters;
1416
1439
 
1417
- export { APP_KEYS, type ApiToken, type AppKey, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, DEFAULT_USER_LANGUAGE, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrganizationContent, type OrganizationData, type OrganizationInvite, type OrganizationJoinRequest, type OrganizationMember, OrganizationMemberModal, type OrganizationMemberModalProps, OrganizationModal, type OrganizationView, type OrganizationWorkspaceItem, type Price, type PriceMetadata, type ProductsResponse, ProfileAvatar, ProfileTab, ReferralTab, SCOPE_LABELS, ScopeHeader, type ScopeHeaderProps, type ServiceItem, type SettingsAdapters, SettingsAdaptersProvider, type SettingsApiAdapter, type SettingsAuthAdapter, type SettingsAuthUser, SettingsContent, type SettingsContentProps, type SettingsImageUploadAdapter, type SettingsNavigationAdapter, type SettingsOrganizationAdapter, type SettingsOrganizationCurrent, type SettingsOrganizationListItem, type SettingsScope, type SettingsTab, type SettingsToastAdapter, SettingsTooltip, type SettingsTooltipPlacement, type SettingsTooltipProps, type SettingsWorkspaceAdapter, type SettingsWorkspaceCurrent, type SettingsWorkspaceListItem, SiconKey, type StoreItem, type SubscriptionPlan, type SubscriptionResponse, TAB_DESCRIPTIONS, TAB_LABELS, TAB_SCOPE, TAB_TO_URL, type TeamMember, TeamsContent, type TokenExpiry, TokensContent, URL_TO_TAB, USER_LANGUAGES, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserLanguage, type UserPermissions, WORKSPACE_LIST_PAGE_SIZE, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspacePicker, type WorkspacePickerItem, type WorkspacePickerProps, WorkspaceTab, type WorkspaceUsageResponse, countLabel, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };
1440
+ export { APP_KEYS, type ApiToken, type AppKey, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, DEFAULT_USER_LANGUAGE, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrganizationContent, type OrganizationData, type OrganizationInvite, type OrganizationJoinRequest, type OrganizationMember, OrganizationMemberModal, type OrganizationMemberModalProps, OrganizationModal, type OrganizationView, type OrganizationWorkspaceItem, type Price, type PriceMetadata, type ProductsResponse, ProfileAvatar, ProfileTab, ReferralTab, SCOPE_LABELS, ScopeHeader, type ScopeHeaderProps, type ServiceItem, type SettingsAdapters, SettingsAdaptersProvider, type SettingsApiAdapter, type SettingsAuthAdapter, type SettingsAuthUser, SettingsContent, type SettingsContentProps, type SettingsImageUploadAdapter, type SettingsNavigationAdapter, type SettingsOrganizationAdapter, type SettingsOrganizationCurrent, type SettingsOrganizationListItem, type SettingsScope, type SettingsTab, type SettingsToastAdapter, SettingsTooltip, type SettingsTooltipPlacement, type SettingsTooltipProps, type SettingsWorkspaceAdapter, type SettingsWorkspaceCurrent, type SettingsWorkspaceListItem, SiconKey, type StoreItem, type SubscriptionPlan, type SubscriptionResponse, TAB_DESCRIPTIONS, TAB_LABELS, TAB_SCOPE, TAB_TO_URL, type TeamMember, TeamsContent, type TokenExpiry, TokensContent, URL_TO_TAB, USER_LANGUAGES, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserLanguage, type UserPermissions, WORKSPACE_LIST_PAGE_SIZE, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, type WorkspaceListOrganization, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspacePicker, type WorkspacePickerItem, type WorkspacePickerProps, WorkspaceTab, type WorkspaceUsageResponse, countLabel, groupWorkspaceList, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };
package/dist/index.d.ts CHANGED
@@ -179,6 +179,9 @@ interface SettingsWorkspaceListItem {
179
179
  plan?: string;
180
180
  /** Optional owner email shown in the workspace list. */
181
181
  ownerEmail?: string;
182
+ /** The organization this workspace belongs to, if any. My workspaces groups
183
+ * the list under each organization (named from `organization.list()`). */
184
+ organizationId?: string;
182
185
  }
183
186
  interface SettingsWorkspaceAdapter {
184
187
  /** Same authenticated transport used by the sidebar owner lookup. */
@@ -940,7 +943,25 @@ declare function ProfileTab(): react.JSX.Element;
940
943
  */
941
944
  /** Workspaces shown per page in My workspaces. */
942
945
  declare const WORKSPACE_LIST_PAGE_SIZE = 10;
943
- declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreateClick, onEditClick, onSwitchClick, onLeaveClick, fetchPlans, pageSize, }: {
946
+ /** An organization as My workspaces needs it to group the list. */
947
+ interface WorkspaceListOrganization {
948
+ _id: string;
949
+ name: string;
950
+ role?: string;
951
+ }
952
+ interface WorkspaceListGroup {
953
+ key: string;
954
+ label: string;
955
+ workspaces: WorkspaceInfo[];
956
+ }
957
+ /**
958
+ * The same grouping as CXO's workspace switcher: the viewer's own
959
+ * organizations first, then those they are only a guest of (labelled so), and
960
+ * workspaces in no organization — or in one the viewer isn't a member of —
961
+ * last. Groups keep the order the organizations came in.
962
+ */
963
+ declare function groupWorkspaceList(workspaces: WorkspaceInfo[], organizations?: WorkspaceListOrganization[]): WorkspaceListGroup[];
964
+ declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreateClick, onEditClick, onSwitchClick, onLeaveClick, fetchPlans, organizations, pageSize, }: {
944
965
  workspaces: WorkspaceInfo[];
945
966
  loading: boolean;
946
967
  onCreateClick: () => void;
@@ -949,6 +970,8 @@ declare function WorkspaceListTab({ workspaces, loading, onCreateClick: _onCreat
949
970
  onLeaveClick: (ws: WorkspaceInfo) => void;
950
971
  /** See SettingsWorkspaceAdapter.fetchPlans. */
951
972
  fetchPlans?: (workspaceIds: string[]) => Promise<Record<string, string>>;
973
+ /** The viewer's organizations, to group the list under. */
974
+ organizations?: WorkspaceListOrganization[];
952
975
  pageSize?: number;
953
976
  }): react.JSX.Element;
954
977
  /**
@@ -1414,4 +1437,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1414
1437
  */
1415
1438
  declare function useSettingsAdapters(): SettingsAdapters;
1416
1439
 
1417
- export { APP_KEYS, type ApiToken, type AppKey, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, DEFAULT_USER_LANGUAGE, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrganizationContent, type OrganizationData, type OrganizationInvite, type OrganizationJoinRequest, type OrganizationMember, OrganizationMemberModal, type OrganizationMemberModalProps, OrganizationModal, type OrganizationView, type OrganizationWorkspaceItem, type Price, type PriceMetadata, type ProductsResponse, ProfileAvatar, ProfileTab, ReferralTab, SCOPE_LABELS, ScopeHeader, type ScopeHeaderProps, type ServiceItem, type SettingsAdapters, SettingsAdaptersProvider, type SettingsApiAdapter, type SettingsAuthAdapter, type SettingsAuthUser, SettingsContent, type SettingsContentProps, type SettingsImageUploadAdapter, type SettingsNavigationAdapter, type SettingsOrganizationAdapter, type SettingsOrganizationCurrent, type SettingsOrganizationListItem, type SettingsScope, type SettingsTab, type SettingsToastAdapter, SettingsTooltip, type SettingsTooltipPlacement, type SettingsTooltipProps, type SettingsWorkspaceAdapter, type SettingsWorkspaceCurrent, type SettingsWorkspaceListItem, SiconKey, type StoreItem, type SubscriptionPlan, type SubscriptionResponse, TAB_DESCRIPTIONS, TAB_LABELS, TAB_SCOPE, TAB_TO_URL, type TeamMember, TeamsContent, type TokenExpiry, TokensContent, URL_TO_TAB, USER_LANGUAGES, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserLanguage, type UserPermissions, WORKSPACE_LIST_PAGE_SIZE, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspacePicker, type WorkspacePickerItem, type WorkspacePickerProps, WorkspaceTab, type WorkspaceUsageResponse, countLabel, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };
1440
+ export { APP_KEYS, type ApiToken, type AppKey, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, DEFAULT_USER_LANGUAGE, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrganizationContent, type OrganizationData, type OrganizationInvite, type OrganizationJoinRequest, type OrganizationMember, OrganizationMemberModal, type OrganizationMemberModalProps, OrganizationModal, type OrganizationView, type OrganizationWorkspaceItem, type Price, type PriceMetadata, type ProductsResponse, ProfileAvatar, ProfileTab, ReferralTab, SCOPE_LABELS, ScopeHeader, type ScopeHeaderProps, type ServiceItem, type SettingsAdapters, SettingsAdaptersProvider, type SettingsApiAdapter, type SettingsAuthAdapter, type SettingsAuthUser, SettingsContent, type SettingsContentProps, type SettingsImageUploadAdapter, type SettingsNavigationAdapter, type SettingsOrganizationAdapter, type SettingsOrganizationCurrent, type SettingsOrganizationListItem, type SettingsScope, type SettingsTab, type SettingsToastAdapter, SettingsTooltip, type SettingsTooltipPlacement, type SettingsTooltipProps, type SettingsWorkspaceAdapter, type SettingsWorkspaceCurrent, type SettingsWorkspaceListItem, SiconKey, type StoreItem, type SubscriptionPlan, type SubscriptionResponse, TAB_DESCRIPTIONS, TAB_LABELS, TAB_SCOPE, TAB_TO_URL, type TeamMember, TeamsContent, type TokenExpiry, TokensContent, URL_TO_TAB, USER_LANGUAGES, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserLanguage, type UserPermissions, WORKSPACE_LIST_PAGE_SIZE, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, type WorkspaceListOrganization, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspacePicker, type WorkspacePickerItem, type WorkspacePickerProps, WorkspaceTab, type WorkspaceUsageResponse, countLabel, groupWorkspaceList, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };
package/dist/index.js CHANGED
@@ -58,6 +58,7 @@ __export(index_exports, {
58
58
  WorkspacePicker: () => WorkspacePicker,
59
59
  WorkspaceTab: () => WorkspaceTab,
60
60
  countLabel: () => countLabel,
61
+ groupWorkspaceList: () => groupWorkspaceList,
61
62
  loadWorkspaceOrganization: () => loadWorkspaceOrganization,
62
63
  resolveSettingsTabFromPath: () => resolveSettingsTabFromPath,
63
64
  useSettingsAdapters: () => useSettingsAdapters,
@@ -10898,6 +10899,36 @@ function ProfileTab() {
10898
10899
  );
10899
10900
  }
10900
10901
  var WORKSPACE_LIST_PAGE_SIZE = 10;
10902
+ function groupWorkspaceList(workspaces, organizations = []) {
10903
+ const ordered = [
10904
+ ...organizations.filter((org) => org.role !== "guest"),
10905
+ ...organizations.filter((org) => org.role === "guest")
10906
+ ];
10907
+ const groups = [];
10908
+ for (const org of ordered) {
10909
+ const inOrg = workspaces.filter((ws) => ws.organizationId === org._id);
10910
+ if (inOrg.length) {
10911
+ groups.push({
10912
+ key: org._id,
10913
+ label: org.role === "guest" ? `${org.name} \xB7 Guest` : org.name,
10914
+ workspaces: inOrg
10915
+ });
10916
+ }
10917
+ }
10918
+ const known = new Set(organizations.map((org) => org._id));
10919
+ const ungrouped = workspaces.filter(
10920
+ (ws) => !ws.organizationId || !known.has(ws.organizationId)
10921
+ );
10922
+ if (ungrouped.length) {
10923
+ groups.push({
10924
+ key: "__no_org__",
10925
+ // "No organization" only means something next to named groups.
10926
+ label: groups.length ? "No organization" : "Other Workspaces",
10927
+ workspaces: ungrouped
10928
+ });
10929
+ }
10930
+ return groups;
10931
+ }
10901
10932
  function WorkspaceListTab({
10902
10933
  workspaces,
10903
10934
  loading,
@@ -10906,15 +10937,27 @@ function WorkspaceListTab({
10906
10937
  onSwitchClick,
10907
10938
  onLeaveClick,
10908
10939
  fetchPlans,
10940
+ organizations = [],
10909
10941
  pageSize = WORKSPACE_LIST_PAGE_SIZE
10910
10942
  }) {
10911
10943
  const currentWorkspace = workspaces.find((ws) => ws.isCurrent);
10912
- const otherWorkspaces = workspaces.filter((ws) => !ws.isCurrent);
10944
+ const groups = groupWorkspaceList(
10945
+ workspaces.filter((ws) => !ws.isCurrent),
10946
+ organizations
10947
+ );
10948
+ const rows = groups.flatMap(
10949
+ (group) => group.workspaces.map((ws) => ({ ws, group }))
10950
+ );
10951
+ const otherWorkspaces = rows.map((row) => row.ws);
10952
+ const currentOrganization = organizations.find(
10953
+ (org) => org._id && org._id === currentWorkspace?.organizationId
10954
+ );
10913
10955
  const pageCount = Math.max(1, Math.ceil(otherWorkspaces.length / pageSize));
10914
10956
  const [page, setPage] = (0, import_react17.useState)(0);
10915
10957
  const safePage = Math.min(page, pageCount - 1);
10916
10958
  const pageStart = safePage * pageSize;
10917
- const pageWorkspaces = otherWorkspaces.slice(pageStart, pageStart + pageSize);
10959
+ const pageRows = rows.slice(pageStart, pageStart + pageSize);
10960
+ const pageWorkspaces = pageRows.map((row) => row.ws);
10918
10961
  const [plans, setPlans] = (0, import_react17.useState)({});
10919
10962
  const requestedPlans = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
10920
10963
  const visibleIds = [
@@ -10976,7 +11019,7 @@ function WorkspaceListTab({
10976
11019
  className: "flex flex-col items-start shrink-0 w-full",
10977
11020
  style: { gap: 16, padding: "var(--spacing-md) 0" },
10978
11021
  children: [
10979
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11022
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
10980
11023
  "p",
10981
11024
  {
10982
11025
  className: "w-full overflow-hidden text-ellipsis whitespace-nowrap",
@@ -10987,7 +11030,10 @@ function WorkspaceListTab({
10987
11030
  fontWeight: 400,
10988
11031
  lineHeight: "var(--line-height-line-height-md)"
10989
11032
  },
10990
- children: "Current Workspace"
11033
+ children: [
11034
+ "Current Workspace",
11035
+ currentOrganization ? ` \xB7 ${currentOrganization.name}${currentOrganization.role === "guest" ? " (guest)" : ""}` : ""
11036
+ ]
10991
11037
  }
10992
11038
  ),
10993
11039
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
@@ -11023,41 +11069,43 @@ function WorkspaceListTab({
11023
11069
  className: "flex flex-col items-start flex-1 min-h-0 w-full",
11024
11070
  style: { gap: 16, overflowY: "auto" },
11025
11071
  children: [
11026
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11027
- "p",
11028
- {
11029
- className: "w-full overflow-hidden text-ellipsis whitespace-nowrap shrink-0",
11030
- style: {
11031
- color: "var(--alias-text---icons-muted)",
11032
- fontFamily: "var(--font-family-font-family-body)",
11033
- fontSize: "var(--font-size-font-size-md)",
11034
- fontWeight: 400,
11035
- lineHeight: "var(--line-height-line-height-md)"
11036
- },
11037
- children: "Other Workspaces"
11038
- }
11039
- ),
11040
11072
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11041
11073
  "div",
11042
11074
  {
11043
11075
  className: "flex flex-col items-start w-full",
11044
11076
  style: { gap: 16 },
11045
- children: pageWorkspaces.map((ws) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11046
- import_ui14.ScWorkspaceSwitchCard,
11047
- {
11048
- wsName: ws.name,
11049
- initials: ws.initials,
11050
- imageUrl: ws.imageUrl,
11051
- role: ws.role,
11052
- plan: planOf(ws),
11053
- ownerId: ws.ownerEmail,
11054
- type: "otherWS",
11055
- onSwitch: () => onSwitchClick(ws),
11056
- onSettings: () => onEditClick(ws),
11057
- onLeave: () => onLeaveClick(ws)
11058
- },
11059
- ws._id
11060
- ))
11077
+ children: pageRows.map(({ ws, group }, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react17.Fragment, { children: [
11078
+ (index === 0 || pageRows[index - 1].group.key !== group.key) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11079
+ "p",
11080
+ {
11081
+ className: "w-full overflow-hidden text-ellipsis whitespace-nowrap shrink-0",
11082
+ style: {
11083
+ color: "var(--alias-text---icons-muted)",
11084
+ fontFamily: "var(--font-family-font-family-body)",
11085
+ fontSize: "var(--font-size-font-size-md)",
11086
+ fontWeight: 400,
11087
+ lineHeight: "var(--line-height-line-height-md)",
11088
+ marginTop: index === 0 ? 0 : 8
11089
+ },
11090
+ children: group.label
11091
+ }
11092
+ ),
11093
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11094
+ import_ui14.ScWorkspaceSwitchCard,
11095
+ {
11096
+ wsName: ws.name,
11097
+ initials: ws.initials,
11098
+ imageUrl: ws.imageUrl,
11099
+ role: ws.role,
11100
+ plan: planOf(ws),
11101
+ ownerId: ws.ownerEmail,
11102
+ type: "otherWS",
11103
+ onSwitch: () => onSwitchClick(ws),
11104
+ onSettings: () => onEditClick(ws),
11105
+ onLeave: () => onLeaveClick(ws)
11106
+ }
11107
+ )
11108
+ ] }, ws._id))
11061
11109
  }
11062
11110
  ),
11063
11111
  pageCount > 1 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
@@ -11255,6 +11303,28 @@ function SettingsContentInner({
11255
11303
  (0, import_react17.useEffect)(() => {
11256
11304
  void refreshWorkspaceList();
11257
11305
  }, [refreshWorkspaceList]);
11306
+ const [listOrganizations, setListOrganizations] = (0, import_react17.useState)([]);
11307
+ (0, import_react17.useEffect)(() => {
11308
+ if (activeTab !== "workspaceList" || typeof organization?.list !== "function") {
11309
+ return;
11310
+ }
11311
+ let cancelled = false;
11312
+ organization.list().then((orgs) => {
11313
+ if (!cancelled) {
11314
+ setListOrganizations(
11315
+ (orgs ?? []).map((org) => ({
11316
+ _id: org._id,
11317
+ name: org.name,
11318
+ role: org.role
11319
+ }))
11320
+ );
11321
+ }
11322
+ }).catch(() => {
11323
+ });
11324
+ return () => {
11325
+ cancelled = true;
11326
+ };
11327
+ }, [activeTab, organization]);
11258
11328
  const switchWorkspace = (0, import_react17.useCallback)(
11259
11329
  async (id) => {
11260
11330
  await workspace.switch(id);
@@ -11903,6 +11973,7 @@ function SettingsContentInner({
11903
11973
  workspaces: displayWorkspaces,
11904
11974
  loading: workspaceListLoading && workspaceList.length === 0,
11905
11975
  fetchPlans: workspace.fetchPlans,
11976
+ organizations: listOrganizations,
11906
11977
  onCreateClick: handleCreateClick,
11907
11978
  onEditClick: handleEditClick,
11908
11979
  onSwitchClick: async (ws) => {
package/dist/index.mjs CHANGED
@@ -163,6 +163,7 @@ function useWorkspaceOrganization({
163
163
 
164
164
  // src/settings-content.tsx
165
165
  import {
166
+ Fragment as Fragment11,
166
167
  useState as useState15,
167
168
  useEffect as useEffect13,
168
169
  useRef as useRef7,
@@ -10097,7 +10098,7 @@ function TokenTable({ tokens, deletingId, onRevoke, onDelete }) {
10097
10098
  }
10098
10099
 
10099
10100
  // src/settings-content.tsx
10100
- import { Fragment as Fragment11, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
10101
+ import { Fragment as Fragment12, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
10101
10102
  function deriveInitials(name) {
10102
10103
  return name.split(/\s+/).slice(0, 2).map((part) => part[0]?.toUpperCase() ?? "").join("") || "WS";
10103
10104
  }
@@ -10205,14 +10206,14 @@ function SettingsNav({
10205
10206
  /* @__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" }),
10206
10207
  item("workspace", (color) => /* @__PURE__ */ jsx22(SiconSettings2, { className: "w-5 h-5", color })),
10207
10208
  item("workspaceMembers", (color) => /* @__PURE__ */ jsx22(SiconTeam, { className: "w-5 h-5", color })),
10208
- isWorkspaceAdmin && /* @__PURE__ */ jsxs19(Fragment11, { children: [
10209
+ isWorkspaceAdmin && /* @__PURE__ */ jsxs19(Fragment12, { children: [
10209
10210
  item("billing", (color) => /* @__PURE__ */ jsx22(SiconBilling, { className: "w-5 h-5", color })),
10210
10211
  item("apikey", (color) => /* @__PURE__ */ jsx22(SiconKey_default, { className: "w-5 h-5", color }))
10211
10212
  ] }),
10212
10213
  !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." })
10213
10214
  ] }),
10214
10215
  /* @__PURE__ */ jsx22(ScHDivider, {}),
10215
- /* @__PURE__ */ jsx22("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: hasOrganization ? /* @__PURE__ */ jsxs19(Fragment11, { children: [
10216
+ /* @__PURE__ */ jsx22("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: hasOrganization ? /* @__PURE__ */ jsxs19(Fragment12, { children: [
10216
10217
  /* @__PURE__ */ jsx22("div", { style: { padding: "4px 12px", fontSize: 11, fontWeight: 500, color: MUTED_COLOR2, textTransform: "uppercase", letterSpacing: "0.08em" }, children: "Organization" }),
10217
10218
  item("organization", (color) => /* @__PURE__ */ jsx22(SiconTeam, { className: "w-5 h-5", color })),
10218
10219
  item("organizationWorkspaces", (color) => /* @__PURE__ */ jsx22(SiconWorkspace2, { className: "w-5 h-5", color }))
@@ -10510,7 +10511,7 @@ function LanguageDropdown({
10510
10511
  ScMenuOptions,
10511
10512
  {
10512
10513
  text: lang.label,
10513
- icon: /* @__PURE__ */ jsx22(Fragment11, {}),
10514
+ icon: /* @__PURE__ */ jsx22(Fragment12, {}),
10514
10515
  hover: isActive ? "true" : "false",
10515
10516
  variant: "default",
10516
10517
  role: "option",
@@ -10901,6 +10902,36 @@ function ProfileTab() {
10901
10902
  );
10902
10903
  }
10903
10904
  var WORKSPACE_LIST_PAGE_SIZE = 10;
10905
+ function groupWorkspaceList(workspaces, organizations = []) {
10906
+ const ordered = [
10907
+ ...organizations.filter((org) => org.role !== "guest"),
10908
+ ...organizations.filter((org) => org.role === "guest")
10909
+ ];
10910
+ const groups = [];
10911
+ for (const org of ordered) {
10912
+ const inOrg = workspaces.filter((ws) => ws.organizationId === org._id);
10913
+ if (inOrg.length) {
10914
+ groups.push({
10915
+ key: org._id,
10916
+ label: org.role === "guest" ? `${org.name} \xB7 Guest` : org.name,
10917
+ workspaces: inOrg
10918
+ });
10919
+ }
10920
+ }
10921
+ const known = new Set(organizations.map((org) => org._id));
10922
+ const ungrouped = workspaces.filter(
10923
+ (ws) => !ws.organizationId || !known.has(ws.organizationId)
10924
+ );
10925
+ if (ungrouped.length) {
10926
+ groups.push({
10927
+ key: "__no_org__",
10928
+ // "No organization" only means something next to named groups.
10929
+ label: groups.length ? "No organization" : "Other Workspaces",
10930
+ workspaces: ungrouped
10931
+ });
10932
+ }
10933
+ return groups;
10934
+ }
10904
10935
  function WorkspaceListTab({
10905
10936
  workspaces,
10906
10937
  loading,
@@ -10909,15 +10940,27 @@ function WorkspaceListTab({
10909
10940
  onSwitchClick,
10910
10941
  onLeaveClick,
10911
10942
  fetchPlans,
10943
+ organizations = [],
10912
10944
  pageSize = WORKSPACE_LIST_PAGE_SIZE
10913
10945
  }) {
10914
10946
  const currentWorkspace = workspaces.find((ws) => ws.isCurrent);
10915
- const otherWorkspaces = workspaces.filter((ws) => !ws.isCurrent);
10947
+ const groups = groupWorkspaceList(
10948
+ workspaces.filter((ws) => !ws.isCurrent),
10949
+ organizations
10950
+ );
10951
+ const rows = groups.flatMap(
10952
+ (group) => group.workspaces.map((ws) => ({ ws, group }))
10953
+ );
10954
+ const otherWorkspaces = rows.map((row) => row.ws);
10955
+ const currentOrganization = organizations.find(
10956
+ (org) => org._id && org._id === currentWorkspace?.organizationId
10957
+ );
10916
10958
  const pageCount = Math.max(1, Math.ceil(otherWorkspaces.length / pageSize));
10917
10959
  const [page, setPage] = useState15(0);
10918
10960
  const safePage = Math.min(page, pageCount - 1);
10919
10961
  const pageStart = safePage * pageSize;
10920
- const pageWorkspaces = otherWorkspaces.slice(pageStart, pageStart + pageSize);
10962
+ const pageRows = rows.slice(pageStart, pageStart + pageSize);
10963
+ const pageWorkspaces = pageRows.map((row) => row.ws);
10921
10964
  const [plans, setPlans] = useState15({});
10922
10965
  const requestedPlans = useRef7(/* @__PURE__ */ new Set());
10923
10966
  const visibleIds = [
@@ -10979,7 +11022,7 @@ function WorkspaceListTab({
10979
11022
  className: "flex flex-col items-start shrink-0 w-full",
10980
11023
  style: { gap: 16, padding: "var(--spacing-md) 0" },
10981
11024
  children: [
10982
- /* @__PURE__ */ jsx22(
11025
+ /* @__PURE__ */ jsxs19(
10983
11026
  "p",
10984
11027
  {
10985
11028
  className: "w-full overflow-hidden text-ellipsis whitespace-nowrap",
@@ -10990,7 +11033,10 @@ function WorkspaceListTab({
10990
11033
  fontWeight: 400,
10991
11034
  lineHeight: "var(--line-height-line-height-md)"
10992
11035
  },
10993
- children: "Current Workspace"
11036
+ children: [
11037
+ "Current Workspace",
11038
+ currentOrganization ? ` \xB7 ${currentOrganization.name}${currentOrganization.role === "guest" ? " (guest)" : ""}` : ""
11039
+ ]
10994
11040
  }
10995
11041
  ),
10996
11042
  /* @__PURE__ */ jsx22(
@@ -11026,41 +11072,43 @@ function WorkspaceListTab({
11026
11072
  className: "flex flex-col items-start flex-1 min-h-0 w-full",
11027
11073
  style: { gap: 16, overflowY: "auto" },
11028
11074
  children: [
11029
- /* @__PURE__ */ jsx22(
11030
- "p",
11031
- {
11032
- className: "w-full overflow-hidden text-ellipsis whitespace-nowrap shrink-0",
11033
- style: {
11034
- color: "var(--alias-text---icons-muted)",
11035
- fontFamily: "var(--font-family-font-family-body)",
11036
- fontSize: "var(--font-size-font-size-md)",
11037
- fontWeight: 400,
11038
- lineHeight: "var(--line-height-line-height-md)"
11039
- },
11040
- children: "Other Workspaces"
11041
- }
11042
- ),
11043
11075
  /* @__PURE__ */ jsx22(
11044
11076
  "div",
11045
11077
  {
11046
11078
  className: "flex flex-col items-start w-full",
11047
11079
  style: { gap: 16 },
11048
- children: pageWorkspaces.map((ws) => /* @__PURE__ */ jsx22(
11049
- ScWorkspaceSwitchCard,
11050
- {
11051
- wsName: ws.name,
11052
- initials: ws.initials,
11053
- imageUrl: ws.imageUrl,
11054
- role: ws.role,
11055
- plan: planOf(ws),
11056
- ownerId: ws.ownerEmail,
11057
- type: "otherWS",
11058
- onSwitch: () => onSwitchClick(ws),
11059
- onSettings: () => onEditClick(ws),
11060
- onLeave: () => onLeaveClick(ws)
11061
- },
11062
- ws._id
11063
- ))
11080
+ children: pageRows.map(({ ws, group }, index) => /* @__PURE__ */ jsxs19(Fragment11, { children: [
11081
+ (index === 0 || pageRows[index - 1].group.key !== group.key) && /* @__PURE__ */ jsx22(
11082
+ "p",
11083
+ {
11084
+ className: "w-full overflow-hidden text-ellipsis whitespace-nowrap shrink-0",
11085
+ style: {
11086
+ color: "var(--alias-text---icons-muted)",
11087
+ fontFamily: "var(--font-family-font-family-body)",
11088
+ fontSize: "var(--font-size-font-size-md)",
11089
+ fontWeight: 400,
11090
+ lineHeight: "var(--line-height-line-height-md)",
11091
+ marginTop: index === 0 ? 0 : 8
11092
+ },
11093
+ children: group.label
11094
+ }
11095
+ ),
11096
+ /* @__PURE__ */ jsx22(
11097
+ ScWorkspaceSwitchCard,
11098
+ {
11099
+ wsName: ws.name,
11100
+ initials: ws.initials,
11101
+ imageUrl: ws.imageUrl,
11102
+ role: ws.role,
11103
+ plan: planOf(ws),
11104
+ ownerId: ws.ownerEmail,
11105
+ type: "otherWS",
11106
+ onSwitch: () => onSwitchClick(ws),
11107
+ onSettings: () => onEditClick(ws),
11108
+ onLeave: () => onLeaveClick(ws)
11109
+ }
11110
+ )
11111
+ ] }, ws._id))
11064
11112
  }
11065
11113
  ),
11066
11114
  pageCount > 1 && /* @__PURE__ */ jsxs19(
@@ -11258,6 +11306,28 @@ function SettingsContentInner({
11258
11306
  useEffect13(() => {
11259
11307
  void refreshWorkspaceList();
11260
11308
  }, [refreshWorkspaceList]);
11309
+ const [listOrganizations, setListOrganizations] = useState15([]);
11310
+ useEffect13(() => {
11311
+ if (activeTab !== "workspaceList" || typeof organization?.list !== "function") {
11312
+ return;
11313
+ }
11314
+ let cancelled = false;
11315
+ organization.list().then((orgs) => {
11316
+ if (!cancelled) {
11317
+ setListOrganizations(
11318
+ (orgs ?? []).map((org) => ({
11319
+ _id: org._id,
11320
+ name: org.name,
11321
+ role: org.role
11322
+ }))
11323
+ );
11324
+ }
11325
+ }).catch(() => {
11326
+ });
11327
+ return () => {
11328
+ cancelled = true;
11329
+ };
11330
+ }, [activeTab, organization]);
11261
11331
  const switchWorkspace = useCallback7(
11262
11332
  async (id) => {
11263
11333
  await workspace.switch(id);
@@ -11645,7 +11715,7 @@ function SettingsContentInner({
11645
11715
  children: "Settings"
11646
11716
  }
11647
11717
  ),
11648
- scopeCrumb && /* @__PURE__ */ jsxs19(Fragment11, { children: [
11718
+ scopeCrumb && /* @__PURE__ */ jsxs19(Fragment12, { children: [
11649
11719
  /* @__PURE__ */ jsx22(SiconRight2, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11650
11720
  /* @__PURE__ */ jsx22(
11651
11721
  "span",
@@ -11678,7 +11748,7 @@ function SettingsContentInner({
11678
11748
  children: leafLabel
11679
11749
  }
11680
11750
  ),
11681
- isBillingPlans && /* @__PURE__ */ jsxs19(Fragment11, { children: [
11751
+ isBillingPlans && /* @__PURE__ */ jsxs19(Fragment12, { children: [
11682
11752
  /* @__PURE__ */ jsx22(SiconRight2, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
11683
11753
  /* @__PURE__ */ jsx22(
11684
11754
  "span",
@@ -11906,6 +11976,7 @@ function SettingsContentInner({
11906
11976
  workspaces: displayWorkspaces,
11907
11977
  loading: workspaceListLoading && workspaceList.length === 0,
11908
11978
  fetchPlans: workspace.fetchPlans,
11979
+ organizations: listOrganizations,
11909
11980
  onCreateClick: handleCreateClick,
11910
11981
  onEditClick: handleEditClick,
11911
11982
  onSwitchClick: async (ws) => {
@@ -12355,6 +12426,7 @@ export {
12355
12426
  WorkspacePicker,
12356
12427
  WorkspaceTab,
12357
12428
  countLabel,
12429
+ groupWorkspaceList,
12358
12430
  loadWorkspaceOrganization,
12359
12431
  resolveSettingsTabFromPath,
12360
12432
  useSettingsAdapters,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamoid/settings",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",