@serhii.olishevskyi/docs 1.2.24 → 1.2.25

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
@@ -504,6 +504,9 @@ type CollapsedContainerComponentProps = {
504
504
  };
505
505
  declare const CollapsedContainerComponent: (props: PropsWithChildren<CollapsedContainerComponentProps>) => React$1.JSX.Element;
506
506
 
507
+ declare const LanguageSelector: React__default.FC;
508
+ declare const PublicLanguageSelector: React__default.FC;
509
+
507
510
  type AIProviderType = 'gemini' | 'openai';
508
511
  interface AIServiceConfig {
509
512
  apiKey?: string;
@@ -854,4 +857,4 @@ declare const Utils: {
854
857
  };
855
858
  };
856
859
 
857
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, ButtonComponent, type ButtonComponentProps, CheckboxComponent, type CheckboxComponentProps, CollapsedContainerComponent, type CollapsedContainerComponentProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, CopyClipboardButtonComponent, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, EmailInputComponent, type EmailInputComponentProps, ErrorAlertComponent, type ErrorAlertComponentProps, ExpandableNoteComponent, type ExpandableNoteComponentProps, FilterContainerComponent, type FilterContainerComponentProps, type FilterSectionProps, type FilterWidth, type FullCompanyMemberItem, type HeaderActionItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, MyAvatarComponent, type MyAvatarComponentProps, NumberInputComponent, type NumberInputComponentProps, PageComponent, type PageComponentProps, type PageHeaderProps, type PageLink, PageLinkComponent, type PageLinkComponentProps, type PrimaryActionProps, Providers, type RefreshActionProps, RefreshButtonComponent, type RefreshButtonComponentProps, type SaveCompanyUserPayload, SearchComponent, type SearchComponentProps, SelectComponent, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, SwitchComponent, type SwitchComponentProps, TextFieldComponent, type TextFieldComponentProps, type TextTruncateMode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, TranslatableTooltipComponent, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UrlComponent, type UrlComponentProps, UserAvatarComponent, type UserAvatarComponentProps, type UserGroupedSessions, UserPopoverComponent, type UserPopoverComponentProps, type UserProfile, UserRoleChipComponent, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, UserStatusChipComponent, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
860
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, ButtonComponent, type ButtonComponentProps, CheckboxComponent, type CheckboxComponentProps, CollapsedContainerComponent, type CollapsedContainerComponentProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, CopyClipboardButtonComponent, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, EmailInputComponent, type EmailInputComponentProps, ErrorAlertComponent, type ErrorAlertComponentProps, ExpandableNoteComponent, type ExpandableNoteComponentProps, FilterContainerComponent, type FilterContainerComponentProps, type FilterSectionProps, type FilterWidth, type FullCompanyMemberItem, type HeaderActionItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, MyAvatarComponent, type MyAvatarComponentProps, NumberInputComponent, type NumberInputComponentProps, PageComponent, type PageComponentProps, type PageHeaderProps, type PageLink, PageLinkComponent, type PageLinkComponentProps, type PrimaryActionProps, LanguageSelector as ProtectedLanguageSelector, Providers, PublicLanguageSelector, type RefreshActionProps, RefreshButtonComponent, type RefreshButtonComponentProps, type SaveCompanyUserPayload, SearchComponent, type SearchComponentProps, SelectComponent, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, SwitchComponent, type SwitchComponentProps, TextFieldComponent, type TextFieldComponentProps, type TextTruncateMode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, TranslatableTooltipComponent, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UrlComponent, type UrlComponentProps, UserAvatarComponent, type UserAvatarComponentProps, type UserGroupedSessions, UserPopoverComponent, type UserPopoverComponentProps, type UserProfile, UserRoleChipComponent, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, UserStatusChipComponent, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
package/dist/index.d.ts CHANGED
@@ -504,6 +504,9 @@ type CollapsedContainerComponentProps = {
504
504
  };
505
505
  declare const CollapsedContainerComponent: (props: PropsWithChildren<CollapsedContainerComponentProps>) => React$1.JSX.Element;
506
506
 
507
+ declare const LanguageSelector: React__default.FC;
508
+ declare const PublicLanguageSelector: React__default.FC;
509
+
507
510
  type AIProviderType = 'gemini' | 'openai';
508
511
  interface AIServiceConfig {
509
512
  apiKey?: string;
@@ -854,4 +857,4 @@ declare const Utils: {
854
857
  };
855
858
  };
856
859
 
