@serhii.olishevskyi/docs 1.2.16 → 1.2.18

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
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { TextFieldProps, SelectProps, SelectChangeEvent, FormControlLabelProps, SwitchProps, CheckboxProps, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
3
+ import { TextFieldProps, SelectProps, SelectChangeEvent, FormControlLabelProps, SwitchProps, CheckboxProps, ButtonProps, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
4
4
  import { SystemProps } from '@mui/system';
5
5
  import * as _supabase_supabase_js from '@supabase/supabase-js';
6
6
  import { SupabaseClient, User, Session } from '@supabase/supabase-js';
@@ -155,6 +155,22 @@ type CheckboxComponentProps = Omit<FormControlLabelProps, 'control' | 'label' |
155
155
  checkboxProps?: CheckboxProps;
156
156
  };
157
157
 
158
+ type ButtonComponentProps = Omit<ButtonProps, 'children'> & {
159
+ /**
160
+ * Метка кнопки. Если передана строка, она автоматически
161
+ * оборачивается в <TranslateText> для локализации.
162
+ */
163
+ label?: ReactNode;
164
+ /**
165
+ * Кастомный неймспейс для перевода (если нужен)
166
+ */
167
+ overrideNamespace?: string;
168
+ /**
169
+ * Дочерние элементы (используются, если не передан label)
170
+ */
171
+ children?: ReactNode;
172
+ };
173
+
158
174
  interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onClick'> {
159
175
  overrideNamespace?: string;
160
176
  /** Текст, який буде скопійовано в буфер обміну */
@@ -171,6 +187,21 @@ interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onCli
171
187
  onCopySuccess?: (text: string) => void;
172
188
  }
173
189
 
