@streamoid/settings 0.6.4 → 0.6.5

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/README.md CHANGED
@@ -175,3 +175,43 @@ owns routing; apps without organization settings omit the callback.
175
175
  The adapter prefers `organizationName` from the authorized workspace response.
176
176
  This lets invited workspace members see its owner without organization membership;
177
177
  the separately checked organization role still controls settings navigation.
178
+
179
+ API Keys navigation and controls are visible only to the selected workspace's
180
+ Admins. When the host supplies only a workspace id, its role is resolved from
181
+ the authorized workspace list. Other roles opening the route see an Admin-only
182
+ message. The page links to https://docs.streamoid.com.
183
+
184
+ Billing and API Keys are grouped under Workspace and restricted to workspace
185
+ Admins in the menu and direct settings routes. Other members see a contact-admin
186
+ explanation and a link to workspace members; billing content is not mounted.
187
+ API documentation lives in an integration help card above the keys list.
188
+
189
+ Hosts should provide `workspace.organizationRequest` using the same authenticated
190
+ transport as their workspace popup. Workspace General and Members then display
191
+ the selected workspace owner independently of account organization membership.
192
+ Unknown or failed lookups are never labeled as an unowned workspace.
193
+
194
+ Hosts that delegate organization management to CXO can set
195
+ `organization.managementUrl` together with `workspace.organizationRequest`.
196
+ Settings then shows the selected workspace's owning organization and the
197
+ independently resolved organization role, rather than treating a null local
198
+ organization adapter as proof that the user has no membership. Management opens
199
+ in the central dashboard; an unavailable role never implies membership.
200
+ The settings navigation separates the Account heading from its Profile action.
201
+ Workspace identity remains in the main sidebar and the page breadcrumb.
202
+
203
+ My workspaces belongs to Account: it lists the signed-in user’s workspace memberships. Organization → Workspaces remains scoped to the organization. The existing `workspace/all` route is retained for bookmark compatibility.
204
+
205
+ Member lists use compact rows with a shared column grid, a short count summary,
206
+ and embedded app favicon artwork in Access. App badges describe tool access;
207
+ invite and credit permissions have separate Yes/No columns. Billing uses compact
208
+ summary cards and usage-log rows while preserving all amounts and actions.
209
+
210
+ ### Shared settings appearance
211
+
212
+ `SettingsContent` mounts a route-scoped appearance layer. While settings is
213
+ visible, it normalizes the root rem scale to 16px, uses a 14px system-font body,
214
+ and shares light/dark canvas, card, text, divider and selection colors with the
215
+ host sidebar. Removing settings restores the host theme. Host wrappers must
216
+ remain transparent and use `--alias-surface-canvas` for the app floor; do not
217
+ paint `--alias-surface-base` behind the whole settings page.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,22 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { SVGProps, ReactNode } from 'react';
3
- import { WorkspaceUsage, ScWorkspaceAccountMenuProps } from '@streamoid/ui';
3
+ import { ScWorkspaceAccountMenuProps, WorkspaceUsage } from '@streamoid/ui';
4
+
5
+ /** Host transport: authenticated GET returning the unified API envelope. */
6
+ type WorkspaceOrganizationRequest = (path: string, signal: AbortSignal) => Promise<unknown>;
7
+ interface WorkspaceOrganization {
8
+ _id: string;
9
+ name: string;
10
+ role?: string;
11
+ }
12
+ /** Resolve only the selected workspace's owner, never a user's first org. */
13
+ declare function loadWorkspaceOrganization(workspaceId: string, request: WorkspaceOrganizationRequest, signal: AbortSignal): Promise<WorkspaceOrganization | null>;
14
+ declare function useWorkspaceOrganization({ workspaceId, request, enabled, onOpenOrganization, }: {
15
+ workspaceId?: string | null;
16
+ request: WorkspaceOrganizationRequest;
17
+ enabled?: boolean;
18
+ onOpenOrganization?: (organizationId: string) => void;
19
+ }): Pick<ScWorkspaceAccountMenuProps, "organizationName" | "organizationRole" | "organizationStatus" | "onOrganizationClick">;
4
20
 