857
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, ButtonComponent, type ButtonComponentProps, CheckboxComponent, type CheckboxComponentProps, CollapsedContainerComponent, type CollapsedContainerComponentProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, CopyClipboardButtonComponent, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, EmailInputComponent, type EmailInputComponentProps, ErrorAlertComponent, type ErrorAlertComponentProps, ExpandableNoteComponent, type ExpandableNoteComponentProps, FilterContainerComponent, type FilterContainerComponentProps, type FilterSectionProps, type FilterWidth, type FullCompanyMemberItem, type HeaderActionItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, MyAvatarComponent, type MyAvatarComponentProps, NumberInputComponent, type NumberInputComponentProps, PageComponent, type PageComponentProps, type PageHeaderProps, type PageLink, PageLinkComponent, type PageLinkComponentProps, type PrimaryActionProps, Providers, type RefreshActionProps, RefreshButtonComponent, type RefreshButtonComponentProps, type SaveCompanyUserPayload, SearchComponent, type SearchComponentProps, SelectComponent, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, SwitchComponent, type SwitchComponentProps, TextFieldComponent, type TextFieldComponentProps, type TextTruncateMode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, TranslatableTooltipComponent, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UrlComponent, type UrlComponentProps, UserAvatarComponent, type UserAvatarComponentProps, type UserGroupedSessions, UserPopoverComponent, type UserPopoverComponentProps, type UserProfile, UserRoleChipComponent, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, UserStatusChipComponent, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
860
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, ButtonComponent, type ButtonComponentProps, CheckboxComponent, type CheckboxComponentProps, CollapsedContainerComponent, type CollapsedContainerComponentProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, CopyClipboardButtonComponent, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, EmailInputComponent, type EmailInputComponentProps, ErrorAlertComponent, type ErrorAlertComponentProps, ExpandableNoteComponent, type ExpandableNoteComponentProps, FilterContainerComponent, type FilterContainerComponentProps, type FilterSectionProps, type FilterWidth, type FullCompanyMemberItem, type HeaderActionItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, MyAvatarComponent, type MyAvatarComponentProps, NumberInputComponent, type NumberInputComponentProps, PageComponent, type PageComponentProps, type PageHeaderProps, type PageLink, PageLinkComponent, type PageLinkComponentProps, type PrimaryActionProps, LanguageSelector as ProtectedLanguageSelector, Providers, PublicLanguageSelector, type RefreshActionProps, RefreshButtonComponent, type RefreshButtonComponentProps, type SaveCompanyUserPayload, SearchComponent, type SearchComponentProps, SelectComponent, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, SwitchComponent, type SwitchComponentProps, TextFieldComponent, type TextFieldComponentProps, type TextTruncateMode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, TranslatableTooltipComponent, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UrlComponent, type UrlComponentProps, UserAvatarComponent, type UserAvatarComponentProps, type UserGroupedSessions, UserPopoverComponent, type UserPopoverComponentProps, type UserProfile, UserRoleChipComponent, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, UserStatusChipComponent, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
package/dist/index.js CHANGED
@@ -2968,7 +2968,9 @@ __export(index_exports, {
2968
2968
  NumberInputComponent: () => NumberInputComponent,
2969
2969
  PageComponent: () => PageComponent,
2970
2970
  PageLinkComponent: () => PageLinkComponent,
2971
+ ProtectedLanguageSelector: () => LanguageSelector,
2971
2972
  Providers: () => Providers,
2973
+ PublicLanguageSelector: () => PublicLanguageSelector,
2972
2974
  RefreshButtonComponent: () => RefreshButtonComponent,
2973
2975
  SearchComponent: () => SearchComponent,
2974
2976
  SelectComponent: () => SelectComponent,
@@ -5212,6 +5214,286 @@ var CollapsedContainerComponent = (props) => {
5212
5214
  ] });
5213
5215
  };
5214
5216
 