190
+ interface RefreshButtonComponentProps {
191
+ overrideNamespace?: string;
192
+ size?: 'small' | 'medium' | 'large';
193
+ color?: "success" | "error" | "info" | "warning";
194
+ onClick?: (event: React__default.MouseEvent<HTMLButtonElement>) => void | Promise<void>;
195
+ disabled?: boolean;
196
+ fullWidth?: boolean;
197
+ loading?: boolean;
198
+ tooltip?: ReactNode;
199
+ mobileViewOnly?: boolean;
200
+ disableMobileView?: boolean;
201
+ hideTooltipOnMobile?: boolean;
202
+ hideTooltipOnDesktop?: boolean;
203
+ }
204
+
174
205
  interface TranslatableTooltipComponentProps extends Omit<TooltipProps, 'children'> {
175
206
  overrideNamespace?: string;
176
207
  disableSpan?: boolean;
@@ -384,6 +415,15 @@ type CollapsedWidgetContainerProps = {
384
415
  onExpanded?: (expanded: boolean) => void;
385
416
  };
386
417
 
418
+ interface ErrorAlertWidgetProps {
419
+ overrideNamespace?: string;
420
+ title?: ReactNode;
421
+ message: ReactNode;
422
+ onRetry?: () => void;
423
+ retryText?: ReactNode;
424
+ isRetrying?: boolean;
425
+ }
426
+
387
427
  declare const UI: {
388
428
  Inputs: {
389
429
  TextField: React$1.FC<TextFieldComponentProps>;
@@ -396,7 +436,9 @@ declare const UI: {
396
436
  Url: typeof UrlComponent;
397
437
  };
398
438
  Buttons: {
439
+ ButtonComponent: React$1.ForwardRefExoticComponent<Omit<ButtonComponentProps, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
399
440
  CopyClipboardButton: React$1.FC<CopyClipboardButtonComponentProps>;
441
+ RefreshButton: React$1.FC<RefreshButtonComponentProps>;
400
442
  };
401
443
  DataDisplay: {
402
444
  TranslatableTooltip: React$1.FC<TranslatableTooltipComponentProps>;
@@ -416,6 +458,9 @@ declare const UI: {
416
458
  PageLinkWidget: React$1.FC<PageLinkWidgetProps>;
417
459
  CollapsedWidgetContainer: (props: React$1.PropsWithChildren<CollapsedWidgetContainerProps>) => React$1.JSX.Element;
418
460
  };
461
+ Misc: {
462
+ ErrorAlertWidget: React$1.FC<ErrorAlertWidgetProps>;
463
+ };
419
464
  };
420
465
  };
421
466
 
@@ -763,6 +808,10 @@ declare const Hooks: {
763
808
 
764
809
  declare const Utils: {
765
810
  readonly getDeviceId: () => string;
811
+ readonly Sessions: {
812
+ readonly notifySessionChange: () => void;
813
+ readonly subscribeToSessionChanges: (callback: () => void) => () => void;
814
+ };
766
815
  };
767
816
 
768
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type CheckboxComponentProps, type CollapsedWidgetContainerProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, type PageLink, type PageLinkWidgetProps, Providers, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type SwitchComponentProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
817
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ButtonComponentProps, type CheckboxComponentProps, type CollapsedWidgetContainerProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ErrorAlertWidgetProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, type PageLink, type PageLinkWidgetProps, Providers, type RefreshButtonComponentProps, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type SwitchComponentProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, 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
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { TextFieldProps, SelectProps, SelectChangeEvent, FormControlLabelProps, SwitchProps, CheckboxProps, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
3
+ import { TextFieldProps, SelectProps, SelectChangeEvent, FormControlLabelProps, SwitchProps, CheckboxProps, ButtonProps, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
4
4
  import { SystemProps } from '@mui/system';
5
5
  import * as _supabase_supabase_js from '@supabase/supabase-js';
6
6
  import { SupabaseClient, User, Session } from '@supabase/supabase-js';
@@ -155,6 +155,22 @@ type CheckboxComponentProps = Omit<FormControlLabelProps, 'control' | 'label' |
155
155
  checkboxProps?: CheckboxProps;
156
156
  };
157
157
 
158
+ type ButtonComponentProps = Omit<ButtonProps, 'children'> & {
159
+ /**
160
+ * Метка кнопки. Если передана строка, она автоматически
161
+ * оборачивается в <TranslateText> для локализации.
162
+ */
163
+ label?: ReactNode;
164
+ /**
165
+ * Кастомный неймспейс для перевода (если нужен)
166
+ */
167
+ overrideNamespace?: string;
168
+ /**
169
+ * Дочерние элементы (используются, если не передан label)
170
+ */
171
+ children?: ReactNode;
172
+ };
173
+
158
174
  interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onClick'> {
159
175
  overrideNamespace?: string;
160
176
  /** Текст, який буде скопійовано в буфер обміну */
@@ -171,6 +187,21 @@ interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onCli
171
187
  onCopySuccess?: (text: string) => void;
172
188
  }
173
189
 
190
+ interface RefreshButtonComponentProps {
191
+ overrideNamespace?: string;
192
+ size?: 'small' | 'medium' | 'large';
193
+ color?: "success" | "error" | "info" | "warning";
194
+ onClick?: (event: React__default.MouseEvent<HTMLButtonElement>) => void | Promise<void>;
195
+ disabled?: boolean;
196
+ fullWidth?: boolean;
197
+ loading?: boolean;
198
+ tooltip?: ReactNode;
199
+ mobileViewOnly?: boolean;
200
+ disableMobileView?: boolean;
201
+ hideTooltipOnMobile?: boolean;
202
+ hideTooltipOnDesktop?: boolean;
203
+ }
204
+
174
205
  interface TranslatableTooltipComponentProps extends Omit<TooltipProps, 'children'> {
175
206
  overrideNamespace?: string;
176
207
  disableSpan?: boolean;
@@ -384,6 +415,15 @@ type CollapsedWidgetContainerProps = {
384
415
  onExpanded?: (expanded: boolean) => void;
385
416
  };
386
417
 
418
+ interface ErrorAlertWidgetProps {
419
+ overrideNamespace?: string;
420
+ title?: ReactNode;
421
+ message: ReactNode;
422
+ onRetry?: () => void;
423
+ retryText?: ReactNode;
424
+ isRetrying?: boolean;
425
+ }
426
+
387
427
  declare const UI: {
388
428
  Inputs: {
389
429
  TextField: React$1.FC<TextFieldComponentProps>;
@@ -396,7 +436,9 @@ declare const UI: {
396
436
  Url: typeof UrlComponent;
397
437
  };
398
438
  Buttons: {
439
+ ButtonComponent: React$1.ForwardRefExoticComponent<Omit<ButtonComponentProps, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
399
440
  CopyClipboardButton: React$1.FC<CopyClipboardButtonComponentProps>;
441
+ RefreshButton: React$1.FC<RefreshButtonComponentProps>;
400
442
  };
401
443
  DataDisplay: {
402
444
  TranslatableTooltip: React$1.FC<TranslatableTooltipComponentProps>;
@@ -416,6 +458,9 @@ declare const UI: {
416
458
  PageLinkWidget: React$1.FC<PageLinkWidgetProps>;
417
459
  CollapsedWidgetContainer: (props: React$1.PropsWithChildren<CollapsedWidgetContainerProps>) => React$1.JSX.Element;
418
460
  };
461
+ Misc: {
462
+ ErrorAlertWidget: React$1.FC<ErrorAlertWidgetProps>;
463
+ };
419
464
  };
420
465
  };
421
466
 
@@ -763,6 +808,10 @@ declare const Hooks: {
763
808
 
764
809
  declare const Utils: {
765
810
  readonly getDeviceId: () => string;
811
+ readonly Sessions: {
812
+ readonly notifySessionChange: () => void;
813
+ readonly subscribeToSessionChanges: (callback: () => void) => () => void;
814
+ };
766
815
  };
767
816
 
768
- export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type CheckboxComponentProps, type CollapsedWidgetContainerProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, type PageLink, type PageLinkWidgetProps, Providers, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type SwitchComponentProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
817
+ export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ButtonComponentProps, type CheckboxComponentProps, type CollapsedWidgetContainerProps, type CompanyMember, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ErrorAlertWidgetProps, type ExpandableNoteComponentProps, type FullCompanyMemberItem, Hooks, type Language, LocalizationProvider, type Membership, type MembershipRole, type MyAvatarComponentProps, type NumberInputComponentProps, type PageLink, type PageLinkWidgetProps, Providers, type RefreshButtonComponentProps, type SaveCompanyUserPayload, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type SwitchComponentProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserProfile, type UserRoleChipComponentProps, type UserSessionItem, type UserSettings, UserSettingsProvider, type UserStatusChipComponentProps, type UserStatusType, Utils, defaultUserSettings, initI18n, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
package/dist/index.js CHANGED
@@ -2619,7 +2619,7 @@ var init_UserPopoverComponent = __esm({
2619
2619
  }
2620
2620
  };
2621
2621
  loadStatus();
2622
- const channel = supabase.channel(`user_status_popover_${userId}`).on(
2622
+ const channel2 = supabase.channel(`user_status_popover_${userId}`).on(
2623
2623
  "postgres_changes",
2624
2624
  {
2625
2625
  event: "*",
@@ -2633,7 +2633,7 @@ var init_UserPopoverComponent = __esm({
2633
2633
  ).subscribe();
2634
2634
  return () => {
2635
2635
  isMounted = false;
2636
- supabase.removeChannel(channel);
2636
+ supabase.removeChannel(channel2);
2637
2637
  };
2638
2638
  }, [userId, open]);
2639
2639
  const isOnline = Boolean(
@@ -3096,7 +3096,7 @@ var TextFieldComponent = ({
3096
3096
  ...slotProps?.input || {},
3097
3097
  readOnly: isReadOnly,
3098
3098
  endAdornment: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_material4.InputAdornment, { position: "end", sx: { gap: 0.5 }, children: [
3099
- hasValue && !isLocked && !disableClearButton && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace, children: clearTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3099
+ hasValue && !isLocked && !disableClearButton && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: clearTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3100
3100
  import_material4.IconButton,
3101
3101
  {
3102
3102
  size: "small",
@@ -3106,7 +3106,7 @@ var TextFieldComponent = ({
3106
3106
  children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_Clear.default, { fontSize: "small" })
3107
3107
  }
3108
3108
  ) }),
3109
- hasValue && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace, children: copied ? copiedTooltip : copyTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3109
+ hasValue && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: copied ? copiedTooltip : copyTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3110
3110
  import_material4.IconButton,
3111
3111
  {
3112
3112
  size: "small",
@@ -3156,7 +3156,7 @@ var TextFieldComponent = ({
3156
3156
  )
3157
3157
  }
3158
3158
  ) }),
3159
- isLocked && showLock && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace, children: lockTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3159
+ isLocked && showLock && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: lockTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3160
3160
  import_material4.IconButton,
3161
3161
  {
3162
3162
  size: "small",
@@ -4834,7 +4834,7 @@ var CollapsedWidgetContainer = (props) => {
4834
4834
  {
4835
4835
  sx: { flexGrow: 1 },
4836
4836
  avatar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_material24.Avatar, { sx: { bgcolor: "primary.main" }, children: props.icon }),
4837
- label: typeof props.title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_material24.Typography, { variant: "subtitle1", sx: { fontWeight: "700" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.title }) }) : props.title,
4837
+ label: typeof props.title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.title }) : props.title,
4838
4838
  subheader: typeof props.subtitle === "string" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.subtitle }) : props.subtitle
4839
4839
  }
4840
4840
  ),
@@ -4856,6 +4856,281 @@ var CollapsedWidgetContainer = (props) => {
4856
4856
  ] });
4857
4857
  };