5
21
  /**
6
22
  * Settings tab identifiers and URL mapping helpers.
@@ -26,7 +42,7 @@ type SettingsTab = "profile"
26
42
  | "workspace"
27
43
  /** Workspace › Members — was the top-level "Team" tab. */
28
44
  | "workspaceMembers"
29
- /** Workspace › All workspaces — the switch/create list. */
45
+ /** Account › My workspaces — the memberships and switch/create list. */
30
46
  | "workspaceList"
31
47
  /** Organization › People. */
32
48
  | "organization"
@@ -73,26 +89,6 @@ declare const TAB_DESCRIPTIONS: Record<SettingsTab, string>;
73
89
  */
74
90
  declare function resolveSettingsTabFromPath(path: string): SettingsTab;
75
91
 
76
- /**
77
- * Adapter contracts for @streamoid/settings.
78
- *
79
- * The host application (cxo-dashboard, photogenix, etc.) implements one
80
- * `SettingsAdapters` object and passes it into <SettingsContent>. Every
81
- * sub-component in this package reads from `useSettingsAdapters()` instead of
82
- * importing the host's auth/workspace/services/router/toast directly.
83
- *
84
- * Design notes:
85
- * - State that the host already owns reactively (current user, current
86
- * workspace) is *embedded* in the adapter object. The host re-creates the
87
- * adapter object (or its inner objects) when its state changes; React's
88
- * normal render-on-prop-change semantics flow that change into the package.
89
- * - Lists that the package fetches on demand (workspace list, members,
90
- * invoices, tokens) are exposed as async functions. The package owns the
91
- * `loading`/`data` state internally and re-fetches after mutations.
92
- * - Mutations don't return anything the package depends on; the convention is
93
- * "fire the mutation, then refetch". Errors throw.
94
- */
95
-
96
92
  interface SettingsAuthUser {
97
93
  id: string;
98
94
  email: string;
@@ -180,6 +176,8 @@ interface SettingsWorkspaceListItem {
180
176
  ownerEmail?: string;
181
177
  }
182
178
  interface SettingsWorkspaceAdapter {
179
+ /** Same authenticated transport used by the sidebar owner lookup. */
180
+ organizationRequest?: WorkspaceOrganizationRequest;
183
181
  current: SettingsWorkspaceCurrent | null;
184
182
  list: () => Promise<SettingsWorkspaceListItem[]>;
185
183
  /**
@@ -348,6 +346,8 @@ interface OrganizationDomainMatch {
348
346
  * mutations are fire-then-refetch and throw on failure.
349
347
  */
350
348
  interface SettingsOrganizationAdapter {
349
+ /** Host delegates organization management to the central dashboard. */
350
+ managementUrl?: string;
351
351
  current: SettingsOrganizationCurrent | null;
352
352
  list: () => Promise<SettingsOrganizationListItem[]>;
353
353
  create: (input: {
@@ -995,12 +995,13 @@ interface WorkspaceGeneralTabProps {
995
995
  memberCount?: number | null;
996
996
  /** Name of the parent organization, when the workspace has joined one. */
997
997
  organizationName?: string | null;
998
+ organizationStatus?: "loading" | "error";
998
999
  saving: boolean;
999
1000
  onSave: (name: string, imageFile: File | null, imageRemoved: boolean) => Promise<boolean>;
1000
1001
  onLeave: () => void;
1001
1002
  onDelete: () => void;
1002
1003
  }
1003
- declare function WorkspaceGeneralTab({ workspace, loading, memberCount, organizationName, saving, onSave, onLeave, onDelete, }: WorkspaceGeneralTabProps): react.JSX.Element;
1004
+ declare function WorkspaceGeneralTab({ workspace, loading, memberCount, organizationName, organizationStatus, saving, onSave, onLeave, onDelete, }: WorkspaceGeneralTabProps): react.JSX.Element;
1004
1005
 
1005
1006
  type IconProps = Omit<SVGProps<SVGSVGElement>, 'color' | 'strokeWidth' | 'width' | 'height'> & {
1006
1007
  color?: string;
@@ -1394,20 +1395,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1394
1395
  */
1395
1396
  declare function useSettingsAdapters(): SettingsAdapters;
1396
1397
 
1397
- /** Host transport: authenticated GET returning the unified API envelope. */
1398
- type WorkspaceOrganizationRequest = (path: string, signal: AbortSignal) => Promise<unknown>;
1399
- interface WorkspaceOrganization {
1400
- _id: string;
1401
- name: string;
1402
- role?: string;
1403
- }
1404
- /** Resolve only the selected workspace's owner, never a user's first org. */
1405
- declare function loadWorkspaceOrganization(workspaceId: string, request: WorkspaceOrganizationRequest, signal: AbortSignal): Promise<WorkspaceOrganization | null>;
1406
- declare function useWorkspaceOrganization({ workspaceId, request, enabled, onOpenOrganization, }: {
1407
- workspaceId?: string | null;
1408
- request: WorkspaceOrganizationRequest;
1409
- enabled?: boolean;
1410
- onOpenOrganization?: (organizationId: string) => void;
1411
- }): Pick<ScWorkspaceAccountMenuProps, "organizationName" | "organizationRole" | "organizationStatus" | "onOrganizationClick">;
1412
-
1413
1398
  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, OrganizationInviteModal, type OrganizationInviteModalProps, type OrganizationJoinRequest, type OrganizationMember, 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, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspaceTab, type WorkspaceUsageResponse, countLabel, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,22 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { SVGProps, ReactNode } from 'react';
3
- import { WorkspaceUsage, ScWorkspaceAccountMenuProps } from '@streamoid/ui';
3
+ import { ScWorkspaceAccountMenuProps, WorkspaceUsage } from '@streamoid/ui';
4
+
5
+ /** Host transport: authenticated GET returning the unified API envelope. */
6
+ type WorkspaceOrganizationRequest = (path: string, signal: AbortSignal) => Promise<unknown>;
7
+ interface WorkspaceOrganization {
8
+ _id: string;
9
+ name: string;
10
+ role?: string;
11
+ }
12
+ /** Resolve only the selected workspace's owner, never a user's first org. */
13
+ declare function loadWorkspaceOrganization(workspaceId: string, request: WorkspaceOrganizationRequest, signal: AbortSignal): Promise<WorkspaceOrganization | null>;
14
+ declare function useWorkspaceOrganization({ workspaceId, request, enabled, onOpenOrganization, }: {
15
+ workspaceId?: string | null;
16
+ request: WorkspaceOrganizationRequest;
17
+ enabled?: boolean;
18
+ onOpenOrganization?: (organizationId: string) => void;
19
+ }): Pick<ScWorkspaceAccountMenuProps, "organizationName" | "organizationRole" | "organizationStatus" | "onOrganizationClick">;
4
20
 
5
21
  /**
6
22
  * Settings tab identifiers and URL mapping helpers.
@@ -26,7 +42,7 @@ type SettingsTab = "profile"
26
42
  | "workspace"
27
43
  /** Workspace › Members — was the top-level "Team" tab. */
28
44
  | "workspaceMembers"
29
- /** Workspace › All workspaces — the switch/create list. */
45
+ /** Account › My workspaces — the memberships and switch/create list. */
30
46
  | "workspaceList"
31
47
  /** Organization › People. */
32
48
  | "organization"
@@ -73,26 +89,6 @@ declare const TAB_DESCRIPTIONS: Record<SettingsTab, string>;
73
89
  */
74
90
  declare function resolveSettingsTabFromPath(path: string): SettingsTab;
75
91
 
76
- /**
77
- * Adapter contracts for @streamoid/settings.
78
- *
79
- * The host application (cxo-dashboard, photogenix, etc.) implements one
80
- * `SettingsAdapters` object and passes it into <SettingsContent>. Every
81
- * sub-component in this package reads from `useSettingsAdapters()` instead of
82
- * importing the host's auth/workspace/services/router/toast directly.
83
- *
84
- * Design notes:
85
- * - State that the host already owns reactively (current user, current
86
- * workspace) is *embedded* in the adapter object. The host re-creates the
87
- * adapter object (or its inner objects) when its state changes; React's
88
- * normal render-on-prop-change semantics flow that change into the package.
89
- * - Lists that the package fetches on demand (workspace list, members,
90
- * invoices, tokens) are exposed as async functions. The package owns the
91
- * `loading`/`data` state internally and re-fetches after mutations.
92
- * - Mutations don't return anything the package depends on; the convention is
93
- * "fire the mutation, then refetch". Errors throw.
94
- */
95
-
96
92
  interface SettingsAuthUser {
97
93
  id: string;
98
94
  email: string;
@@ -180,6 +176,8 @@ interface SettingsWorkspaceListItem {
180
176
  ownerEmail?: string;
181
177
  }
182
178
  interface SettingsWorkspaceAdapter {
179
+ /** Same authenticated transport used by the sidebar owner lookup. */
180
+ organizationRequest?: WorkspaceOrganizationRequest;
183
181
  current: SettingsWorkspaceCurrent | null;
184
182
  list: () => Promise<SettingsWorkspaceListItem[]>;
185
183
  /**
@@ -348,6 +346,8 @@ interface OrganizationDomainMatch {
348
346
  * mutations are fire-then-refetch and throw on failure.
349
347
  */
350
348
  interface SettingsOrganizationAdapter {
349
+ /** Host delegates organization management to the central dashboard. */
350
+ managementUrl?: string;
351
351
  current: SettingsOrganizationCurrent | null;
352
352
  list: () => Promise<SettingsOrganizationListItem[]>;
353
353
  create: (input: {
@@ -995,12 +995,13 @@ interface WorkspaceGeneralTabProps {
995
995
  memberCount?: number | null;
996
996
  /** Name of the parent organization, when the workspace has joined one. */
997
997
  organizationName?: string | null;
998
+ organizationStatus?: "loading" | "error";
998
999
  saving: boolean;
999
1000
  onSave: (name: string, imageFile: File | null, imageRemoved: boolean) => Promise<boolean>;
1000
1001
  onLeave: () => void;
1001
1002
  onDelete: () => void;
1002
1003
  }
1003
- declare function WorkspaceGeneralTab({ workspace, loading, memberCount, organizationName, saving, onSave, onLeave, onDelete, }: WorkspaceGeneralTabProps): react.JSX.Element;
1004
+ declare function WorkspaceGeneralTab({ workspace, loading, memberCount, organizationName, organizationStatus, saving, onSave, onLeave, onDelete, }: WorkspaceGeneralTabProps): react.JSX.Element;
1004
1005
 
1005
1006
  type IconProps = Omit<SVGProps<SVGSVGElement>, 'color' | 'strokeWidth' | 'width' | 'height'> & {
1006
1007
  color?: string;
@@ -1394,20 +1395,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1394
1395
  */
1395
1396
  declare function useSettingsAdapters(): SettingsAdapters;
1396
1397
 
1397
- /** Host transport: authenticated GET returning the unified API envelope. */
1398
- type WorkspaceOrganizationRequest = (path: string, signal: AbortSignal) => Promise<unknown>;
1399
- interface WorkspaceOrganization {
1400
- _id: string;
1401
- name: string;
1402
- role?: string;
1403
- }
1404
- /** Resolve only the selected workspace's owner, never a user's first org. */
1405
- declare function loadWorkspaceOrganization(workspaceId: string, request: WorkspaceOrganizationRequest, signal: AbortSignal): Promise<WorkspaceOrganization | null>;
1406
- declare function useWorkspaceOrganization({ workspaceId, request, enabled, onOpenOrganization, }: {
1407
- workspaceId?: string | null;
1408
- request: WorkspaceOrganizationRequest;
1409
- enabled?: boolean;
1410
- onOpenOrganization?: (organizationId: string) => void;
1411
- }): Pick<ScWorkspaceAccountMenuProps, "organizationName" | "organizationRole" | "organizationStatus" | "onOrganizationClick">;
1412
-
1413
1398
  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, OrganizationInviteModal, type OrganizationInviteModalProps, type OrganizationJoinRequest, type OrganizationMember, 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, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, type WorkspaceOrganization, type WorkspaceOrganizationRequest, WorkspaceTab, type WorkspaceUsageResponse, countLabel, loadWorkspaceOrganization, resolveSettingsTabFromPath, useSettingsAdapters, useWorkspaceOrganization, userLanguageLabel };