5217
+ // src/i18n/LanguageSelector.tsx
5218
+ var import_react33 = require("react");
5219
+ var import_react_i18next6 = require("react-i18next");
5220
+ var import_material29 = require("@mui/material");
5221
+ init_LocalizationProvider();
5222
+ init_UserSettingsProvider();
5223
+ init_SupabaseProvider();
5224
+ var import_jsx_runtime39 = require("react/jsx-runtime");
5225
+ var LanguageSelector = () => {
5226
+ const supabase = useSupabase();
5227
+ const { i18n: i18n2 } = (0, import_react_i18next6.useTranslation)();
5228
+ const [languages, setLanguages] = (0, import_react33.useState)([]);
5229
+ const [loading, setLoading] = (0, import_react33.useState)(true);
5230
+ const { changeLanguage } = useLocalization();
5231
+ const { settings: userSettings, setLanguage } = useUserSettings();
5232
+ const [anchorEl, setAnchorEl] = (0, import_react33.useState)(null);
5233
+ const open = Boolean(anchorEl);
5234
+ (0, import_react33.useEffect)(() => {
5235
+ const fetchLanguages = async () => {
5236
+ try {
5237
+ const { data, error } = await supabase.from("languages").select("code, name, svg_flag").eq("enabled", true);
5238
+ if (error) throw error;
5239
+ setLanguages(data || []);
5240
+ if (userSettings.language) changeLanguage(userSettings.language);
5241
+ } catch (err) {
5242
+ console.error("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u043C\u043E\u0432:", err);
5243
+ } finally {
5244
+ setLoading(false);
5245
+ }
5246
+ };
5247
+ fetchLanguages();
5248
+ }, []);
5249
+ const handleClick = (event) => {
5250
+ setAnchorEl(event.currentTarget);
5251
+ };
5252
+ const handleClose = () => {
5253
+ setAnchorEl(null);
5254
+ };
5255
+ const handleSelectLanguage = (langCode) => {
5256
+ changeLanguage(langCode);
5257
+ setLanguage(langCode);
5258
+ handleClose();
5259
+ };
5260
+ if (loading) {
5261
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.CircularProgress, { size: 20, color: "inherit", sx: { mx: 1 } });
5262
+ }
5263
+ const rawCurrentLang = i18n2.language || "uk";
5264
+ const currentLangCode = rawCurrentLang.split("-")[0];
5265
+ const currentLang = languages.find((l) => l.code === currentLangCode) || languages[0];
5266
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
5267
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.Tooltip, { title: currentLang ? currentLang.name : "\u041C\u043E\u0432\u0430", arrow: true, placement: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5268
+ import_material29.IconButton,
5269
+ {
5270
+ onClick: handleClick,
5271
+ size: "small",
5272
+ "aria-controls": open ? "language-menu" : void 0,
5273
+ "aria-haspopup": "true",
5274
+ "aria-expanded": open ? "true" : void 0,
5275
+ sx: {
5276
+ p: 1,
5277
+ borderRadius: 2,
5278
+ transition: "background-color 0.2s",
5279
+ "&:hover": {
5280
+ backgroundColor: "action.hover"
5281
+ }
5282
+ },
5283
+ children: currentLang?.svg_flag && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5284
+ import_material29.Box,
5285
+ {
5286
+ sx: {
5287
+ width: 24,
5288
+ height: 16,
5289
+ borderRadius: "3px",
5290
+ overflow: "hidden",
5291
+ flexShrink: 0,
5292
+ boxShadow: "0 0 2px rgba(0,0,0,0.3)",
5293
+ display: "flex",
5294
+ alignItems: "center",
5295
+ justifyContent: "center",
5296
+ "& svg": { width: "100%", height: "100%", display: "block", objectFit: "cover" }
5297
+ },
5298
+ dangerouslySetInnerHTML: { __html: currentLang.svg_flag }
5299
+ }
5300
+ )
5301
+ }
5302
+ ) }),
5303
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5304
+ import_material29.Menu,
5305
+ {
5306
+ id: "language-menu",
5307
+ anchorEl,
5308
+ open,
5309
+ onClose: handleClose,
5310
+ slotProps: {
5311
+ paper: {
5312
+ elevation: 3,
5313
+ sx: {
5314
+ mt: 1,
5315
+ minWidth: 150,
5316
+ borderRadius: 2
5317
+ }
5318
+ }
5319
+ },
5320
+ transformOrigin: { horizontal: "right", vertical: "top" },
5321
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
5322
+ children: languages.map((lang) => {
5323
+ const isSelected = lang.code === currentLangCode;
5324
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
5325
+ import_material29.MenuItem,
5326
+ {
5327
+ selected: isSelected,
5328
+ onClick: () => handleSelectLanguage(lang.code),
5329
+ sx: {
5330
+ display: "flex",
5331
+ alignItems: "center",
5332
+ gap: 1.5,
5333
+ py: 1,
5334
+ px: 2
5335
+ },
5336
+ children: [
5337
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5338
+ import_material29.Box,
5339
+ {
5340
+ sx: {
5341
+ width: 22,
5342
+ height: 15,
5343
+ borderRadius: "2px",
5344
+ overflow: "hidden",
5345
+ flexShrink: 0,
5346
+ boxShadow: "0 0 1px rgba(0,0,0,0.4)",
5347
+ "& svg": { width: "100%", height: "100%", display: "block" }
5348
+ },
5349
+ dangerouslySetInnerHTML: { __html: lang.svg_flag }
5350
+ }
5351
+ ),
5352
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.Typography, { variant: "body2", sx: { fontWeight: isSelected ? 600 : 400 }, children: lang.name })
5353
+ ]
5354
+ },
5355
+ lang.code
5356
+ );
5357
+ })
5358
+ }
5359
+ )
5360
+ ] });
5361
+ };
5362
+ var PublicLanguageSelector = () => {
5363
+ const supabase = useSupabase();
5364
+ const { i18n: i18n2 } = (0, import_react_i18next6.useTranslation)();
5365
+ const { changeLanguage } = useLocalization();
5366
+ const [languages, setLanguages] = (0, import_react33.useState)([]);
5367
+ const [loading, setLoading] = (0, import_react33.useState)(true);
5368
+ const [anchorEl, setAnchorEl] = (0, import_react33.useState)(null);
5369
+ const open = Boolean(anchorEl);
5370
+ (0, import_react33.useEffect)(() => {
5371
+ const fetchLanguages = async () => {
5372
+ try {
5373
+ const { data, error } = await supabase.from("languages").select("code, name, svg_flag").eq("enabled", true);
5374
+ if (error) throw error;
5375
+ setLanguages(data || []);
5376
+ } catch (err) {
5377
+ console.error("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u043C\u043E\u0432:", err);
5378
+ } finally {
5379
+ setLoading(false);
5380
+ }
5381
+ };
5382
+ fetchLanguages();
5383
+ }, []);
5384
+ const handleClick = (event) => {
5385
+ setAnchorEl(event.currentTarget);
5386
+ };
5387
+ const handleClose = () => {
5388
+ setAnchorEl(null);
5389
+ };
5390
+ const handleSelectLanguage = (langCode) => {
5391
+ changeLanguage(langCode);
5392
+ handleClose();
5393
+ };
5394
+ if (loading) {
5395
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.CircularProgress, { size: 20, color: "inherit", sx: { mx: 1 } });
5396
+ }
5397
+ const rawCurrentLang = i18n2.language || "uk";
5398
+ const currentLangCode = rawCurrentLang.split("-")[0];
5399
+ const currentLang = languages.find((l) => l.code === currentLangCode) || languages[0];
5400
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
5401
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.Tooltip, { title: currentLang ? currentLang.name : "\u041C\u043E\u0432\u0430", arrow: true, placement: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5402
+ import_material29.IconButton,
5403
+ {
5404
+ onClick: handleClick,
5405
+ size: "small",
5406
+ "aria-controls": open ? "language-menu" : void 0,
5407
+ "aria-haspopup": "true",
5408
+ "aria-expanded": open ? "true" : void 0,
5409
+ sx: {
5410
+ p: 1,
5411
+ borderRadius: 2,
5412
+ transition: "background-color 0.2s",
5413
+ "&:hover": {
5414
+ backgroundColor: "action.hover"
5415
+ }
5416
+ },
5417
+ children: currentLang?.svg_flag && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5418
+ import_material29.Box,
5419
+ {
5420
+ sx: {
5421
+ width: 24,
5422
+ height: 16,
5423
+ borderRadius: "3px",
5424
+ overflow: "hidden",
5425
+ flexShrink: 0,
5426
+ boxShadow: "0 0 2px rgba(0,0,0,0.3)",
5427
+ display: "flex",
5428
+ alignItems: "center",
5429
+ justifyContent: "center",
5430
+ "& svg": { width: "100%", height: "100%", display: "block", objectFit: "cover" }
5431
+ },
5432
+ dangerouslySetInnerHTML: { __html: currentLang.svg_flag }
5433
+ }
5434
+ )
5435
+ }
5436
+ ) }),
5437
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5438
+ import_material29.Menu,
5439
+ {
5440
+ id: "language-menu",
5441
+ anchorEl,
5442
+ open,
5443
+ onClose: handleClose,
5444
+ slotProps: {
5445
+ paper: {
5446
+ elevation: 3,
5447
+ sx: {
5448
+ mt: 1,
5449
+ minWidth: 150,
5450
+ borderRadius: 2
5451
+ }
5452
+ }
5453
+ },
5454
+ transformOrigin: { horizontal: "right", vertical: "top" },
5455
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
5456
+ children: languages.map((lang) => {
5457
+ const isSelected = lang.code === currentLangCode;
5458
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
5459
+ import_material29.MenuItem,
5460
+ {
5461
+ selected: isSelected,
5462
+ onClick: () => handleSelectLanguage(lang.code),
5463
+ sx: {
5464
+ display: "flex",
5465
+ alignItems: "center",
5466
+ gap: 1.5,
5467
+ py: 1,
5468
+ px: 2
5469
+ },
5470
+ children: [
5471
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
5472
+ import_material29.Box,
5473
+ {
5474
+ sx: {
5475
+ width: 22,
5476
+ height: 15,
5477
+ borderRadius: "2px",
5478
+ overflow: "hidden",
5479
+ flexShrink: 0,
5480
+ boxShadow: "0 0 1px rgba(0,0,0,0.4)",
5481
+ "& svg": { width: "100%", height: "100%", display: "block" }
5482
+ },
5483
+ dangerouslySetInnerHTML: { __html: lang.svg_flag }
5484
+ }
5485
+ ),
5486
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material29.Typography, { variant: "body2", sx: { fontWeight: isSelected ? 600 : 400 }, children: lang.name })
5487
+ ]
5488
+ },
5489
+ lang.code
5490
+ );
5491
+ })
5492
+ }
5493
+ )
5494
+ ] });
5495
+ };
5496
+
5215
5497
  // src/types/index.ts