4858
4858
 
4859
+ // src/UI/components/buttons/RefreshButtonComponent.tsx
4860
+ var import_react30 = require("react");
4861
+ var import_material25 = require("@mui/material");
4862
+ var import_Refresh = __toESM(require("@mui/icons-material/Refresh"));
4863
+ init_context();
4864
+ init_TranslatableTooltipComponent();
4865
+ var import_jsx_runtime35 = require("react/jsx-runtime");
4866
+ var AnimatedRefreshIcon = (0, import_material25.styled)(import_Refresh.default, {
4867
+ shouldForwardProp: (prop) => prop !== "isSpinning"
4868
+ })(({ isSpinning }) => ({
4869
+ animation: isSpinning ? "spin 1s linear infinite" : "none",
4870
+ "@keyframes spin": {
4871
+ "0%": {
4872
+ transform: "rotate(0deg)"
4873
+ },
4874
+ "100%": {
4875
+ transform: "rotate(360deg)"
4876
+ }
4877
+ }
4878
+ }));
4879
+ var RefreshButtonComponent = ({
4880
+ overrideNamespace,
4881
+ size = "small",
4882
+ onClick,
4883
+ disabled = false,
4884
+ fullWidth = false,
4885
+ loading: externalLoading,
4886
+ tooltip,
4887
+ mobileViewOnly,
4888
+ disableMobileView,
4889
+ hideTooltipOnMobile,
4890
+ hideTooltipOnDesktop
4891
+ }) => {
4892
+ const { displayState } = useAppTheme();
4893
+ const [internalLoading, setInternalLoading] = (0, import_react30.useState)(false);
4894
+ const isLoading = externalLoading !== void 0 ? externalLoading : internalLoading;
4895
+ const handleClick = async (event) => {
4896
+ if (!onClick || isLoading || disabled) return;
4897
+ try {
4898
+ setInternalLoading(true);
4899
+ await onClick(event);
4900
+ } finally {
4901
+ setInternalLoading(false);
4902
+ }
4903
+ };
4904
+ const renderIcon = () => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(AnimatedRefreshIcon, { fontSize: size, isSpinning: isLoading });
4905
+ if (displayState.isMobile && !disableMobileView || mobileViewOnly) {
4906
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TranslatableTooltipComponent, { title: hideTooltipOnMobile ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, {}) : tooltip || /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" }), children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4907
+ import_material25.Fab,
4908
+ {
4909
+ size,
4910
+ color: "inherit",
4911
+ onClick: handleClick,
4912
+ disabled: disabled || isLoading,
4913
+ "aria-label": "refresh",
4914
+ children: renderIcon()
4915
+ }
4916
+ ) }) });
4917
+ }
4918
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TranslatableTooltipComponent, { title: hideTooltipOnDesktop ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, {}) : tooltip || /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" }), children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4919
+ import_material25.Button,
4920
+ {
4921
+ variant: "contained",
4922
+ color: "inherit",
4923
+ size,
4924
+ onClick: handleClick,
4925
+ disabled: disabled || isLoading,
4926
+ fullWidth,
4927
+ startIcon: renderIcon(),
4928
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" })
4929
+ }
4930
+ ) });
4931
+ };
4932
+
4933
+ // src/UI/widgets/misc/ErrorAlertWidget.tsx
4934
+ var import_material26 = require("@mui/material");
4935
+ var import_Replay = __toESM(require("@mui/icons-material/Replay"));
4936
+ init_context();
4937
+ var import_jsx_runtime36 = require("react/jsx-runtime");
4938
+ var ErrorIllustration = ({ size = 64 }) => {
4939
+ const theme = (0, import_material26.useTheme)();
4940
+ const mainColor = theme.palette.error.main;
4941
+ const lightColor = theme.palette.error.light;
4942
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4943
+ import_material26.Box,
4944
+ {
4945
+ sx: {
4946
+ display: "flex",
4947
+ alignItems: "center",
4948
+ justifyContent: "center",
4949
+ flexShrink: 0
4950
+ },
4951
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4952
+ "svg",
4953
+ {
4954
+ width: size,
4955
+ height: size,
4956
+ viewBox: "0 0 100 100",
4957
+ fill: "none",
4958
+ xmlns: "http://www.w3.org/2000/svg",
4959
+ children: [
4960
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4961
+ "circle",
4962
+ {
4963
+ cx: "50",
4964
+ cy: "50",
4965
+ r: "42",
4966
+ fill: lightColor,
4967
+ fillOpacity: "0.25",
4968
+ children: [
4969
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4970
+ "animate",
4971
+ {
4972
+ attributeName: "r",
4973
+ values: "38;44;38",
4974
+ dur: "3s",
4975
+ repeatCount: "indefinite"
4976
+ }
4977
+ ),
4978
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4979
+ "animate",
4980
+ {
4981
+ attributeName: "fill-opacity",
4982
+ values: "0.2;0.4;0.2",
4983
+ dur: "3s",
4984
+ repeatCount: "indefinite"
4985
+ }
4986
+ )
4987
+ ]
4988
+ }
4989
+ ),
4990
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "50", cy: "50", r: "34", fill: lightColor, fillOpacity: "0.35" }),
4991
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4992
+ "path",
4993
+ {
4994
+ d: "M50 20L80 72H20L50 20Z",
4995
+ fill: mainColor,
4996
+ stroke: theme.palette.background.paper,
4997
+ strokeWidth: "3",
4998
+ strokeLinejoin: "round"
4999
+ }
5000
+ ),
5001
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5002
+ "path",
5003
+ {
5004
+ d: "M50 36V54",
5005
+ stroke: "#FFFFFF",
5006
+ strokeWidth: "4",
5007
+ strokeLinecap: "round"
5008
+ }
5009
+ ),
5010
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "50", cy: "62", r: "2.5", fill: "#FFFFFF" }),
5011
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "16", cy: "30", r: "3", fill: mainColor, opacity: "0.4" }),
5012
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "84", cy: "30", r: "2", fill: mainColor, opacity: "0.6" }),
5013
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "88", cy: "68", r: "3", fill: mainColor, opacity: "0.3" })
5014
+ ]
5015
+ }
5016
+ )
5017
+ }
5018
+ );
5019
+ };
5020
+ var ErrorAlertWidget = ({
5021
+ overrideNamespace,
5022
+ title = "An error occurred",
5023
+ message,
5024
+ onRetry,
5025
+ retryText = "Retry",
5026
+ isRetrying = false
5027
+ }) => {
5028
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5029
+ import_material26.Alert,
5030
+ {
5031
+ severity: "error",
5032
+ icon: false,
5033
+ sx: {
5034
+ borderRadius: 1,
5035
+ p: 2.5,
5036
+ m: 3,
5037
+ border: "1px solid",
5038
+ borderColor: "error.light",
5039
+ bgcolor: (theme) => theme.palette.mode === "dark" ? "rgba(211, 47, 47, 0.08)" : "rgba(211, 47, 47, 0.04)",
5040
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.05)",
5041
+ "& .MuiAlert-message": {
5042
+ width: "100%",
5043
+ p: 0
5044
+ }
5045
+ },
5046
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
5047
+ import_material26.Box,
5048
+ {
5049
+ sx: {
5050
+ display: "flex",
5051
+ flexDirection: { xs: "column", sm: "row" },
5052
+ alignItems: { xs: "flex-start", sm: "center" },
5053
+ gap: 2
5054
+ },
5055
+ children: [
5056
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ErrorIllustration, { size: 68 }),
5057
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material26.Box, { sx: { flexGrow: 1 }, children: [
5058
+ typeof title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5059
+ import_material26.Typography,
5060
+ {
5061
+ variant: "subtitle1",
5062
+ sx: { fontWeight: 600, color: "error.main", mb: 0.5 },
5063
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TranslateText, { overrideNamespace, children: title })
5064
+ }
5065
+ ) : title,
5066
+ typeof message === "string" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material26.Typography, { variant: "body2", color: "text.secondary", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TranslateText, { overrideNamespace, children: message }) }) : message
5067
+ ] }),
5068
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5069
+ import_material26.Box,
5070
+ {
5071
+ sx: {
5072
+ alignSelf: { xs: "flex-end", sm: "center" },
5073
+ mt: { xs: 1, sm: 0 }
5074
+ },
5075
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5076
+ import_material26.Button,
5077
+ {
5078
+ variant: "outlined",
5079
+ color: "error",
5080
+ size: "small",
5081
+ disabled: isRetrying,
5082
+ onClick: onRetry,
5083
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5084
+ import_Replay.default,
5085
+ {
5086
+ sx: {
5087
+ animation: isRetrying ? "spin 1s linear infinite" : "none",
5088
+ "@keyframes spin": {
5089
+ "0%": { transform: "rotate(0deg)" },
5090
+ "100%": { transform: "rotate(360deg)" }
5091
+ }
5092
+ }
5093
+ }
5094
+ ),
5095
+ sx: {
5096
+ //borderRadius: 2,
5097
+ textTransform: "none",
5098
+ fontWeight: 600,
5099
+ px: 2,
5100
+ py: 0.75,
5101
+ whiteSpace: "nowrap"
5102
+ },
5103
+ children: retryText
5104
+ }
5105
+ )
5106
+ }
5107
+ )
5108
+ ]
5109
+ }
5110
+ )
5111
+ }
5112
+ );
5113
+ };
5114
+
5115
+ // src/UI/components/buttons/ButtonComponent.tsx
5116
+ var import_react31 = require("react");
5117
+ var import_material27 = require("@mui/material");
5118
+ init_context();
5119
+ var import_jsx_runtime37 = require("react/jsx-runtime");
5120
+ var ButtonComponent = (0, import_react31.forwardRef)(
5121
+ ({ label, children, overrideNamespace, ...props }, ref) => {
5122
+ const renderContent = (content) => {
5123
+ if (typeof content === "string") {
5124
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(TranslateText, { overrideNamespace, children: content });
5125
+ }
5126
+ return content;
5127
+ };
5128
+ const contentToRender = label !== void 0 ? label : children;
5129
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_material27.Button, { ref, ...props, children: renderContent(contentToRender) });
5130
+ }
5131
+ );
5132
+ ButtonComponent.displayName = "ButtonComponent";
5133
+
4859
5134
  // src/UI/index.ts
