@streamoid/settings 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -104,6 +104,10 @@ interface SettingsAuthUser {
104
104
  "unspecified" = explicit skip; otherwise one of the host-defined ids
105
105
  (e.g. "design", "merchandising"). */
106
106
  userSpecialization?: string;
107
+ /** Preferred UI language as a code from `USER_LANGUAGES` (e.g. "en", "kn").
108
+ Absent or empty means the account has never chosen one, which reads as
109
+ `DEFAULT_USER_LANGUAGE` rather than as blank. */
110
+ language?: string;
107
111
  }
108
112
  /** Option shape returned by `auth.getSpecializations` — drives the
109
113
  Specialization dropdown in Settings → Account. The host adapter is the
@@ -121,6 +125,7 @@ interface SettingsAuthAdapter {
121
125
  name?: string;
122
126
  imageUrl?: string | null;
123
127
  userSpecialization?: string;
128
+ language?: string;
124
129
  }) => Promise<void>;
125
130
  clearAuth: () => void;
126
131
  logout: () => Promise<void>;
@@ -779,6 +784,49 @@ interface SettingsAdapters {
779
784
  imageUpload: SettingsImageUploadAdapter;
780
785
  }
781
786
 
787
+ /**
788
+ * The apps the invite / update dialog can offer a toggle for.
789
+ *
790
+ * Ordered as the dialog renders them. Exported because a host has to be able to
791
+ * name them in `hiddenApps` — see InviteUpdateModal.
792
+ */
793
+ declare const APP_KEYS: readonly ["artifax", "photogenix", "returns", "catalogix"];
794
+ type AppKey = (typeof APP_KEYS)[number];
795
+ interface UserPermissions {
796
+ artifax: boolean;
797
+ photogenix: boolean;
798
+ catalogix: boolean;
799
+ /**
800
+ * SPF Returns.
801
+ *
802
+ * Its services identify themselves by group: the provider carries five of
803
+ * them — the dashboard, Claims, Capture and two settings pages — all named
804
+ * "returns" and all in a "Returns" group. Granting the app means granting the
805
+ * group, which is what `permissionServiceIds` does.
806
+ */
807
+ returns: boolean;
808
+ canUseCredits: boolean;
809
+ canInviteUser: boolean;
810
+ role: "admin" | "member";
811
+ catalogixStores: string[];
812
+ }
813
+ interface TeamMember {
814
+ id: string;
815
+ kind: "member" | "invite";
816
+ /** Unified user id (for change-role and remove-users userIds). */
817
+ userId?: string;
818
+ /** Invitation id (for remove-users invitationIds). */
819
+ invitationId?: string;
820
+ /** Invitation token (for invite-cancel flow, if needed). */
821
+ inviteToken?: string;
822
+ name?: string;
823
+ userEmail: string;
824
+ invitedBy: string;
825
+ signedOn?: string;
826
+ permissions: UserPermissions;
827
+ }
828
+ declare const DEFAULT_PERMISSIONS: UserPermissions;
829
+
782
830
  type WorkspaceInfo = SettingsWorkspaceListItem & {
783
831
  initials?: string;
784
832
  plan?: string;
@@ -812,6 +860,14 @@ declare const WorkspaceTab: typeof WorkspaceListTab;
812
860
  declare function ReferralTab(): react.JSX.Element;
813
861
  interface SettingsContentProps {
814
862
  adapters: SettingsAdapters;
863
+ /**
864
+ * App rows the Members tab's invite / update dialog leaves out.
865
+ *
866
+ * Omit it and nothing is hidden, which is what every host got before this
867
+ * existed. A console that administers one product hides the others, so it
868
+ * stops inviting people to products it cannot administer.
869
+ */
870
+ hiddenApps?: readonly AppKey[];
815
871
  /** Currently active tab. The host owns routing and resolves this from the URL. */
816
872
  activeTab?: SettingsTab;
817
873
  /**
@@ -825,7 +881,7 @@ interface SettingsContentProps {
825
881
  */
826
882
  onClose?: () => void;
827
883
  }
828
- declare function SettingsContent({ adapters, activeTab, onClose, }: SettingsContentProps): react.JSX.Element;
884
+ declare function SettingsContent({ adapters, activeTab, onClose, hiddenApps, }: SettingsContentProps): react.JSX.Element;
829
885
 
830
886
  interface WorkspaceData {
831
887
  id: string;
@@ -880,7 +936,7 @@ declare function BillingContent({ embedded, showPlans: showPlansProp, onShowPlan
880
936
  onShowPlansChange?: (open: boolean) => void;
881
937
  }): react__default.JSX.Element;
882
938
 
883
- declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, workspaceName, workspaceImageUrl, organizationName, }?: {
939
+ declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, workspaceName, workspaceImageUrl, organizationName, hiddenApps, }?: {
884
940
  embedded?: boolean;
885
941
  onInviteOpen?: boolean;
886
942
  onInviteOpenChange?: (open: boolean) => void;
@@ -894,6 +950,11 @@ declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, work
894
950
  workspaceImageUrl?: string;
895
951
  /** Parent organization, when the workspace has joined one. */
896
952
  organizationName?: string | null;
953
+ /**
954
+ * App rows the invite / update dialog leaves out. Omitted, nothing is hidden
955
+ * — see InviteUpdateModal for what hiding one does and does not change.
956
+ */
957
+ hiddenApps?: readonly AppKey[];
897
958
  }): react.JSX.Element;