5216
5498
  init_user_types();
5217
5499
 
@@ -5235,16 +5517,16 @@ var Services = {
5235
5517
  };
5236
5518
 
5237
5519
  // src/hooks/useUserStatus.ts
5238
- var import_react33 = require("react");
5520
+ var import_react34 = require("react");
5239
5521
  init_deviceId();
5240
5522
  init_context();
5241
5523
  var ONLINE_THRESHOLD_MINUTES = 2;
5242
5524
  var AWAY_THRESHOLD_MINUTES = 15;
5243
5525
  var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
5244
5526
  const supabase = useSupabase();
5245
- const [status, setStatus] = (0, import_react33.useState)("offline");
5246
- const [lastSeen, setLastSeen] = (0, import_react33.useState)(initialLastSeenAt ?? null);
5247
- const lastSeenRef = (0, import_react33.useRef)(initialLastSeenAt ?? null);
5527
+ const [status, setStatus] = (0, import_react34.useState)("offline");
5528
+ const [lastSeen, setLastSeen] = (0, import_react34.useState)(initialLastSeenAt ?? null);
5529
+ const lastSeenRef = (0, import_react34.useRef)(initialLastSeenAt ?? null);
5248
5530
  lastSeenRef.current = lastSeen;
5249
5531
  const calculateStatus = (isOnline, lastSeenIso) => {
5250
5532
  if (isOnline) return "online";
@@ -5260,7 +5542,7 @@ var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
5260
5542
  }
