@streamoid/settings 0.4.3 → 0.4.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/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
 
@@ -2151,7 +2175,7 @@ function OrganizationAffiliationCard({
2151
2175
  "Failed to change visibility"
2152
2176
  );
2153
2177
  },
2154
- children: opt === "private" ? "Only its members" : "Everyone in the organization"
2178
+ children: opt === "private" ? "Only workspace members" : "Everyone in the organization"
2155
2179
  },
2156
2180
  opt
2157
2181
  );
@@ -10311,25 +10335,25 @@ function SettingsNavGroupHeader({
10311
10335
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
10312
10336
  "div",
10313
10337
  {
10314
- className: "flex items-center w-full min-w-0",
10315
- style: { gap: 6, padding: "2px var(--spacing-md) 4px" },
10338
+ className: "flex flex-col w-full min-w-0",
10339
+ style: { gap: 2, padding: "2px var(--spacing-xl) var(--spacing-sm)" },
10316
10340
  children: [
10317
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 flex items-center", children: icon }),
10318
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col min-w-0", children: [
10319
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
10320
- "span",
10321
- {
10322
- style: {
10323
- fontFamily: "var(--font-family-font-family-body)",
10324
- fontSize: "var(--font-size-font-size-xxs, 10px)",
10325
- fontWeight: 500,
10326
- letterSpacing: "0.08em",
10327
- textTransform: "uppercase",
10328
- color: MUTED_COLOR2
10329
- },
10330
- children: eyebrow
10331
- }
10332
- ),
10341
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
10342
+ "span",
10343
+ {
10344
+ style: {
10345
+ fontFamily: "var(--font-family-font-family-body)",
10346
+ fontSize: "var(--font-size-font-size-xxs, 10px)",
10347
+ fontWeight: 500,
10348
+ letterSpacing: "0.08em",
10349
+ textTransform: "uppercase",
10350
+ color: MUTED_COLOR2
10351
+ },
10352
+ children: eyebrow
10353
+ }
10354
+ ),
10355
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center min-w-0", style: { gap: "var(--spacing-md)" }, children: [
10356
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 flex items-center", children: icon }),
10333
10357
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
10334
10358
  "span",
10335
10359
  {
@@ -10371,26 +10395,26 @@ function SettingsNav({
10371
10395
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
10372
10396
  "div",
10373
10397
  {
10374
- className: "flex flex-col items-start shrink-0 relative",
10398
+ className: "flex flex-col items-start shrink-0 relative overflow-y-auto",
10375
10399
  style: {
10376
10400
  backgroundColor: "var(--alias-surface-base)",
10377
10401
  borderRadius: "var(--radius-3xl)",
10378
10402
  padding: "var(--spacing-md)",
10379
10403
  width: 216,
10380
- gap: "var(--spacing-xl)"
10404
+ maxHeight: "100%",
10405
+ /* A REAL BORDER, not the absolutely-positioned overlay that used to
10406
+ * sit inside this box. Now that the nav scrolls, an `absolute inset-0`
10407
+ * child is positioned against the scrolled CONTENT, so the outline
10408
+ * would slide up out of view and leave the card unbounded. `border`
10409
+ * belongs to the box itself and cannot drift; `box-sizing: border-box`
10410
+ * keeps the 216px width. */
10411
+ border: "1px solid var(--alias-border-subtle)",
10412
+ /* Was `--spacing-xl` (12). The groups and the rules between them sat
10413
+ * closer to each other than the rows inside a group did to their own
10414
+ * heading, so the divisions read as weaker than what they divided. */
10415
+ gap: "var(--spacing-5xl)"
10381
10416
  },
10382
10417
  children: [
10383
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
10384
- "div",
10385
- {
10386
- "aria-hidden": "true",
10387
- className: "absolute inset-0 pointer-events-none",
10388
- style: {
10389
- border: "1px solid var(--alias-border-subtle)",
10390
- borderRadius: "var(--radius-3xl)"
10391
- }
10392
- }
10393
- ),
10394
10418
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: item("profile", (color) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_icons12.SiconUser, { className: "w-6 h-6", color })) }),
10395
10419
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ui11.ScHDivider, {}),
10396
10420
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: [
@@ -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
 
@@ -2118,7 +2139,7 @@ function OrganizationAffiliationCard({
2118
2139
  "Failed to change visibility"
2119
2140
  );
2120
2141
  },
2121
- children: opt === "private" ? "Only its members" : "Everyone in the organization"
2142
+ children: opt === "private" ? "Only workspace members" : "Everyone in the organization"
2122
2143
  },
2123
2144
  opt
2124
2145
  );
@@ -10322,25 +10343,25 @@ function SettingsNavGroupHeader({
10322
10343
  return /* @__PURE__ */ jsxs18(
10323
10344
  "div",
10324
10345
  {
10325
- className: "flex items-center w-full min-w-0",
10326
- style: { gap: 6, padding: "2px var(--spacing-md) 4px" },
10346
+ className: "flex flex-col w-full min-w-0",
10347
+ style: { gap: 2, padding: "2px var(--spacing-xl) var(--spacing-sm)" },
10327
10348
  children: [
10328
- /* @__PURE__ */ jsx20("span", { className: "shrink-0 flex items-center", children: icon }),
10329
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col min-w-0", children: [
10330
- /* @__PURE__ */ jsx20(
10331
- "span",
10332
- {
10333
- style: {
10334
- fontFamily: "var(--font-family-font-family-body)",
10335
- fontSize: "var(--font-size-font-size-xxs, 10px)",
10336
- fontWeight: 500,
10337
- letterSpacing: "0.08em",
10338
- textTransform: "uppercase",
10339
- color: MUTED_COLOR2
10340
- },
10341
- children: eyebrow
10342
- }
10343
- ),
10349
+ /* @__PURE__ */ jsx20(
10350
+ "span",
10351
+ {
10352
+ style: {
10353
+ fontFamily: "var(--font-family-font-family-body)",
10354
+ fontSize: "var(--font-size-font-size-xxs, 10px)",
10355
+ fontWeight: 500,
10356
+ letterSpacing: "0.08em",
10357
+ textTransform: "uppercase",
10358
+ color: MUTED_COLOR2
10359
+ },
10360
+ children: eyebrow
10361
+ }
10362
+ ),
10363
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center min-w-0", style: { gap: "var(--spacing-md)" }, children: [
10364
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 flex items-center", children: icon }),
10344
10365
  /* @__PURE__ */ jsx20(
10345
10366
  "span",
10346
10367
  {
@@ -10382,26 +10403,26 @@ function SettingsNav({
10382
10403
  return /* @__PURE__ */ jsxs18(
10383
10404
  "div",
10384
10405
  {
10385
- className: "flex flex-col items-start shrink-0 relative",
10406
+ className: "flex flex-col items-start shrink-0 relative overflow-y-auto",
10386
10407
  style: {
10387
10408
  backgroundColor: "var(--alias-surface-base)",
10388
10409
  borderRadius: "var(--radius-3xl)",
10389
10410
  padding: "var(--spacing-md)",
10390
10411
  width: 216,
10391
- gap: "var(--spacing-xl)"
10412
+ maxHeight: "100%",
10413
+ /* A REAL BORDER, not the absolutely-positioned overlay that used to
10414
+ * sit inside this box. Now that the nav scrolls, an `absolute inset-0`
10415
+ * child is positioned against the scrolled CONTENT, so the outline
10416
+ * would slide up out of view and leave the card unbounded. `border`
10417
+ * belongs to the box itself and cannot drift; `box-sizing: border-box`
10418
+ * keeps the 216px width. */
10419
+ border: "1px solid var(--alias-border-subtle)",
10420
+ /* Was `--spacing-xl` (12). The groups and the rules between them sat
10421
+ * closer to each other than the rows inside a group did to their own
10422
+ * heading, so the divisions read as weaker than what they divided. */
10423
+ gap: "var(--spacing-5xl)"
10392
10424
  },
10393
10425
  children: [
10394
- /* @__PURE__ */ jsx20(
10395
- "div",
10396
- {
10397
- "aria-hidden": "true",
10398
- className: "absolute inset-0 pointer-events-none",
10399
- style: {
10400
- border: "1px solid var(--alias-border-subtle)",
10401
- borderRadius: "var(--radius-3xl)"
10402
- }
10403
- }
10404
- ),
10405
10426
  /* @__PURE__ */ jsx20("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: item("profile", (color) => /* @__PURE__ */ jsx20(SiconUser, { className: "w-6 h-6", color })) }),
10406
10427
  /* @__PURE__ */ jsx20(ScHDivider, {}),
10407
10428
  /* @__PURE__ */ jsxs18("div", { className: "flex flex-col w-full", style: { gap: "var(--spacing-md)" }, children: [
@@ -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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamoid/settings",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",