@streamoid/settings 0.4.3 → 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 +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +163 -2
- package/dist/index.mjs +163 -2
- package/package.json +1 -1
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>;
|
|
@@ -978,6 +983,40 @@ declare function TokensContent({ embedded, showRevokedOverride, onShowRevokedCha
|
|
|
978
983
|
onCreateOpenChange?: (v: boolean) => void;
|
|
979
984
|
}): react.JSX.Element;
|
|
980
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
|
+
|
|
981
1020
|
interface ProfileAvatarProps {
|
|
982
1021
|
name: string;
|
|
983
1022
|
profileImage?: string;
|
|
@@ -1234,4 +1273,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
|
|
|
1234
1273
|
*/
|
|
1235
1274
|
declare function useSettingsAdapters(): SettingsAdapters;
|
|
1236
1275
|
|
|
1237
|
-
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, 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>;
|
|
@@ -978,6 +983,40 @@ declare function TokensContent({ embedded, showRevokedOverride, onShowRevokedCha
|
|
|
978
983
|
onCreateOpenChange?: (v: boolean) => void;
|
|
979
984
|
}): react.JSX.Element;
|
|
980
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
|
+
|
|
981
1020
|
interface ProfileAvatarProps {
|
|
982
1021
|
name: string;
|
|
983
1022
|
profileImage?: string;
|
|
@@ -1234,4 +1273,4 @@ declare function SettingsAdaptersProvider({ adapters, children, }: {
|
|
|
1234
1273
|
*/
|
|
1235
1274
|
declare function useSettingsAdapters(): SettingsAdapters;
|
|
1236
1275
|
|
|
1237
|
-
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, 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.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
ConfirmDeleteModal: () => ConfirmDeleteModal,
|
|
27
27
|
ConfirmLeaveModal: () => ConfirmLeaveModal,
|
|
28
28
|
DEFAULT_PERMISSIONS: () => DEFAULT_PERMISSIONS,
|
|
29
|
+
DEFAULT_USER_LANGUAGE: () => DEFAULT_USER_LANGUAGE,
|
|
29
30
|
ExportDateModal: () => ExportDateModal,
|
|
30
31
|
InviteUpdateModal: () => InviteUpdateModal,
|
|
31
32
|
MemberListFrame: () => MemberListFrame,
|
|
@@ -50,13 +51,15 @@ __export(index_exports, {
|
|
|
50
51
|
TeamsContent: () => TeamsContent,
|
|
51
52
|
TokensContent: () => TokensContent,
|
|
52
53
|
URL_TO_TAB: () => URL_TO_TAB,
|
|
54
|
+
USER_LANGUAGES: () => USER_LANGUAGES,
|
|
53
55
|
WorkspaceGeneralTab: () => WorkspaceGeneralTab,
|
|
54
56
|
WorkspaceListTab: () => WorkspaceListTab,
|
|
55
57
|
WorkspaceModal: () => WorkspaceModal,
|
|
56
58
|
WorkspaceTab: () => WorkspaceTab,
|
|
57
59
|
countLabel: () => countLabel,
|
|
58
60
|
resolveSettingsTabFromPath: () => resolveSettingsTabFromPath,
|
|
59
|
-
useSettingsAdapters: () => useSettingsAdapters
|
|
61
|
+
useSettingsAdapters: () => useSettingsAdapters,
|
|
62
|
+
userLanguageLabel: () => userLanguageLabel
|
|
60
63
|
});
|
|
61
64
|
module.exports = __toCommonJS(index_exports);
|
|
62
65
|
|
|
@@ -91,6 +94,27 @@ var SiconKey = ({ color = "currentColor", strokeWidth = 1.25, size = 24, ...prop
|
|
|
91
94
|
};
|
|
92
95
|
var SiconKey_default = SiconKey;
|
|
93
96
|
|
|
97
|
+
// src/languages.ts
|
|
98
|
+
var USER_LANGUAGES = [
|
|
99
|
+
{ code: "en", label: "English" },
|
|
100
|
+
{ code: "es", label: "Spanish" },
|
|
101
|
+
{ code: "fr", label: "French" },
|
|
102
|
+
{ code: "pt", label: "Portuguese" },
|
|
103
|
+
{ code: "hi", label: "Hindi" },
|
|
104
|
+
{ code: "kn", label: "Kannada" },
|
|
105
|
+
{ code: "te", label: "Telugu" },
|
|
106
|
+
{ code: "ta", label: "Tamil" },
|
|
107
|
+
{ code: "mr", label: "Marathi" },
|
|
108
|
+
{ code: "gu", label: "Gujarati" },
|
|
109
|
+
{ code: "bn", label: "Bengali" },
|
|
110
|
+
{ code: "ar", label: "Arabic" }
|
|
111
|
+
];
|
|
112
|
+
var DEFAULT_USER_LANGUAGE = "en";
|
|
113
|
+
function userLanguageLabel(code) {
|
|
114
|
+
const resolved = (code || "").trim() || DEFAULT_USER_LANGUAGE;
|
|
115
|
+
return USER_LANGUAGES.find((lang) => lang.code === resolved)?.label ?? resolved;
|
|
116
|
+
}
|
|
117
|
+
|
|
94
118
|
// src/workspace-modal.tsx
|
|
95
119
|
var import_react3 = require("react");
|
|
96
120
|
|
|
@@ -10619,13 +10643,134 @@ function SpecializationDropdown({
|
|
|
10619
10643
|
}
|
|
10620
10644
|
);
|
|
10621
10645
|
}
|
|
10646
|
+
function LanguageDropdown({
|
|
10647
|
+
value,
|
|
10648
|
+
onChange,
|
|
10649
|
+
disabled
|
|
10650
|
+
}) {
|
|
10651
|
+
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
10652
|
+
const containerRef = (0, import_react16.useRef)(null);
|
|
10653
|
+
(0, import_react16.useEffect)(() => {
|
|
10654
|
+
if (!open) return;
|
|
10655
|
+
function handleMouseDown(e) {
|
|
10656
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
10657
|
+
setOpen(false);
|
|
10658
|
+
}
|
|
10659
|
+
}
|
|
10660
|
+
function handleKeyDown(e) {
|
|
10661
|
+
if (e.key === "Escape") setOpen(false);
|
|
10662
|
+
}
|
|
10663
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
10664
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
10665
|
+
return () => {
|
|
10666
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
10667
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
10668
|
+
};
|
|
10669
|
+
}, [open]);
|
|
10670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
10671
|
+
"div",
|
|
10672
|
+
{
|
|
10673
|
+
ref: containerRef,
|
|
10674
|
+
className: "w-full",
|
|
10675
|
+
style: { position: "relative" },
|
|
10676
|
+
children: [
|
|
10677
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("style", { children: DROPDOWN_TRIGGER_STYLES }),
|
|
10678
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10679
|
+
"div",
|
|
10680
|
+
{
|
|
10681
|
+
className: "spec-dropdown-trigger",
|
|
10682
|
+
"data-disabled": disabled ? "true" : "false",
|
|
10683
|
+
onClick: () => !disabled && setOpen((v) => !v),
|
|
10684
|
+
"aria-haspopup": "listbox",
|
|
10685
|
+
"aria-expanded": open,
|
|
10686
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10687
|
+
import_ui12.ScTextField,
|
|
10688
|
+
{
|
|
10689
|
+
label: "Language",
|
|
10690
|
+
labelGroup: "label",
|
|
10691
|
+
value: userLanguageLabel(value),
|
|
10692
|
+
placeholderFilled: "Select language",
|
|
10693
|
+
tfGroup: "icon-right",
|
|
10694
|
+
tfRightIcon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10695
|
+
"span",
|
|
10696
|
+
{
|
|
10697
|
+
style: {
|
|
10698
|
+
display: "flex",
|
|
10699
|
+
alignItems: "center",
|
|
10700
|
+
justifyContent: "center",
|
|
10701
|
+
transform: open ? "rotate(180deg)" : "none",
|
|
10702
|
+
transition: "transform 120ms ease-out"
|
|
10703
|
+
},
|
|
10704
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_icons12.SiconDown, {})
|
|
10705
|
+
}
|
|
10706
|
+
),
|
|
10707
|
+
className: "sc-text-field-full-width",
|
|
10708
|
+
style: { width: "100%" },
|
|
10709
|
+
readOnly: true,
|
|
10710
|
+
disabled
|
|
10711
|
+
}
|
|
10712
|
+
)
|
|
10713
|
+
}
|
|
10714
|
+
),
|
|
10715
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10716
|
+
"div",
|
|
10717
|
+
{
|
|
10718
|
+
role: "listbox",
|
|
10719
|
+
style: {
|
|
10720
|
+
position: "absolute",
|
|
10721
|
+
top: "calc(100% + 4px)",
|
|
10722
|
+
left: 0,
|
|
10723
|
+
right: 0,
|
|
10724
|
+
zIndex: 50,
|
|
10725
|
+
// The list is longer than the specialization one, so it scrolls
|
|
10726
|
+
// rather than running off the bottom of the panel.
|
|
10727
|
+
maxHeight: 280,
|
|
10728
|
+
overflowY: "auto",
|
|
10729
|
+
background: "var(--alias-surface-subtle, #1a1a1a)",
|
|
10730
|
+
border: "0.5px solid var(--alias-border-subtle, #242424)",
|
|
10731
|
+
borderRadius: "var(--radius-4xl, 18px)",
|
|
10732
|
+
padding: "var(--spacing-md, 8px)",
|
|
10733
|
+
display: "flex",
|
|
10734
|
+
flexDirection: "column",
|
|
10735
|
+
gap: 8,
|
|
10736
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)",
|
|
10737
|
+
backdropFilter: "blur(42px)"
|
|
10738
|
+
},
|
|
10739
|
+
children: USER_LANGUAGES.map((lang) => {
|
|
10740
|
+
const isActive = lang.code === value;
|
|
10741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10742
|
+
import_ui11.ScMenuOptions,
|
|
10743
|
+
{
|
|
10744
|
+
text: lang.label,
|
|
10745
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, {}),
|
|
10746
|
+
hover: isActive ? "true" : "false",
|
|
10747
|
+
variant: "default",
|
|
10748
|
+
role: "option",
|
|
10749
|
+
"aria-selected": isActive,
|
|
10750
|
+
onClick: () => {
|
|
10751
|
+
onChange(lang.code);
|
|
10752
|
+
setOpen(false);
|
|
10753
|
+
},
|
|
10754
|
+
style: { width: "100%", cursor: "pointer" }
|
|
10755
|
+
},
|
|
10756
|
+
lang.code
|
|
10757
|
+
);
|
|
10758
|
+
})
|
|
10759
|
+
}
|
|
10760
|
+
)
|
|
10761
|
+
]
|
|
10762
|
+
}
|
|
10763
|
+
);
|
|
10764
|
+
}
|
|
10622
10765
|
function ProfileTab() {
|
|
10623
10766
|
const { auth, imageUpload, toast } = useSettingsAdapters();
|
|
10624
10767
|
const user = auth.user;
|
|
10625
10768
|
const derivedName = user?.name ?? "";
|
|
10626
10769
|
const derivedSpec = user?.userSpecialization ?? "";
|
|
10770
|
+
const derivedLanguage = user?.language?.trim() || DEFAULT_USER_LANGUAGE;
|
|
10627
10771
|
const [fullName, setFullName] = (0, import_react16.useState)(derivedName);
|
|
10628
10772
|
const [selectedSpec, setSelectedSpec] = (0, import_react16.useState)(derivedSpec);
|
|
10773
|
+
const [selectedLanguage, setSelectedLanguage] = (0, import_react16.useState)(derivedLanguage);
|
|
10629
10774
|
const [saving, setSaving] = (0, import_react16.useState)(false);
|
|
10630
10775
|
const [imageSaving, setImageSaving] = (0, import_react16.useState)(false);
|
|
10631
10776
|
const [imagePreview, setImagePreview] = (0, import_react16.useState)(
|
|
@@ -10636,7 +10781,7 @@ function ProfileTab() {
|
|
|
10636
10781
|
const profileImage = imagePreview ?? getUserProfileImage(user);
|
|
10637
10782
|
const profileInitial = profileDisplayName.charAt(0).toUpperCase();
|
|
10638
10783
|
const disableAllActions = saving || imageSaving;
|
|
10639
|
-
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
|
|
10784
|
+
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec || selectedLanguage !== derivedLanguage;
|
|
10640
10785
|
(0, import_react16.useEffect)(() => {
|
|
10641
10786
|
setFullName(derivedName);
|
|
10642
10787
|
setImagePreview(void 0);
|
|
@@ -10644,6 +10789,9 @@ function ProfileTab() {
|
|
|
10644
10789
|
(0, import_react16.useEffect)(() => {
|
|
10645
10790
|
setSelectedSpec(derivedSpec);
|
|
10646
10791
|
}, [derivedSpec]);
|
|
10792
|
+
(0, import_react16.useEffect)(() => {
|
|
10793
|
+
setSelectedLanguage(derivedLanguage);
|
|
10794
|
+
}, [derivedLanguage]);
|
|
10647
10795
|
const handleSave = async () => {
|
|
10648
10796
|
if (disableAllActions || !dirty) return;
|
|
10649
10797
|
setSaving(true);
|
|
@@ -10651,6 +10799,8 @@ function ProfileTab() {
|
|
|
10651
10799
|
const patch = {};
|
|
10652
10800
|
if (fullName.trim() !== derivedName) patch.name = fullName.trim();
|
|
10653
10801
|
if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
|
|
10802
|
+
if (selectedLanguage !== derivedLanguage)
|
|
10803
|
+
patch.language = selectedLanguage;
|
|
10654
10804
|
await auth.updateProfile(patch);
|
|
10655
10805
|
await auth.refreshProfile();
|
|
10656
10806
|
toast.success("Profile updated");
|
|
@@ -10870,6 +11020,17 @@ function ProfileTab() {
|
|
|
10870
11020
|
}
|
|
10871
11021
|
) })
|
|
10872
11022
|
] }),
|
|
11023
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-start w-full", style: { gap: "var(--spacing-3xl)" }, children: [
|
|
11024
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
11025
|
+
LanguageDropdown,
|
|
11026
|
+
{
|
|
11027
|
+
value: selectedLanguage,
|
|
11028
|
+
onChange: setSelectedLanguage,
|
|
11029
|
+
disabled: disableAllActions
|
|
11030
|
+
}
|
|
11031
|
+
) }),
|
|
11032
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 min-w-0" })
|
|
11033
|
+
] }),
|
|
10873
11034
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
10874
11035
|
import_ui12.ScTextField,
|
|
10875
11036
|
{
|
package/dist/index.mjs
CHANGED
|
@@ -58,6 +58,27 @@ var SiconKey = ({ color = "currentColor", strokeWidth = 1.25, size = 24, ...prop
|
|
|
58
58
|
};
|
|
59
59
|
var SiconKey_default = SiconKey;
|
|
60
60
|
|
|
61
|
+
// src/languages.ts
|
|
62
|
+
var USER_LANGUAGES = [
|
|
63
|
+
{ code: "en", label: "English" },
|
|
64
|
+
{ code: "es", label: "Spanish" },
|
|
65
|
+
{ code: "fr", label: "French" },
|
|
66
|
+
{ code: "pt", label: "Portuguese" },
|
|
67
|
+
{ code: "hi", label: "Hindi" },
|
|
68
|
+
{ code: "kn", label: "Kannada" },
|
|
69
|
+
{ code: "te", label: "Telugu" },
|
|
70
|
+
{ code: "ta", label: "Tamil" },
|
|
71
|
+
{ code: "mr", label: "Marathi" },
|
|
72
|
+
{ code: "gu", label: "Gujarati" },
|
|
73
|
+
{ code: "bn", label: "Bengali" },
|
|
74
|
+
{ code: "ar", label: "Arabic" }
|
|
75
|
+
];
|
|
76
|
+
var DEFAULT_USER_LANGUAGE = "en";
|
|
77
|
+
function userLanguageLabel(code) {
|
|
78
|
+
const resolved = (code || "").trim() || DEFAULT_USER_LANGUAGE;
|
|
79
|
+
return USER_LANGUAGES.find((lang) => lang.code === resolved)?.label ?? resolved;
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
// src/workspace-modal.tsx
|
|
62
83
|
import { useState, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
63
84
|
|
|
@@ -10630,13 +10651,134 @@ function SpecializationDropdown({
|
|
|
10630
10651
|
}
|
|
10631
10652
|
);
|
|
10632
10653
|
}
|
|
10654
|
+
function LanguageDropdown({
|
|
10655
|
+
value,
|
|
10656
|
+
onChange,
|
|
10657
|
+
disabled
|
|
10658
|
+
}) {
|
|
10659
|
+
const [open, setOpen] = useState14(false);
|
|
10660
|
+
const containerRef = useRef7(null);
|
|
10661
|
+
useEffect12(() => {
|
|
10662
|
+
if (!open) return;
|
|
10663
|
+
function handleMouseDown(e) {
|
|
10664
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
10665
|
+
setOpen(false);
|
|
10666
|
+
}
|
|
10667
|
+
}
|
|
10668
|
+
function handleKeyDown(e) {
|
|
10669
|
+
if (e.key === "Escape") setOpen(false);
|
|
10670
|
+
}
|
|
10671
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
10672
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
10673
|
+
return () => {
|
|
10674
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
10675
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
10676
|
+
};
|
|
10677
|
+
}, [open]);
|
|
10678
|
+
return /* @__PURE__ */ jsxs18(
|
|
10679
|
+
"div",
|
|
10680
|
+
{
|
|
10681
|
+
ref: containerRef,
|
|
10682
|
+
className: "w-full",
|
|
10683
|
+
style: { position: "relative" },
|
|
10684
|
+
children: [
|
|
10685
|
+
/* @__PURE__ */ jsx20("style", { children: DROPDOWN_TRIGGER_STYLES }),
|
|
10686
|
+
/* @__PURE__ */ jsx20(
|
|
10687
|
+
"div",
|
|
10688
|
+
{
|
|
10689
|
+
className: "spec-dropdown-trigger",
|
|
10690
|
+
"data-disabled": disabled ? "true" : "false",
|
|
10691
|
+
onClick: () => !disabled && setOpen((v) => !v),
|
|
10692
|
+
"aria-haspopup": "listbox",
|
|
10693
|
+
"aria-expanded": open,
|
|
10694
|
+
children: /* @__PURE__ */ jsx20(
|
|
10695
|
+
ScTextField,
|
|
10696
|
+
{
|
|
10697
|
+
label: "Language",
|
|
10698
|
+
labelGroup: "label",
|
|
10699
|
+
value: userLanguageLabel(value),
|
|
10700
|
+
placeholderFilled: "Select language",
|
|
10701
|
+
tfGroup: "icon-right",
|
|
10702
|
+
tfRightIcon: /* @__PURE__ */ jsx20(
|
|
10703
|
+
"span",
|
|
10704
|
+
{
|
|
10705
|
+
style: {
|
|
10706
|
+
display: "flex",
|
|
10707
|
+
alignItems: "center",
|
|
10708
|
+
justifyContent: "center",
|
|
10709
|
+
transform: open ? "rotate(180deg)" : "none",
|
|
10710
|
+
transition: "transform 120ms ease-out"
|
|
10711
|
+
},
|
|
10712
|
+
children: /* @__PURE__ */ jsx20(SiconDown, {})
|
|
10713
|
+
}
|
|
10714
|
+
),
|
|
10715
|
+
className: "sc-text-field-full-width",
|
|
10716
|
+
style: { width: "100%" },
|
|
10717
|
+
readOnly: true,
|
|
10718
|
+
disabled
|
|
10719
|
+
}
|
|
10720
|
+
)
|
|
10721
|
+
}
|
|
10722
|
+
),
|
|
10723
|
+
open && /* @__PURE__ */ jsx20(
|
|
10724
|
+
"div",
|
|
10725
|
+
{
|
|
10726
|
+
role: "listbox",
|
|
10727
|
+
style: {
|
|
10728
|
+
position: "absolute",
|
|
10729
|
+
top: "calc(100% + 4px)",
|
|
10730
|
+
left: 0,
|
|
10731
|
+
right: 0,
|
|
10732
|
+
zIndex: 50,
|
|
10733
|
+
// The list is longer than the specialization one, so it scrolls
|
|
10734
|
+
// rather than running off the bottom of the panel.
|
|
10735
|
+
maxHeight: 280,
|
|
10736
|
+
overflowY: "auto",
|
|
10737
|
+
background: "var(--alias-surface-subtle, #1a1a1a)",
|
|
10738
|
+
border: "0.5px solid var(--alias-border-subtle, #242424)",
|
|
10739
|
+
borderRadius: "var(--radius-4xl, 18px)",
|
|
10740
|
+
padding: "var(--spacing-md, 8px)",
|
|
10741
|
+
display: "flex",
|
|
10742
|
+
flexDirection: "column",
|
|
10743
|
+
gap: 8,
|
|
10744
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)",
|
|
10745
|
+
backdropFilter: "blur(42px)"
|
|
10746
|
+
},
|
|
10747
|
+
children: USER_LANGUAGES.map((lang) => {
|
|
10748
|
+
const isActive = lang.code === value;
|
|
10749
|
+
return /* @__PURE__ */ jsx20(
|
|
10750
|
+
ScMenuOptions,
|
|
10751
|
+
{
|
|
10752
|
+
text: lang.label,
|
|
10753
|
+
icon: /* @__PURE__ */ jsx20(Fragment12, {}),
|
|
10754
|
+
hover: isActive ? "true" : "false",
|
|
10755
|
+
variant: "default",
|
|
10756
|
+
role: "option",
|
|
10757
|
+
"aria-selected": isActive,
|
|
10758
|
+
onClick: () => {
|
|
10759
|
+
onChange(lang.code);
|
|
10760
|
+
setOpen(false);
|
|
10761
|
+
},
|
|
10762
|
+
style: { width: "100%", cursor: "pointer" }
|
|
10763
|
+
},
|
|
10764
|
+
lang.code
|
|
10765
|
+
);
|
|
10766
|
+
})
|
|
10767
|
+
}
|
|
10768
|
+
)
|
|
10769
|
+
]
|
|
10770
|
+
}
|
|
10771
|
+
);
|
|
10772
|
+
}
|
|
10633
10773
|
function ProfileTab() {
|
|
10634
10774
|
const { auth, imageUpload, toast } = useSettingsAdapters();
|
|
10635
10775
|
const user = auth.user;
|
|
10636
10776
|
const derivedName = user?.name ?? "";
|
|
10637
10777
|
const derivedSpec = user?.userSpecialization ?? "";
|
|
10778
|
+
const derivedLanguage = user?.language?.trim() || DEFAULT_USER_LANGUAGE;
|
|
10638
10779
|
const [fullName, setFullName] = useState14(derivedName);
|
|
10639
10780
|
const [selectedSpec, setSelectedSpec] = useState14(derivedSpec);
|
|
10781
|
+
const [selectedLanguage, setSelectedLanguage] = useState14(derivedLanguage);
|
|
10640
10782
|
const [saving, setSaving] = useState14(false);
|
|
10641
10783
|
const [imageSaving, setImageSaving] = useState14(false);
|
|
10642
10784
|
const [imagePreview, setImagePreview] = useState14(
|
|
@@ -10647,7 +10789,7 @@ function ProfileTab() {
|
|
|
10647
10789
|
const profileImage = imagePreview ?? getUserProfileImage(user);
|
|
10648
10790
|
const profileInitial = profileDisplayName.charAt(0).toUpperCase();
|
|
10649
10791
|
const disableAllActions = saving || imageSaving;
|
|
10650
|
-
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
|
|
10792
|
+
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec || selectedLanguage !== derivedLanguage;
|
|
10651
10793
|
useEffect12(() => {
|
|
10652
10794
|
setFullName(derivedName);
|
|
10653
10795
|
setImagePreview(void 0);
|
|
@@ -10655,6 +10797,9 @@ function ProfileTab() {
|
|
|
10655
10797
|
useEffect12(() => {
|
|
10656
10798
|
setSelectedSpec(derivedSpec);
|
|
10657
10799
|
}, [derivedSpec]);
|
|
10800
|
+
useEffect12(() => {
|
|
10801
|
+
setSelectedLanguage(derivedLanguage);
|
|
10802
|
+
}, [derivedLanguage]);
|
|
10658
10803
|
const handleSave = async () => {
|
|
10659
10804
|
if (disableAllActions || !dirty) return;
|
|
10660
10805
|
setSaving(true);
|
|
@@ -10662,6 +10807,8 @@ function ProfileTab() {
|
|
|
10662
10807
|
const patch = {};
|
|
10663
10808
|
if (fullName.trim() !== derivedName) patch.name = fullName.trim();
|
|
10664
10809
|
if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
|
|
10810
|
+
if (selectedLanguage !== derivedLanguage)
|
|
10811
|
+
patch.language = selectedLanguage;
|
|
10665
10812
|
await auth.updateProfile(patch);
|
|
10666
10813
|
await auth.refreshProfile();
|
|
10667
10814
|
toast.success("Profile updated");
|
|
@@ -10881,6 +11028,17 @@ function ProfileTab() {
|
|
|
10881
11028
|
}
|
|
10882
11029
|
) })
|
|
10883
11030
|
] }),
|
|
11031
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-start w-full", style: { gap: "var(--spacing-3xl)" }, children: [
|
|
11032
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx20(
|
|
11033
|
+
LanguageDropdown,
|
|
11034
|
+
{
|
|
11035
|
+
value: selectedLanguage,
|
|
11036
|
+
onChange: setSelectedLanguage,
|
|
11037
|
+
disabled: disableAllActions
|
|
11038
|
+
}
|
|
11039
|
+
) }),
|
|
11040
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0" })
|
|
11041
|
+
] }),
|
|
10884
11042
|
/* @__PURE__ */ jsx20("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx20(
|
|
10885
11043
|
ScTextField,
|
|
10886
11044
|
{
|
|
@@ -11983,6 +12141,7 @@ export {
|
|
|
11983
12141
|
ConfirmDeleteModal,
|
|
11984
12142
|
ConfirmLeaveModal,
|
|
11985
12143
|
DEFAULT_PERMISSIONS,
|
|
12144
|
+
DEFAULT_USER_LANGUAGE,
|
|
11986
12145
|
ExportDateModal,
|
|
11987
12146
|
InviteUpdateModal,
|
|
11988
12147
|
MemberListFrame,
|
|
@@ -12007,11 +12166,13 @@ export {
|
|
|
12007
12166
|
TeamsContent,
|
|
12008
12167
|
TokensContent,
|
|
12009
12168
|
URL_TO_TAB,
|
|
12169
|
+
USER_LANGUAGES,
|
|
12010
12170
|
WorkspaceGeneralTab,
|
|
12011
12171
|
WorkspaceListTab,
|
|
12012
12172
|
WorkspaceModal,
|
|
12013
12173
|
WorkspaceTab,
|
|
12014
12174
|
countLabel,
|
|
12015
12175
|
resolveSettingsTabFromPath,
|
|
12016
|
-
useSettingsAdapters
|
|
12176
|
+
useSettingsAdapters,
|
|
12177
|
+
userLanguageLabel
|
|
12017
12178
|
};
|