5261
5543
  return "offline";
5262
5544
  };
5263
- (0, import_react33.useEffect)(() => {
5545
+ (0, import_react34.useEffect)(() => {
5264
5546
  if (!userId) return;
5265
5547
  let isMounted = true;
5266
5548
  const isSelf = currentAuthUserId && userId === currentAuthUserId;
@@ -5380,7 +5662,9 @@ var Utils = {
5380
5662
  NumberInputComponent,
5381
5663
  PageComponent,
5382
5664
  PageLinkComponent,
5665
+ ProtectedLanguageSelector,
5383
5666
  Providers,
5667
+ PublicLanguageSelector,
5384
5668
  RefreshButtonComponent,
5385
5669
  SearchComponent,
5386
5670
  SelectComponent,
package/dist/index.mjs CHANGED
@@ -2277,6 +2277,291 @@ var CollapsedContainerComponent = (props) => {
2277
2277
  ] });
2278
2278
  };
2279
2279
 
2280
+ // src/i18n/LanguageSelector.tsx
2281
+ import { useEffect as useEffect5, useState as useState13 } from "react";
2282
+ import { useTranslation as useTranslation3 } from "react-i18next";
2283
+ import {
2284
+ Box as Box10,
2285
+ Typography as Typography9,
2286
+ CircularProgress,
2287
+ IconButton as IconButton8,
2288
+ Menu as Menu2,
2289
+ MenuItem as MenuItem3,
2290
+ Tooltip as Tooltip8
2291
+ } from "@mui/material";
2292
+ import { Fragment as Fragment10, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2293
+ var LanguageSelector = () => {
2294
+ const supabase = useSupabase();
2295
+ const { i18n } = useTranslation3();
2296
+ const [languages, setLanguages] = useState13([]);
2297
+ const [loading, setLoading] = useState13(true);
2298
+ const { changeLanguage } = useLocalization();
2299
+ const { settings: userSettings, setLanguage } = useUserSettings();
2300
+ const [anchorEl, setAnchorEl] = useState13(null);
2301
+ const open = Boolean(anchorEl);
2302
+ useEffect5(() => {
2303
+ const fetchLanguages = async () => {
2304
+ try {
2305
+ const { data, error } = await supabase.from("languages").select("code, name, svg_flag").eq("enabled", true);
2306
+ if (error) throw error;
2307
+ setLanguages(data || []);
2308
+ if (userSettings.language) changeLanguage(userSettings.language);
2309
+ } catch (err) {
2310
+ console.error("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u043C\u043E\u0432:", err);
2311
+ } finally {
2312
+ setLoading(false);
2313
+ }
2314
+ };
2315
+ fetchLanguages();
2316
+ }, []);
2317
+ const handleClick = (event) => {
2318
+ setAnchorEl(event.currentTarget);
2319
+ };
2320
+ const handleClose = () => {
2321
+ setAnchorEl(null);
2322
+ };
2323
+ const handleSelectLanguage = (langCode) => {
2324
+ changeLanguage(langCode);
2325
+ setLanguage(langCode);
2326
+ handleClose();
2327
+ };
2328
+ if (loading) {
2329
+ return /* @__PURE__ */ jsx19(CircularProgress, { size: 20, color: "inherit", sx: { mx: 1 } });
2330
+ }
2331
+ const rawCurrentLang = i18n.language || "uk";
2332
+ const currentLangCode = rawCurrentLang.split("-")[0];
2333
+ const currentLang = languages.find((l) => l.code === currentLangCode) || languages[0];
2334
+ return /* @__PURE__ */ jsxs13(Fragment10, { children: [
2335
+ /* @__PURE__ */ jsx19(Tooltip8, { title: currentLang ? currentLang.name : "\u041C\u043E\u0432\u0430", arrow: true, placement: "bottom", children: /* @__PURE__ */ jsx19(
2336
+ IconButton8,
2337
+ {
2338
+ onClick: handleClick,
2339
+ size: "small",
2340
+ "aria-controls": open ? "language-menu" : void 0,
2341
+ "aria-haspopup": "true",
2342
+ "aria-expanded": open ? "true" : void 0,
2343
+ sx: {
2344
+ p: 1,
2345
+ borderRadius: 2,
2346
+ transition: "background-color 0.2s",
2347
+ "&:hover": {
2348
+ backgroundColor: "action.hover"
2349
+ }
2350
+ },
2351
+ children: currentLang?.svg_flag && /* @__PURE__ */ jsx19(
2352
+ Box10,
2353
+ {
2354
+ sx: {
2355
+ width: 24,
2356
+ height: 16,
2357
+ borderRadius: "3px",
2358
+ overflow: "hidden",
2359
+ flexShrink: 0,
2360
+ boxShadow: "0 0 2px rgba(0,0,0,0.3)",
2361
+ display: "flex",
2362
+ alignItems: "center",
2363
+ justifyContent: "center",
2364
+ "& svg": { width: "100%", height: "100%", display: "block", objectFit: "cover" }
2365
+ },
2366
+ dangerouslySetInnerHTML: { __html: currentLang.svg_flag }
2367
+ }
2368
+ )
2369
+ }
2370
+ ) }),
2371
+ /* @__PURE__ */ jsx19(
2372
+ Menu2,
2373
+ {
2374
+ id: "language-menu",
2375
+ anchorEl,
2376
+ open,
2377
+ onClose: handleClose,
2378
+ slotProps: {
2379
+ paper: {
2380
+ elevation: 3,
2381
+ sx: {
2382
+ mt: 1,
2383
+ minWidth: 150,
2384
+ borderRadius: 2
2385
+ }
2386
+ }
2387
+ },
2388
+ transformOrigin: { horizontal: "right", vertical: "top" },
2389
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
2390
+ children: languages.map((lang) => {
2391
+ const isSelected = lang.code === currentLangCode;
2392
+ return /* @__PURE__ */ jsxs13(
2393
+ MenuItem3,
2394
+ {
2395
+ selected: isSelected,
2396
+ onClick: () => handleSelectLanguage(lang.code),
2397
+ sx: {
2398
+ display: "flex",
2399
+ alignItems: "center",
2400
+ gap: 1.5,
2401
+ py: 1,
2402
+ px: 2
2403
+ },
2404
+ children: [
2405
+ /* @__PURE__ */ jsx19(
2406
+ Box10,
2407
+ {
2408
+ sx: {
2409
+ width: 22,
2410
+ height: 15,
2411
+ borderRadius: "2px",
2412
+ overflow: "hidden",
2413
+ flexShrink: 0,
2414
+ boxShadow: "0 0 1px rgba(0,0,0,0.4)",
2415
+ "& svg": { width: "100%", height: "100%", display: "block" }
2416
+ },
2417
+ dangerouslySetInnerHTML: { __html: lang.svg_flag }
2418
+ }
2419
+ ),
2420
+ /* @__PURE__ */ jsx19(Typography9, { variant: "body2", sx: { fontWeight: isSelected ? 600 : 400 }, children: lang.name })
2421
+ ]
2422
+ },
2423
+ lang.code
2424
+ );
2425
+ })
2426
+ }
2427
+ )
2428
+ ] });
2429
+ };
2430
+ var PublicLanguageSelector = () => {
2431
+ const supabase = useSupabase();
2432
+ const { i18n } = useTranslation3();
2433
+ const { changeLanguage } = useLocalization();
2434
+ const [languages, setLanguages] = useState13([]);
2435
+ const [loading, setLoading] = useState13(true);
2436
+ const [anchorEl, setAnchorEl] = useState13(null);
2437
+ const open = Boolean(anchorEl);
2438
+ useEffect5(() => {
2439
+ const fetchLanguages = async () => {
2440
+ try {
2441
+ const { data, error } = await supabase.from("languages").select("code, name, svg_flag").eq("enabled", true);
2442
+ if (error) throw error;
2443
+ setLanguages(data || []);
2444
+ } catch (err) {
2445
+ console.error("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u043C\u043E\u0432:", err);
2446
+ } finally {
2447
+ setLoading(false);
2448
+ }
2449
+ };
2450
+ fetchLanguages();
2451
+ }, []);
2452
+ const handleClick = (event) => {
2453
+ setAnchorEl(event.currentTarget);
2454
+ };
2455
+ const handleClose = () => {
2456
+ setAnchorEl(null);
2457
+ };
2458
+ const handleSelectLanguage = (langCode) => {
2459
+ changeLanguage(langCode);
2460
+ handleClose();
2461
+ };
2462
+ if (loading) {
2463
+ return /* @__PURE__ */ jsx19(CircularProgress, { size: 20, color: "inherit", sx: { mx: 1 } });
2464
+ }
2465
+ const rawCurrentLang = i18n.language || "uk";
2466
+ const currentLangCode = rawCurrentLang.split("-")[0];
2467
+ const currentLang = languages.find((l) => l.code === currentLangCode) || languages[0];
2468
+ return /* @__PURE__ */ jsxs13(Fragment10, { children: [
2469
+ /* @__PURE__ */ jsx19(Tooltip8, { title: currentLang ? currentLang.name : "\u041C\u043E\u0432\u0430", arrow: true, placement: "bottom", children: /* @__PURE__ */ jsx19(
2470
+ IconButton8,
2471
+ {
2472
+ onClick: handleClick,
2473
+ size: "small",
2474
+ "aria-controls": open ? "language-menu" : void 0,
2475
+ "aria-haspopup": "true",
2476
+ "aria-expanded": open ? "true" : void 0,
2477
+ sx: {
2478
+ p: 1,
2479
+ borderRadius: 2,
2480
+ transition: "background-color 0.2s",
2481
+ "&:hover": {
2482
+ backgroundColor: "action.hover"
2483
+ }
2484
+ },
2485
+ children: currentLang?.svg_flag && /* @__PURE__ */ jsx19(
2486
+ Box10,
2487
+ {
2488
+ sx: {
2489
+ width: 24,
2490
+ height: 16,
2491
+ borderRadius: "3px",
2492
+ overflow: "hidden",
2493
+ flexShrink: 0,
2494
+ boxShadow: "0 0 2px rgba(0,0,0,0.3)",
2495
+ display: "flex",
2496
+ alignItems: "center",
2497
+ justifyContent: "center",
2498
+ "& svg": { width: "100%", height: "100%", display: "block", objectFit: "cover" }
2499
+ },
2500
+ dangerouslySetInnerHTML: { __html: currentLang.svg_flag }
2501
+ }
2502
+ )
2503
+ }
2504
+ ) }),
2505
+ /* @__PURE__ */ jsx19(
2506
+ Menu2,
2507
+ {
2508
+ id: "language-menu",
2509
+ anchorEl,
2510
+ open,
2511
+ onClose: handleClose,
2512
+ slotProps: {
2513
+ paper: {
2514
+ elevation: 3,
2515
+ sx: {
2516
+ mt: 1,
2517
+ minWidth: 150,
2518
+ borderRadius: 2
2519
+ }
2520
+ }
2521
+ },
2522
+ transformOrigin: { horizontal: "right", vertical: "top" },
2523
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
2524
+ children: languages.map((lang) => {
2525
+ const isSelected = lang.code === currentLangCode;
2526
+ return /* @__PURE__ */ jsxs13(
2527
+ MenuItem3,
2528
+ {
2529
+ selected: isSelected,
2530
+ onClick: () => handleSelectLanguage(lang.code),
2531
+ sx: {
2532
+ display: "flex",
2533
+ alignItems: "center",
2534
+ gap: 1.5,
2535
+ py: 1,
2536
+ px: 2
2537
+ },
2538
+ children: [
2539
+ /* @__PURE__ */ jsx19(
2540
+ Box10,
2541
+ {
2542
+ sx: {
2543
+ width: 22,
2544
+ height: 15,
2545
+ borderRadius: "2px",
2546
+ overflow: "hidden",
2547
+ flexShrink: 0,
2548
+ boxShadow: "0 0 1px rgba(0,0,0,0.4)",
2549
+ "& svg": { width: "100%", height: "100%", display: "block" }
2550
+ },
2551
+ dangerouslySetInnerHTML: { __html: lang.svg_flag }
2552
+ }
2553
+ ),
2554
+ /* @__PURE__ */ jsx19(Typography9, { variant: "body2", sx: { fontWeight: isSelected ? 600 : 400 }, children: lang.name })
2555
+ ]
2556
+ },
2557
+ lang.code
2558
+ );
2559
+ })
2560
+ }
2561
+ )
2562
+ ] });
2563
+ };
2564
+
2280
2565
  // src/services/index.ts
2281
2566
  var Services = {
2282
2567
  SessionService: {
@@ -2292,13 +2577,13 @@ var Services = {
2292
2577
  };
2293
2578
 
2294
2579
  // src/hooks/useUserStatus.ts
2295
- import { useEffect as useEffect5, useRef, useState as useState13 } from "react";
2580
+ import { useEffect as useEffect6, useRef, useState as useState14 } from "react";
2296
2581
  var ONLINE_THRESHOLD_MINUTES = 2;
2297
2582
  var AWAY_THRESHOLD_MINUTES = 15;
2298
2583
  var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
2299
2584
  const supabase = useSupabase();
2300
- const [status, setStatus] = useState13("offline");
2301
- const [lastSeen, setLastSeen] = useState13(initialLastSeenAt ?? null);
2585
+ const [status, setStatus] = useState14("offline");
2586
+ const [lastSeen, setLastSeen] = useState14(initialLastSeenAt ?? null);
2302
2587
  const lastSeenRef = useRef(initialLastSeenAt ?? null);
2303
2588
  lastSeenRef.current = lastSeen;
2304
2589
  const calculateStatus = (isOnline, lastSeenIso) => {
@@ -2315,7 +2600,7 @@ var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
2315
2600
  }
2316
2601
  return "offline";
2317
2602
  };
2318
- useEffect5(() => {
2603
+ useEffect6(() => {
2319
2604
  if (!userId) return;
2320
2605
  let isMounted = true;
2321
2606
  const isSelf = currentAuthUserId && userId === currentAuthUserId;
@@ -2431,7 +2716,9 @@ export {
2431
2716
  NumberInputComponent,
2432
2717
  PageComponent,
2433
2718
  PageLinkComponent,
2719
+ LanguageSelector as ProtectedLanguageSelector,
2434
2720
  Providers,
2721
+ PublicLanguageSelector,
2435
2722
  RefreshButtonComponent,
2436
2723
  SearchComponent,
2437
2724
  SelectComponent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serhii.olishevskyi/docs",
3
- "version": "1.2.24",
3
+ "version": "1.2.25",
4
4
  "description": "DOCS.UA react packages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",