898
959
 
899
960
  /**
@@ -922,6 +983,40 @@ declare function TokensContent({ embedded, showRevokedOverride, onShowRevokedCha
922
983
  onCreateOpenChange?: (v: boolean) => void;
923
984
  }): react.JSX.Element;
924
985
 
986
+ /**
987
+ * The account-level language preference, shared by every Streamoid dashboard.
988
+ *
989
+ * Stored as the code and never as the label. `Intl`, the `lang` attribute and
990
+ * every translation API want "kn"; and a label reworded later ("Portuguese" →
991
+ * "Português (Brasil)") should be an edit here, not a migration across every
992
+ * user row. Hosts that want to show the language render the label from this
993
+ * list rather than keeping a map of their own — one list, so two dashboards
994
+ * cannot disagree about what "pt" is called.
995
+ *
996
+ * Mirrors `userLanguages` in the unified backend, which is the source of truth
997
+ * and rejects anything outside it.
998
+ */
999
+ interface UserLanguage {
1000
+ code: string;
1001
+ /** The English name — "Kannada". What the picker shows. */
1002
+ label: string;
1003
+ }
1004
+ declare const USER_LANGUAGES: readonly UserLanguage[];
1005
+ /**
1006
+ * English until somebody says otherwise.
1007
+ *
1008
+ * Unlike a specialization — where "" means never-answered, and the dashboard
1009
+ * has a reason to keep asking — an unanswered language already has a sensible
1010
+ * answer: the language these dashboards are written in. So a profile with no
1011
+ * language reads as English rather than as blank, and the dropdown is never
1012
+ * shown empty.
1013
+ */
1014
+ declare const DEFAULT_USER_LANGUAGE = "en";
1015
+ /** The label for a code, falling back to the code itself for one this build
1016
+ does not know — a newer dashboard may have written it, and showing "sw" is
1017
+ better than showing nothing. */
1018
+ declare function userLanguageLabel(code: string | undefined | null): string;
1019
+
925
1020
  interface ProfileAvatarProps {
926
1021
  name: string;
927
1022
  profileImage?: string;
@@ -1108,41 +1203,6 @@ interface BuyCreditsModalProps {
1108
1203
  }
1109
1204
  declare function BuyCreditsModal({ currencySymbol, country, onClose, onBuy, }: BuyCreditsModalProps): react.JSX.Element;
1110
1205
 
1111
- interface UserPermissions {
1112
- artifax: boolean;
1113
- photogenix: boolean;
1114
- catalogix: boolean;
1115
- /**
1116
- * SPF Returns.
1117
- *
1118
- * Its services identify themselves by group: the provider carries five of
1119
- * them — the dashboard, Claims, Capture and two settings pages — all named
1120
- * "returns" and all in a "Returns" group. Granting the app means granting the
1121
- * group, which is what `permissionServiceIds` does.
1122
- */
1123
- returns: boolean;
1124
- canUseCredits: boolean;
1125
- canInviteUser: boolean;
1126
- role: "admin" | "member";
1127
- catalogixStores: string[];
1128
- }
1129
- interface TeamMember {
1130
- id: string;
1131
- kind: "member" | "invite";
1132
- /** Unified user id (for change-role and remove-users userIds). */
1133
- userId?: string;
1134
- /** Invitation id (for remove-users invitationIds). */
1135
- invitationId?: string;
1136
- /** Invitation token (for invite-cancel flow, if needed). */
1137
- inviteToken?: string;
1138
- name?: string;
1139
- userEmail: string;
1140
- invitedBy: string;
1141
- signedOn?: string;
1142
- permissions: UserPermissions;
1143
- }
1144
- declare const DEFAULT_PERMISSIONS: UserPermissions;
1145
-
1146
1206
  type ModalMode = "invite" | "update";
1147
1207
  interface StoreOption {
1148
1208
  _id: string;
@@ -1153,6 +1213,36 @@ interface InviteUpdateModalProps {
1153
1213
  mode: ModalMode;
1154
1214
  userEmail?: string;
1155
1215
  stores?: StoreOption[];
1216
+ /**
1217
+ * App rows to leave out.
1218
+ *
1219
+ * A denylist, deliberately, because this modal is shared: every other console
1220
+ * renders it too, and none of them should have to name the apps it already
1221
+ * shows in order to keep showing them. Omit this and nothing is hidden, which
1222
+ * is what every existing host gets without touching a line.
1223
+ *
1224
+ * A single-product console passes the ones it cannot administer. A toggle for
1225
+ * an app this host has no way to grant is worse than clutter — it invites
1226
+ * somebody to a product on a screen that cannot follow through.
1227
+ *
1228
+ * A hidden row is granted nothing — on an invite AND on an update. Hiding an
1229
+ * app in a host that cannot administer it is a statement that nobody it
1230
+ * manages should hold it, so a save takes it away rather than carrying it
1231
+ * along invisibly. This did once preserve an existing grant on update, on the
1232
+ * grounds that hiding a toggle should not revoke access an admin cannot see
1233
+ * to restore; that left a member who was granted an app before it was hidden
1234
+ * holding it forever, with every save putting its service ids back on the
1235
+ * wire, and no screen in the host able to show it or take it off.
1236
+ *
1237
+ * Hide every app and the "App permission" section goes with them, rather than
1238
+ * leaving a heading over an empty box.
1239
+ *
1240
+ * The trade against an allowlist, taken on purpose: an app added to this
1241
+ * modal later shows up in hosts that never asked for it, until they hide it.
1242
+ * That is the right way round for a shared component — a new app should have
1243
+ * to be hidden deliberately, not shown deliberately by every console at once.
1244
+ */
1245
+ hiddenApps?: readonly AppKey[];
1156
1246
  allowSubmitWithoutChanges?: boolean;
1157
1247
  initialPermissions?: UserPermissions;
1158
1248
  onClose: () => void;
@@ -1163,7 +1253,7 @@ interface InviteUpdateModalProps {
1163
1253
  /** Called only in invite mode; receives (permissions, email) */
1164
1254
  onInvite?: (permissions: UserPermissions, email: string) => void;
1165
1255
  }
1166
- declare function InviteUpdateModal({ open, mode, userEmail, stores, allowSubmitWithoutChanges, initialPermissions, onClose, onSave, onRemove, canRemove, onInvite, }: InviteUpdateModalProps): react.JSX.Element | null;
1256
+ declare function InviteUpdateModal({ open, mode, userEmail, stores, hiddenApps, allowSubmitWithoutChanges, initialPermissions, onClose, onSave, onRemove, canRemove, onInvite, }: InviteUpdateModalProps): react.JSX.Element | null;
1167
1257
 
1168
1258
  interface ExportDateModalProps {
1169
1259
  title: string;
@@ -1183,4 +1273,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1183
1273
  */
1184
1274
  declare function useSettingsAdapters(): SettingsAdapters;
1185
1275
 
1186
- export { type ApiToken, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrgMembershipTag, 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, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserPermissions, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, WorkspaceTab, countLabel, resolveSettingsTabFromPath, useSettingsAdapters };
1276
+ 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, OrgMembershipTag, 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, WorkspaceTab, countLabel, resolveSettingsTabFromPath, useSettingsAdapters, userLanguageLabel };
package/dist/index.d.ts CHANGED
@@ -104,6 +104,10 @@ interface SettingsAuthUser {
104
104
  "unspecified" = explicit skip; otherwise one of the host-defined ids
105
105
  (e.g. "design", "merchandising"). */
106
106
  userSpecialization?: string;
107
+ /** Preferred UI language as a code from `USER_LANGUAGES` (e.g. "en", "kn").
108
+ Absent or empty means the account has never chosen one, which reads as
109
+ `DEFAULT_USER_LANGUAGE` rather than as blank. */
110
+ language?: string;
107
111
  }
108
112
  /** Option shape returned by `auth.getSpecializations` — drives the
109
113
  Specialization dropdown in Settings → Account. The host adapter is the
@@ -121,6 +125,7 @@ interface SettingsAuthAdapter {
121
125
  name?: string;
122
126
  imageUrl?: string | null;
123
127
  userSpecialization?: string;
128
+ language?: string;
124
129
  }) => Promise<void>;
125
130
  clearAuth: () => void;
126
131
  logout: () => Promise<void>;
@@ -779,6 +784,49 @@ interface SettingsAdapters {
779
784
  imageUpload: SettingsImageUploadAdapter;
780
785
  }
781
786
 
787
+ /**
788
+ * The apps the invite / update dialog can offer a toggle for.
789
+ *
790
+ * Ordered as the dialog renders them. Exported because a host has to be able to
791
+ * name them in `hiddenApps` — see InviteUpdateModal.
792
+ */
793
+ declare const APP_KEYS: readonly ["artifax", "photogenix", "returns", "catalogix"];
794
+ type AppKey = (typeof APP_KEYS)[number];
795
+ interface UserPermissions {
796
+ artifax: boolean;
797
+ photogenix: boolean;
798
+ catalogix: boolean;
799
+ /**
800
+ * SPF Returns.
801
+ *
802
+ * Its services identify themselves by group: the provider carries five of
803
+ * them — the dashboard, Claims, Capture and two settings pages — all named
804
+ * "returns" and all in a "Returns" group. Granting the app means granting the
805
+ * group, which is what `permissionServiceIds` does.
806
+ */
807
+ returns: boolean;
808
+ canUseCredits: boolean;
809
+ canInviteUser: boolean;
810
+ role: "admin" | "member";
811
+ catalogixStores: string[];
812
+ }
813
+ interface TeamMember {
814
+ id: string;
815
+ kind: "member" | "invite";
816
+ /** Unified user id (for change-role and remove-users userIds). */
817
+ userId?: string;
818
+ /** Invitation id (for remove-users invitationIds). */
819
+ invitationId?: string;
820
+ /** Invitation token (for invite-cancel flow, if needed). */
821
+ inviteToken?: string;
822
+ name?: string;
823
+ userEmail: string;
824
+ invitedBy: string;
825
+ signedOn?: string;
826
+ permissions: UserPermissions;
827
+ }
828
+ declare const DEFAULT_PERMISSIONS: UserPermissions;
829
+
782
830
  type WorkspaceInfo = SettingsWorkspaceListItem & {
783
831
  initials?: string;
784
832
  plan?: string;
@@ -812,6 +860,14 @@ declare const WorkspaceTab: typeof WorkspaceListTab;
812
860
  declare function ReferralTab(): react.JSX.Element;
813
861
  interface SettingsContentProps {
814
862
  adapters: SettingsAdapters;
863
+ /**
864
+ * App rows the Members tab's invite / update dialog leaves out.
865
+ *
866
+ * Omit it and nothing is hidden, which is what every host got before this
867
+ * existed. A console that administers one product hides the others, so it
868
+ * stops inviting people to products it cannot administer.
869
+ */
870
+ hiddenApps?: readonly AppKey[];
815
871
  /** Currently active tab. The host owns routing and resolves this from the URL. */
816
872
  activeTab?: SettingsTab;
817
873
  /**
@@ -825,7 +881,7 @@ interface SettingsContentProps {
825
881
  */
826
882
  onClose?: () => void;
827
883
  }
828
- declare function SettingsContent({ adapters, activeTab, onClose, }: SettingsContentProps): react.JSX.Element;
884
+ declare function SettingsContent({ adapters, activeTab, onClose, hiddenApps, }: SettingsContentProps): react.JSX.Element;
829
885
 
830
886
  interface WorkspaceData {
831
887
  id: string;
@@ -880,7 +936,7 @@ declare function BillingContent({ embedded, showPlans: showPlansProp, onShowPlan
880
936
  onShowPlansChange?: (open: boolean) => void;
881
937
  }): react__default.JSX.Element;
882
938
 
883
- declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, workspaceName, workspaceImageUrl, organizationName, }?: {
939
+ declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, workspaceName, workspaceImageUrl, organizationName, hiddenApps, }?: {
884
940
  embedded?: boolean;
885
941
  onInviteOpen?: boolean;
886
942
  onInviteOpenChange?: (open: boolean) => void;
@@ -894,6 +950,11 @@ declare function TeamsContent({ embedded, onInviteOpen, onInviteOpenChange, work
894
950
  workspaceImageUrl?: string;
895
951
  /** Parent organization, when the workspace has joined one. */
896
952
  organizationName?: string | null;
953
+ /**
954
+ * App rows the invite / update dialog leaves out. Omitted, nothing is hidden
955
+ * — see InviteUpdateModal for what hiding one does and does not change.
956
+ */
957
+ hiddenApps?: readonly AppKey[];
897
958
  }): react.JSX.Element;
898
959
 
899
960
  /**
@@ -922,6 +983,40 @@ declare function TokensContent({ embedded, showRevokedOverride, onShowRevokedCha
922
983
  onCreateOpenChange?: (v: boolean) => void;
923
984
  }): react.JSX.Element;
924
985
 
986
+ /**
987
+ * The account-level language preference, shared by every Streamoid dashboard.
988
+ *
989
+ * Stored as the code and never as the label. `Intl`, the `lang` attribute and
990
+ * every translation API want "kn"; and a label reworded later ("Portuguese" →
991
+ * "Português (Brasil)") should be an edit here, not a migration across every
992
+ * user row. Hosts that want to show the language render the label from this
993
+ * list rather than keeping a map of their own — one list, so two dashboards
994
+ * cannot disagree about what "pt" is called.
995
+ *
996
+ * Mirrors `userLanguages` in the unified backend, which is the source of truth
997
+ * and rejects anything outside it.
998
+ */
999
+ interface UserLanguage {
1000
+ code: string;
1001
+ /** The English name — "Kannada". What the picker shows. */
1002
+ label: string;
1003
+ }
1004
+ declare const USER_LANGUAGES: readonly UserLanguage[];
1005
+ /**
1006
+ * English until somebody says otherwise.
1007
+ *
1008
+ * Unlike a specialization — where "" means never-answered, and the dashboard
1009
+ * has a reason to keep asking — an unanswered language already has a sensible
1010
+ * answer: the language these dashboards are written in. So a profile with no
1011
+ * language reads as English rather than as blank, and the dropdown is never
1012
+ * shown empty.
1013
+ */
1014
+ declare const DEFAULT_USER_LANGUAGE = "en";
1015
+ /** The label for a code, falling back to the code itself for one this build
1016
+ does not know — a newer dashboard may have written it, and showing "sw" is
1017
+ better than showing nothing. */
1018
+ declare function userLanguageLabel(code: string | undefined | null): string;
1019
+
925
1020
  interface ProfileAvatarProps {
926
1021
  name: string;
927
1022
  profileImage?: string;
@@ -1108,41 +1203,6 @@ interface BuyCreditsModalProps {
1108
1203
  }
1109
1204
  declare function BuyCreditsModal({ currencySymbol, country, onClose, onBuy, }: BuyCreditsModalProps): react.JSX.Element;
1110
1205
 
1111
- interface UserPermissions {
1112
- artifax: boolean;
1113
- photogenix: boolean;
1114
- catalogix: boolean;
1115
- /**
1116
- * SPF Returns.
1117
- *
1118
- * Its services identify themselves by group: the provider carries five of
1119
- * them — the dashboard, Claims, Capture and two settings pages — all named
1120
- * "returns" and all in a "Returns" group. Granting the app means granting the
1121
- * group, which is what `permissionServiceIds` does.
1122
- */
1123
- returns: boolean;
1124
- canUseCredits: boolean;
1125
- canInviteUser: boolean;
1126
- role: "admin" | "member";
1127
- catalogixStores: string[];
1128
- }
1129
- interface TeamMember {
1130
- id: string;
1131
- kind: "member" | "invite";
1132
- /** Unified user id (for change-role and remove-users userIds). */
1133
- userId?: string;
1134
- /** Invitation id (for remove-users invitationIds). */
1135
- invitationId?: string;
1136
- /** Invitation token (for invite-cancel flow, if needed). */
1137
- inviteToken?: string;
1138
- name?: string;
1139
- userEmail: string;
1140
- invitedBy: string;
1141
- signedOn?: string;
1142
- permissions: UserPermissions;
1143
- }
1144
- declare const DEFAULT_PERMISSIONS: UserPermissions;
1145
-
1146
1206
  type ModalMode = "invite" | "update";
1147
1207
  interface StoreOption {
1148
1208
  _id: string;
@@ -1153,6 +1213,36 @@ interface InviteUpdateModalProps {
1153
1213
  mode: ModalMode;
1154
1214
  userEmail?: string;
1155
1215
  stores?: StoreOption[];
1216
+ /**
1217
+ * App rows to leave out.
1218
+ *
1219
+ * A denylist, deliberately, because this modal is shared: every other console
1220
+ * renders it too, and none of them should have to name the apps it already
1221
+ * shows in order to keep showing them. Omit this and nothing is hidden, which
1222
+ * is what every existing host gets without touching a line.
1223
+ *
1224
+ * A single-product console passes the ones it cannot administer. A toggle for
1225
+ * an app this host has no way to grant is worse than clutter — it invites
1226
+ * somebody to a product on a screen that cannot follow through.
1227
+ *
1228
+ * A hidden row is granted nothing — on an invite AND on an update. Hiding an
1229
+ * app in a host that cannot administer it is a statement that nobody it
1230
+ * manages should hold it, so a save takes it away rather than carrying it
1231
+ * along invisibly. This did once preserve an existing grant on update, on the
1232
+ * grounds that hiding a toggle should not revoke access an admin cannot see
1233
+ * to restore; that left a member who was granted an app before it was hidden
1234
+ * holding it forever, with every save putting its service ids back on the
1235
+ * wire, and no screen in the host able to show it or take it off.
1236
+ *
1237
+ * Hide every app and the "App permission" section goes with them, rather than
1238
+ * leaving a heading over an empty box.
1239
+ *
1240
+ * The trade against an allowlist, taken on purpose: an app added to this
1241
+ * modal later shows up in hosts that never asked for it, until they hide it.
1242
+ * That is the right way round for a shared component — a new app should have
1243
+ * to be hidden deliberately, not shown deliberately by every console at once.
1244
+ */
1245
+ hiddenApps?: readonly AppKey[];
1156
1246
  allowSubmitWithoutChanges?: boolean;
1157
1247
  initialPermissions?: UserPermissions;
1158
1248
  onClose: () => void;
@@ -1163,7 +1253,7 @@ interface InviteUpdateModalProps {
1163
1253
  /** Called only in invite mode; receives (permissions, email) */
1164
1254
  onInvite?: (permissions: UserPermissions, email: string) => void;
1165
1255
  }
1166
- declare function InviteUpdateModal({ open, mode, userEmail, stores, allowSubmitWithoutChanges, initialPermissions, onClose, onSave, onRemove, canRemove, onInvite, }: InviteUpdateModalProps): react.JSX.Element | null;
1256
+ declare function InviteUpdateModal({ open, mode, userEmail, stores, hiddenApps, allowSubmitWithoutChanges, initialPermissions, onClose, onSave, onRemove, canRemove, onInvite, }: InviteUpdateModalProps): react.JSX.Element | null;
1167
1257
 
1168
1258
  interface ExportDateModalProps {
1169
1259
  title: string;
@@ -1183,4 +1273,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
1183
1273
  */
1184
1274
  declare function useSettingsAdapters(): SettingsAdapters;
1185
1275
 
1186
- export { type ApiToken, type AvailableCreditsResponse, BillingContent, type BillingEventPayload, type BillingProduct, type BillingSubscription, BuyCreditsModal, type BuyCreditsPayload, type BuyCreditsResponse, ConfirmDeleteModal, ConfirmLeaveModal, type CreatedToken, type CustomCreditInfo, type CustomCreditResponse, DEFAULT_PERMISSIONS, ExportDateModal, InviteUpdateModal, type InvoicePdfResponse, MemberListFrame, type MemberListFrameProps, type MemberListTab, MemberListToolbar, type MemberListToolbarProps, type MemberPermissionsPayload, OrgMembershipTag, 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, type UpdateSubscriptionPayload, type UpdateSubscriptionResponse, type UsageHistoryItem, type UsageHistoryResponse, type UserPermissions, type WorkspaceData, WorkspaceGeneralTab, type WorkspaceGeneralTabProps, type WorkspaceInvite, WorkspaceListTab, type WorkspaceMember, WorkspaceModal, WorkspaceTab, countLabel, resolveSettingsTabFromPath, useSettingsAdapters };
1276
+ 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, OrgMembershipTag, 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, WorkspaceTab, countLabel, resolveSettingsTabFromPath, useSettingsAdapters, userLanguageLabel };