4860
5135
  var UI = {
4861
5136
  Inputs: {
@@ -4869,7 +5144,9 @@ var UI = {
4869
5144
  Url: UrlComponent
4870
5145
  },
4871
5146
  Buttons: {
4872
- CopyClipboardButton: CopyClipboardButtonComponent
5147
+ ButtonComponent,
5148
+ CopyClipboardButton: CopyClipboardButtonComponent,
5149
+ RefreshButton: RefreshButtonComponent
4873
5150
  },
4874
5151
  DataDisplay: {
4875
5152
  TranslatableTooltip: TranslatableTooltipComponent,
@@ -4891,6 +5168,9 @@ var UI = {
4891
5168
  Pages: {
4892
5169
  PageLinkWidget,
4893
5170
  CollapsedWidgetContainer
5171
+ },
5172
+ Misc: {
5173
+ ErrorAlertWidget
4894
5174
  }
4895
5175
  }
4896
5176
  };
@@ -4918,16 +5198,16 @@ var Services = {
4918
5198
  };
4919
5199
 
4920
5200
  // src/hooks/useUserStatus.ts
4921
- var import_react30 = require("react");
5201
+ var import_react32 = require("react");
4922
5202
  init_deviceId();
4923
5203
  init_context();
4924
5204
  var ONLINE_THRESHOLD_MINUTES = 2;
4925
5205
  var AWAY_THRESHOLD_MINUTES = 15;
4926
5206
  var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
4927
5207
  const supabase = useSupabase();
4928
- const [status, setStatus] = (0, import_react30.useState)("offline");
4929
- const [lastSeen, setLastSeen] = (0, import_react30.useState)(initialLastSeenAt ?? null);
4930
- const lastSeenRef = (0, import_react30.useRef)(initialLastSeenAt ?? null);
5208
+ const [status, setStatus] = (0, import_react32.useState)("offline");
5209
+ const [lastSeen, setLastSeen] = (0, import_react32.useState)(initialLastSeenAt ?? null);
5210
+ const lastSeenRef = (0, import_react32.useRef)(initialLastSeenAt ?? null);
4931
5211
  lastSeenRef.current = lastSeen;
4932
5212
  const calculateStatus = (isOnline, lastSeenIso) => {
4933
5213
  if (isOnline) return "online";
@@ -4943,7 +5223,7 @@ var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
4943
5223
  }
4944
5224
  return "offline";
4945
5225
  };
4946
- (0, import_react30.useEffect)(() => {
5226
+ (0, import_react32.useEffect)(() => {
4947
5227
  if (!userId) return;
4948
5228
  let isMounted = true;
4949
5229
  const isSelf = currentAuthUserId && userId === currentAuthUserId;
@@ -4966,9 +5246,9 @@ var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
4966
5246
  }
4967
5247
  };
4968
5248
  fetchLastSeen();
4969
- const channel = supabase.channel(`presence_user_${userId}`);
4970
- channel.on("presence", { event: "sync" }, () => {
4971
- const state = channel.presenceState();
5249
+ const channel2 = supabase.channel(`presence_user_${userId}`);
5250
+ channel2.on("presence", { event: "sync" }, () => {
5251
+ const state = channel2.presenceState();
4972
5252
  const isOnline = Object.keys(state).length > 0;
4973
5253
  if (isMounted) {
4974
5254
  setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
@@ -4998,7 +5278,7 @@ var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
4998
5278
  ).subscribe();
4999
5279
  return () => {
5000
5280
  isMounted = false;
5001
- supabase.removeChannel(channel);
5281
+ supabase.removeChannel(channel2);
5002
5282
  };
5003
5283
  }, [userId, initialLastSeenAt, currentAuthUserId]);
5004
5284
  return {
@@ -5016,8 +5296,31 @@ var Hooks = {
5016
5296
 
5017
5297
  // src/utils/index.ts
5018
5298
  init_deviceId();
5299
+
5300
+ // src/utils/session.events.ts
5301
+ var channel = typeof window !== "undefined" ? new BroadcastChannel("session_activity") : null;
5302
+ var notifySessionChange = () => {
5303
+ channel?.postMessage("SESSION_UPDATED");
5304
+ };
5305
+ var subscribeToSessionChanges = (callback) => {
5306
+ if (!channel) return () => {
5307
+ };
5308
+ const handleMessage = (event) => {
5309
+ if (event.data === "SESSION_UPDATED") {
5310
+ callback();
5311
+ }
5312
+ };
5313
+ channel.addEventListener("message", handleMessage);
5314
+ return () => channel.removeEventListener("message", handleMessage);
5315
+ };
5316
+
5317
+ // src/utils/index.ts
5019
5318
  var Utils = {
5020
- getDeviceId
5319
+ getDeviceId,
5320
+ Sessions: {
5321
+ notifySessionChange,
5322
+ subscribeToSessionChanges
5323
+ }
5021
5324
  };
5022
5325
  // Annotate the CommonJS export names for ESM import in node:
5023
5326
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -156,7 +156,7 @@ var TextFieldComponent = ({
156
156
  ...slotProps?.input || {},
157
157
  readOnly: isReadOnly,
158
158
  endAdornment: /* @__PURE__ */ jsxs(InputAdornment, { position: "end", sx: { gap: 0.5 }, children: [
159
- hasValue && !isLocked && !disableClearButton && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace, children: clearTooltip }), children: /* @__PURE__ */ jsx(
159
+ hasValue && !isLocked && !disableClearButton && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: clearTooltip }), children: /* @__PURE__ */ jsx(
160
160
  IconButton,
161
161
  {
162
162
  size: "small",
@@ -166,7 +166,7 @@ var TextFieldComponent = ({
166
166
  children: /* @__PURE__ */ jsx(ClearIcon, { fontSize: "small" })
167
167
  }
168
168
  ) }),
169
- hasValue && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace, children: copied ? copiedTooltip : copyTooltip }), children: /* @__PURE__ */ jsx(
169
+ hasValue && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: copied ? copiedTooltip : copyTooltip }), children: /* @__PURE__ */ jsx(
170
170
  IconButton,
171
171
  {
172
172
  size: "small",
@@ -216,7 +216,7 @@ var TextFieldComponent = ({
216
216
  )
217
217
  }
218
218
  ) }),
219
- isLocked && showLock && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace, children: lockTooltip }), children: /* @__PURE__ */ jsx(
219
+ isLocked && showLock && /* @__PURE__ */ jsx(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: lockTooltip }), children: /* @__PURE__ */ jsx(
220
220
  IconButton,
221
221
  {
222
222
  size: "small",
@@ -1875,7 +1875,7 @@ var CheckboxComponent = ({
1875
1875
 
1876
1876
  // src/UI/widgets/page/CollapsedWidgetContainer.tsx
1877
1877
  import { ExpandMore as ExpandMoreIcon } from "@mui/icons-material";
1878
- import { Avatar as Avatar3, Box as Box8, Card as Card2, CardContent as CardContent2, CardHeader as CardHeader2, Collapse, Divider as Divider2, IconButton as IconButton7, styled, Tooltip as Tooltip7, Typography as Typography7 } from "@mui/material";
1878
+ import { Avatar as Avatar3, Box as Box8, Card as Card2, CardContent as CardContent2, CardHeader as CardHeader2, Collapse, Divider as Divider2, IconButton as IconButton7, styled, Tooltip as Tooltip7 } from "@mui/material";
1879
1879
  import { useState as useState11 } from "react";
1880
1880
  import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1881
1881
  var ExpandMore = styled((props) => {
@@ -1918,7 +1918,7 @@ var CollapsedWidgetContainer = (props) => {
1918
1918
  {
1919
1919
  sx: { flexGrow: 1 },
1920
1920
  avatar: /* @__PURE__ */ jsx14(Avatar3, { sx: { bgcolor: "primary.main" }, children: props.icon }),
1921
- label: typeof props.title === "string" ? /* @__PURE__ */ jsx14(Typography7, { variant: "subtitle1", sx: { fontWeight: "700" }, children: /* @__PURE__ */ jsx14(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.title }) }) : props.title,
1921
+ label: typeof props.title === "string" ? /* @__PURE__ */ jsx14(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.title }) : props.title,
1922
1922
  subheader: typeof props.subtitle === "string" ? /* @__PURE__ */ jsx14(TranslateText, { overrideNamespace: props.overrideNamespace, children: props.subtitle }) : props.subtitle
1923
1923
  }
1924
1924
  ),
@@ -1940,6 +1940,281 @@ var CollapsedWidgetContainer = (props) => {
1940
1940
  ] });
1941
1941
  };
1942
1942
 
1943
+ // src/UI/components/buttons/RefreshButtonComponent.tsx
1944
+ import { useState as useState12 } from "react";
1945
+ import {
1946
+ Button as Button3,
1947
+ Fab,
1948
+ styled as styled2
1949
+ } from "@mui/material";
1950
+ import RefreshIconMui from "@mui/icons-material/Refresh";
1951
+ import { Fragment as Fragment9, jsx as jsx15 } from "react/jsx-runtime";
1952
+ var AnimatedRefreshIcon = styled2(RefreshIconMui, {
1953
+ shouldForwardProp: (prop) => prop !== "isSpinning"
1954
+ })(({ isSpinning }) => ({
1955
+ animation: isSpinning ? "spin 1s linear infinite" : "none",
1956
+ "@keyframes spin": {
1957
+ "0%": {
1958
+ transform: "rotate(0deg)"
1959
+ },
1960
+ "100%": {
1961
+ transform: "rotate(360deg)"
1962
+ }
1963
+ }
1964
+ }));
1965
+ var RefreshButtonComponent = ({
1966
+ overrideNamespace,
1967
+ size = "small",
1968
+ onClick,
1969
+ disabled = false,
1970
+ fullWidth = false,
1971
+ loading: externalLoading,
1972
+ tooltip,
1973
+ mobileViewOnly,
1974
+ disableMobileView,
1975
+ hideTooltipOnMobile,
1976
+ hideTooltipOnDesktop
1977
+ }) => {
1978
+ const { displayState } = useAppTheme();
1979
+ const [internalLoading, setInternalLoading] = useState12(false);
1980
+ const isLoading = externalLoading !== void 0 ? externalLoading : internalLoading;
1981
+ const handleClick = async (event) => {
1982
+ if (!onClick || isLoading || disabled) return;
1983
+ try {
1984
+ setInternalLoading(true);
1985
+ await onClick(event);
1986
+ } finally {
1987
+ setInternalLoading(false);
1988
+ }
1989
+ };
1990
+ const renderIcon = () => /* @__PURE__ */ jsx15(AnimatedRefreshIcon, { fontSize: size, isSpinning: isLoading });
1991
+ if (displayState.isMobile && !disableMobileView || mobileViewOnly) {
1992
+ return /* @__PURE__ */ jsx15(TranslatableTooltipComponent, { title: hideTooltipOnMobile ? /* @__PURE__ */ jsx15(Fragment9, {}) : tooltip || /* @__PURE__ */ jsx15(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" }), children: /* @__PURE__ */ jsx15("span", { children: /* @__PURE__ */ jsx15(
1993
+ Fab,
1994
+ {
1995
+ size,
1996
+ color: "inherit",
1997
+ onClick: handleClick,
1998
+ disabled: disabled || isLoading,
1999
+ "aria-label": "refresh",
2000
+ children: renderIcon()
2001
+ }
2002
+ ) }) });
2003
+ }
2004
+ return /* @__PURE__ */ jsx15(TranslatableTooltipComponent, { title: hideTooltipOnDesktop ? /* @__PURE__ */ jsx15(Fragment9, {}) : tooltip || /* @__PURE__ */ jsx15(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" }), children: /* @__PURE__ */ jsx15(
2005
+ Button3,
2006
+ {
2007
+ variant: "contained",
2008
+ color: "inherit",
2009
+ size,
2010
+ onClick: handleClick,
2011
+ disabled: disabled || isLoading,
2012
+ fullWidth,
2013
+ startIcon: renderIcon(),
2014
+ children: /* @__PURE__ */ jsx15(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Refresh" })
2015
+ }
2016
+ ) });
2017
+ };
2018
+
2019
+ // src/UI/widgets/misc/ErrorAlertWidget.tsx
2020
+ import { Alert, Box as Box9, Button as Button4, Typography as Typography8, useTheme } from "@mui/material";
2021
+ import ReplayIcon from "@mui/icons-material/Replay";
2022
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
2023
+ var ErrorIllustration = ({ size = 64 }) => {
2024
+ const theme = useTheme();
2025
+ const mainColor = theme.palette.error.main;
2026
+ const lightColor = theme.palette.error.light;
2027
+ return /* @__PURE__ */ jsx16(
2028
+ Box9,
2029
+ {
2030
+ sx: {
2031
+ display: "flex",
2032
+ alignItems: "center",
2033
+ justifyContent: "center",
2034
+ flexShrink: 0
2035
+ },
2036
+ children: /* @__PURE__ */ jsxs12(
2037
+ "svg",
2038
+ {
2039
+ width: size,
2040
+ height: size,
2041
+ viewBox: "0 0 100 100",
2042
+ fill: "none",
2043
+ xmlns: "http://www.w3.org/2000/svg",
2044
+ children: [
2045
+ /* @__PURE__ */ jsxs12(
2046
+ "circle",
2047
+ {
2048
+ cx: "50",
2049
+ cy: "50",
2050
+ r: "42",
2051
+ fill: lightColor,
2052
+ fillOpacity: "0.25",
2053
+ children: [
2054
+ /* @__PURE__ */ jsx16(
2055
+ "animate",
2056
+ {
2057
+ attributeName: "r",
2058
+ values: "38;44;38",
2059
+ dur: "3s",
2060
+ repeatCount: "indefinite"
2061
+ }
2062
+ ),
2063
+ /* @__PURE__ */ jsx16(
2064
+ "animate",
2065
+ {
2066
+ attributeName: "fill-opacity",
2067
+ values: "0.2;0.4;0.2",
2068
+ dur: "3s",
2069
+ repeatCount: "indefinite"
2070
+ }
2071
+ )
2072
+ ]
2073
+ }
2074
+ ),
2075
+ /* @__PURE__ */ jsx16("circle", { cx: "50", cy: "50", r: "34", fill: lightColor, fillOpacity: "0.35" }),
2076
+ /* @__PURE__ */ jsx16(
2077
+ "path",
2078
+ {
2079
+ d: "M50 20L80 72H20L50 20Z",
2080
+ fill: mainColor,
2081
+ stroke: theme.palette.background.paper,
2082
+ strokeWidth: "3",
2083
+ strokeLinejoin: "round"
2084
+ }
2085
+ ),
2086
+ /* @__PURE__ */ jsx16(
2087
+ "path",
2088
+ {
2089
+ d: "M50 36V54",
2090
+ stroke: "#FFFFFF",
2091
+ strokeWidth: "4",
2092
+ strokeLinecap: "round"
2093
+ }
2094
+ ),
2095
+ /* @__PURE__ */ jsx16("circle", { cx: "50", cy: "62", r: "2.5", fill: "#FFFFFF" }),
2096
+ /* @__PURE__ */ jsx16("circle", { cx: "16", cy: "30", r: "3", fill: mainColor, opacity: "0.4" }),
2097
+ /* @__PURE__ */ jsx16("circle", { cx: "84", cy: "30", r: "2", fill: mainColor, opacity: "0.6" }),
2098
+ /* @__PURE__ */ jsx16("circle", { cx: "88", cy: "68", r: "3", fill: mainColor, opacity: "0.3" })
2099
+ ]
2100
+ }
2101
+ )
2102
+ }
2103
+ );
2104
+ };
2105
+ var ErrorAlertWidget = ({
2106
+ overrideNamespace,
2107
+ title = "An error occurred",
2108
+ message,
2109
+ onRetry,
2110
+ retryText = "Retry",
2111
+ isRetrying = false
2112
+ }) => {
2113
+ return /* @__PURE__ */ jsx16(
2114
+ Alert,
2115
+ {
2116
+ severity: "error",
2117
+ icon: false,
2118
+ sx: {
2119
+ borderRadius: 1,
2120
+ p: 2.5,
2121
+ m: 3,
2122
+ border: "1px solid",
2123
+ borderColor: "error.light",
2124
+ bgcolor: (theme) => theme.palette.mode === "dark" ? "rgba(211, 47, 47, 0.08)" : "rgba(211, 47, 47, 0.04)",
2125
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.05)",
2126
+ "& .MuiAlert-message": {
2127
+ width: "100%",
2128
+ p: 0
2129
+ }
2130
+ },
2131
+ children: /* @__PURE__ */ jsxs12(
2132
+ Box9,
2133
+ {
2134
+ sx: {
2135
+ display: "flex",
2136
+ flexDirection: { xs: "column", sm: "row" },
2137
+ alignItems: { xs: "flex-start", sm: "center" },
2138
+ gap: 2
2139
+ },
2140
+ children: [
2141
+ /* @__PURE__ */ jsx16(ErrorIllustration, { size: 68 }),
2142
+ /* @__PURE__ */ jsxs12(Box9, { sx: { flexGrow: 1 }, children: [
2143
+ typeof title === "string" ? /* @__PURE__ */ jsx16(
2144
+ Typography8,
2145
+ {
2146
+ variant: "subtitle1",
2147
+ sx: { fontWeight: 600, color: "error.main", mb: 0.5 },
2148
+ children: /* @__PURE__ */ jsx16(TranslateText, { overrideNamespace, children: title })
2149
+ }
2150
+ ) : title,
2151
+ typeof message === "string" ? /* @__PURE__ */ jsx16(Typography8, { variant: "body2", color: "text.secondary", children: /* @__PURE__ */ jsx16(TranslateText, { overrideNamespace, children: message }) }) : message
2152
+ ] }),
2153
+ onRetry && /* @__PURE__ */ jsx16(
2154
+ Box9,
2155
+ {
2156
+ sx: {
2157
+ alignSelf: { xs: "flex-end", sm: "center" },
2158
+ mt: { xs: 1, sm: 0 }
2159
+ },
2160
+ children: /* @__PURE__ */ jsx16(
2161
+ Button4,
2162
+ {
2163
+ variant: "outlined",
2164
+ color: "error",
2165
+ size: "small",
2166
+ disabled: isRetrying,
2167
+ onClick: onRetry,
2168
+ startIcon: /* @__PURE__ */ jsx16(
2169
+ ReplayIcon,
2170
+ {
2171
+ sx: {
2172
+ animation: isRetrying ? "spin 1s linear infinite" : "none",
2173
+ "@keyframes spin": {
2174
+ "0%": { transform: "rotate(0deg)" },
2175
+ "100%": { transform: "rotate(360deg)" }
2176
+ }
2177
+ }
2178
+ }
2179
+ ),
2180
+ sx: {
2181
+ //borderRadius: 2,
2182
+ textTransform: "none",
2183
+ fontWeight: 600,
2184
+ px: 2,
2185
+ py: 0.75,
2186
+ whiteSpace: "nowrap"
2187
+ },
2188
+ children: retryText
2189
+ }
2190
+ )
2191
+ }
2192
+ )
2193
+ ]
2194
+ }
2195
+ )
2196
+ }
2197
+ );
2198
+ };
2199
+
2200
+ // src/UI/components/buttons/ButtonComponent.tsx
2201
+ import { forwardRef } from "react";
2202
+ import { Button as Button5 } from "@mui/material";
2203
+ import { jsx as jsx17 } from "react/jsx-runtime";
2204
+ var ButtonComponent = forwardRef(
2205
+ ({ label, children, overrideNamespace, ...props }, ref) => {
2206
+ const renderContent = (content) => {
2207
+ if (typeof content === "string") {
2208
+ return /* @__PURE__ */ jsx17(TranslateText, { overrideNamespace, children: content });
2209
+ }
2210
+ return content;
2211
+ };
2212
+ const contentToRender = label !== void 0 ? label : children;
2213
+ return /* @__PURE__ */ jsx17(Button5, { ref, ...props, children: renderContent(contentToRender) });
2214
+ }
2215
+ );
2216
+ ButtonComponent.displayName = "ButtonComponent";
2217
+
1943
2218
  // src/UI/index.ts
1944
2219
  var UI = {
1945
2220
  Inputs: {
@@ -1953,7 +2228,9 @@ var UI = {
1953
2228
  Url: UrlComponent
1954
2229
  },
1955
2230
  Buttons: {
1956
- CopyClipboardButton: CopyClipboardButtonComponent
2231
+ ButtonComponent,
2232
+ CopyClipboardButton: CopyClipboardButtonComponent,
2233
+ RefreshButton: RefreshButtonComponent
1957
2234
  },
1958
2235
  DataDisplay: {
1959
2236
  TranslatableTooltip: TranslatableTooltipComponent,
@@ -1975,6 +2252,9 @@ var UI = {
1975
2252
  Pages: {
1976
2253
  PageLinkWidget,
1977
2254
  CollapsedWidgetContainer
2255
+ },
2256
+ Misc: {
2257
+ ErrorAlertWidget
1978
2258
  }
1979
2259
  }
1980
2260
  };
@@ -1994,13 +2274,13 @@ var Services = {
1994
2274
  };
1995
2275
 
1996
2276
  // src/hooks/useUserStatus.ts
1997
- import { useEffect as useEffect6, useRef, useState as useState12 } from "react";
2277
+ import { useEffect as useEffect6, useRef, useState as useState13 } from "react";
1998
2278
  var ONLINE_THRESHOLD_MINUTES = 2;
1999
2279
  var AWAY_THRESHOLD_MINUTES = 15;
2000
2280
  var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
2001
2281
  const supabase = useSupabase();
2002
- const [status, setStatus] = useState12("offline");
2003
- const [lastSeen, setLastSeen] = useState12(initialLastSeenAt ?? null);
2282
+ const [status, setStatus] = useState13("offline");
2283
+ const [lastSeen, setLastSeen] = useState13(initialLastSeenAt ?? null);
2004
2284
  const lastSeenRef = useRef(initialLastSeenAt ?? null);
2005
2285
  lastSeenRef.current = lastSeen;
2006
2286
  const calculateStatus = (isOnline, lastSeenIso) => {
@@ -2040,9 +2320,9 @@ var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
2040
2320
  }
2041
2321
  };
2042
2322
  fetchLastSeen();
2043
- const channel = supabase.channel(`presence_user_${userId}`);
2044
- channel.on("presence", { event: "sync" }, () => {
2045
- const state = channel.presenceState();
2323
+ const channel2 = supabase.channel(`presence_user_${userId}`);
2324
+ channel2.on("presence", { event: "sync" }, () => {
2325
+ const state = channel2.presenceState();
2046
2326
  const isOnline = Object.keys(state).length > 0;
2047
2327
  if (isMounted) {
2048
2328
  setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
@@ -2072,7 +2352,7 @@ var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
2072
2352
  ).subscribe();
2073
2353
  return () => {
2074
2354
  isMounted = false;
2075
- supabase.removeChannel(channel);
2355
+ supabase.removeChannel(channel2);
2076
2356
  };
2077
2357
  }, [userId, initialLastSeenAt, currentAuthUserId]);
2078
2358
  return {
@@ -2088,9 +2368,30 @@ var Hooks = {
2088
2368
  useUserStatus
2089
2369
  };
2090
2370
 
2371
+ // src/utils/session.events.ts
2372
+ var channel = typeof window !== "undefined" ? new BroadcastChannel("session_activity") : null;
2373
+ var notifySessionChange = () => {
2374
+ channel?.postMessage("SESSION_UPDATED");
2375
+ };
2376
+ var subscribeToSessionChanges = (callback) => {
2377
+ if (!channel) return () => {
2378
+ };
2379
+ const handleMessage = (event) => {
2380
+ if (event.data === "SESSION_UPDATED") {
2381
+ callback();
2382
+ }
2383
+ };
2384
+ channel.addEventListener("message", handleMessage);
2385
+ return () => channel.removeEventListener("message", handleMessage);
2386
+ };
2387
+
2091
2388
  // src/utils/index.ts
2092
2389
  var Utils = {
2093
- getDeviceId
2390
+ getDeviceId,
2391
+ Sessions: {
2392
+ notifySessionChange,
2393
+ subscribeToSessionChanges
2394
+ }
2094
2395
  };
2095
2396
  export {
2096
2397
  AIProvider,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serhii.olishevskyi/docs",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "description": "DOCS.UA react packages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",