@astral/ui 4.55.2 → 4.55.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/components/ConfigProvider/ConfigProvider.d.ts +2 -1
  2. package/components/ErrorBoundary/ErrorBoundary.d.ts +2 -5
  3. package/components/ErrorBoundary/ErrorBoundary.js +9 -10
  4. package/components/PageHeader/PageHeader.js +10 -3
  5. package/components/PageHeader/constants.d.ts +1 -0
  6. package/components/PageHeader/constants.js +1 -0
  7. package/components/PageHeader/styles.js +4 -0
  8. package/components/ProductSwitcher/useLogic/useLogic.js +5 -4
  9. package/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.js +2 -4
  10. package/components/fileUploading/PreviewFileUploaderFile/FilePreview/useLogic/useLogic.js +2 -4
  11. package/components/services/ErrorService/ErrorService.d.ts +15 -3
  12. package/components/services/ErrorService/ErrorService.js +7 -4
  13. package/hook-form/useFormWizard/useFormWizard.js +7 -4
  14. package/node/components/ConfigProvider/ConfigProvider.d.ts +2 -1
  15. package/node/components/ErrorBoundary/ErrorBoundary.d.ts +2 -5
  16. package/node/components/ErrorBoundary/ErrorBoundary.js +9 -10
  17. package/node/components/PageHeader/PageHeader.js +10 -3
  18. package/node/components/PageHeader/constants.d.ts +1 -0
  19. package/node/components/PageHeader/constants.js +1 -0
  20. package/node/components/PageHeader/styles.js +4 -0
  21. package/node/components/ProductSwitcher/useLogic/useLogic.js +4 -3
  22. package/node/components/fileUploading/FileUploaderFile/Actions/useLogic/useLogic.js +2 -4
  23. package/node/components/fileUploading/PreviewFileUploaderFile/FilePreview/useLogic/useLogic.js +2 -4
  24. package/node/components/services/ErrorService/ErrorService.d.ts +15 -3
  25. package/node/components/services/ErrorService/ErrorService.js +7 -4
  26. package/node/hook-form/useFormWizard/useFormWizard.js +6 -3
  27. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { type ReactElement, type ReactNode } from 'react';
2
2
  import { type LanguageMap } from '../DatePicker/types';
3
3
  import { type PlaceholderImageProps } from '../placeholders/Placeholder/Image';
4
+ import { type CaptureException } from '../services/ErrorService';
4
5
  import { type NextFeatureFlagsContextProps } from './NextFeatureFlagsContext';
5
6
  type Language = 'ru';
6
7
  type ImagesMap = {
@@ -45,7 +46,7 @@ export type ConfigContextProps = {
45
46
  * @default russianMap
46
47
  */
47
48
  datePickerLanguageMap: LanguageMap;
48
- captureException: (error: any) => void;
49
+ captureException: CaptureException;
49
50
  /**
50
51
  * Карта для типовых изображений.
51
52
  * Используется в компонентах ui-kit, где требуется отображение декоративных
@@ -1,5 +1,4 @@
1
1
  import React, { type ReactNode } from 'react';
2
- import { ConfigContext } from '../ConfigProvider';
3
2
  import { ErrorBoundaryTypeError } from './enums';
4
3
  export type State = {
5
4
  /**
@@ -23,14 +22,12 @@ type Props = {
23
22
  * @example <ErrorBoundary><InsecureComponent/></ErrorBoundary>
24
23
  */
25
24
  declare class ErrorBoundary extends React.Component<Props, State> {
26
- static contextType: React.Context<import("../ConfigProvider").ConfigContextProps>;
27
- context: React.ContextType<typeof ConfigContext>;
28
25
  state: State;
26
+ componentDidCatch(error: Error): void;
27
+ render(): React.ReactNode;
29
28
  static getDerivedStateFromError(error: Error): {
30
29
  hasError: boolean;
31
30
  typeError: ErrorBoundaryTypeError;
32
31
  };
33
- componentDidCatch(error: Error): void;
34
- render(): React.ReactNode;
35
32
  }
36
33
  export { ErrorBoundary };
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- import { ConfigContext } from '../ConfigProvider';
4
3
  import { InternalErrorPlaceholder } from '../placeholders/InternalErrorPlaceholder';
5
4
  import { OutdatedReleasePlaceholder } from '../placeholders/OutdatedReleasePlaceholder';
5
+ import { ErrorService } from '../services/ErrorService';
6
6
  import { CONDITION_TYPE_ERROR } from './constants';
7
7
  import { ErrorBoundaryTypeError } from './enums';
8
8
  /**
@@ -25,15 +25,8 @@ class ErrorBoundary extends React.Component {
25
25
  typeError: ErrorBoundaryTypeError.Default,
26
26
  };
27
27
  }
28
- static getDerivedStateFromError(error) {
29
- return {
30
- hasError: true,
31
- typeError: CONDITION_TYPE_ERROR.find(({ condition }) => condition(error))?.type ??
32
- ErrorBoundaryTypeError.Default,
33
- };
34
- }
35
28
  componentDidCatch(error) {
36
- this.context.captureException(error);
29
+ ErrorService.getInstance().captureException(error);
37
30
  }
38
31
  render() {
39
32
  if (this.state.hasError) {
@@ -41,6 +34,12 @@ class ErrorBoundary extends React.Component {
41
34
  }
42
35
  return this.props.children;
43
36
  }
37
+ static getDerivedStateFromError(error) {
38
+ return {
39
+ hasError: true,
40
+ typeError: CONDITION_TYPE_ERROR.find(({ condition }) => condition(error))?.type ??
41
+ ErrorBoundaryTypeError.Default,
42
+ };
43
+ }
44
44
  }
45
- ErrorBoundary.contextType = ConfigContext;
46
45
  export { ErrorBoundary };
@@ -7,7 +7,7 @@ import { MobilePageActions } from './MobilePageActions';
7
7
  import { MobileTitleWrapper, Wrapper } from './styles';
8
8
  import { Title } from './Title';
9
9
  import { useLogic } from './useLogic';
10
- const mobilePageHeader = cva(pageHeaderClassnames.pageHeaderMobileTitle, {
10
+ const mobilePageHeaderCva = cva(pageHeaderClassnames.pageHeaderMobileTitle, {
11
11
  variants: {
12
12
  hasTitle: {
13
13
  true: pageHeaderClassnames.hasTitle,
@@ -17,11 +17,18 @@ const mobilePageHeader = cva(pageHeaderClassnames.pageHeaderMobileTitle, {
17
17
  },
18
18
  },
19
19
  });
20
+ const rootCva = cva(pageHeaderClassnames.root, {
21
+ variants: {
22
+ hasActions: {
23
+ true: pageHeaderClassnames.hasActions,
24
+ },
25
+ },
26
+ });
20
27
  export const PageHeader = (props) => {
21
28
  const { title, description, subheader, breadcrumbs, actions, backButton, className, filters, } = props;
22
29
  const { isLoading, mobileTitleActions, isShowMobileActions } = useLogic(props);
23
- return (_jsxs(_Fragment, { children: [_jsxs(MobileTitleWrapper, { className: mobilePageHeader({
30
+ return (_jsxs(_Fragment, { children: [_jsxs(MobileTitleWrapper, { className: mobilePageHeaderCva({
24
31
  hasTitle: Boolean(title) || isLoading,
25
32
  hasBackButton: Boolean(backButton),
26
- }), children: [_jsx(Title, { backButton: backButton, title: title, isLoading: isLoading }), mobileTitleActions && mobileTitleActions] }), _jsx(Wrapper, { className: classNames(pageHeaderClassnames.root, className), children: _jsx(HeaderContent, { breadcrumbs: breadcrumbs, backButton: backButton, title: title, description: description, actions: actions, subheader: subheader, filters: filters, isLoading: isLoading }) }), isShowMobileActions && (_jsx(MobilePageActions, { className: classNames(pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, ...actions }))] }));
33
+ }), children: [_jsx(Title, { backButton: backButton, title: title, isLoading: isLoading }), mobileTitleActions && mobileTitleActions] }), _jsx(Wrapper, { className: classNames(rootCva({ hasActions: Boolean(actions) }), className), children: _jsx(HeaderContent, { breadcrumbs: breadcrumbs, backButton: backButton, title: title, description: description, actions: actions, subheader: subheader, filters: filters, isLoading: isLoading }) }), isShowMobileActions && (_jsx(MobilePageActions, { className: classNames(pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, ...actions }))] }));
27
34
  };
@@ -9,5 +9,6 @@ export declare const pageHeaderClassnames: {
9
9
  quickFilters: string;
10
10
  hasFilters: string;
11
11
  hasSubheader: string;
12
+ hasActions: string;
12
13
  };
13
14
  export declare const PAGE_HEADER_HEIGHT_MOBILE = "48px";
@@ -10,5 +10,6 @@ export const pageHeaderClassnames = {
10
10
  quickFilters: createUIKitClassname('page-header__quick-filters'),
11
11
  hasFilters: createUIKitClassname('page-header_has-filters'),
12
12
  hasSubheader: createUIKitClassname('page-header_has-subheader'),
13
+ hasActions: createUIKitClassname('page-header_has-actions'),
13
14
  };
14
15
  export const PAGE_HEADER_HEIGHT_MOBILE = '48px';
@@ -12,6 +12,10 @@ export const Wrapper = styled.header `
12
12
 
13
13
  ${({ theme }) => theme.breakpoints.down('laptop')} {
14
14
  padding: ${({ theme }) => theme.spacing(0, 4)};
15
+
16
+ &.${pageHeaderClassnames.hasActions} {
17
+ grid-template-columns: min-content 1fr auto auto;
18
+ }
15
19
  }
16
20
 
17
21
  ${({ theme }) => theme.breakpoints.down('sm')} {
@@ -1,11 +1,10 @@
1
- import { useContext, useState } from 'react';
2
- import { ConfigContext } from '../../ConfigProvider';
1
+ import { useState } from 'react';
2
+ import { ErrorService } from '../../services/ErrorService';
3
3
  import { useMenu } from '../../useMenu';
4
4
  export const useLogic = ({ getProducts, filter }) => {
5
5
  const [products, setProducts] = useState([]);
6
6
  const [isLoading, setIsLoading] = useState(false);
7
7
  const [isError, setIsError] = useState(false);
8
- const { captureException } = useContext(ConfigContext);
9
8
  const { open, anchorRef, handleOpenMenu, handleCloseMenu } = useMenu();
10
9
  const filterProductList = (productList) => {
11
10
  const { hostname } = new URL(window.origin);
@@ -32,7 +31,9 @@ export const useLogic = ({ getProducts, filter }) => {
32
31
  }
33
32
  catch (error) {
34
33
  setIsError(true);
35
- captureException(error);
34
+ ErrorService.getInstance().captureException(error, {
35
+ place: 'ProductSwitcher',
36
+ });
36
37
  }
37
38
  finally {
38
39
  setIsLoading(false);
@@ -1,11 +1,9 @@
1
- import { useContext } from 'react';
2
- import { ConfigContext } from '../../../../ConfigProvider';
1
+ import { ErrorService } from '../../../../services/ErrorService';
3
2
  import { ABORT_ERROR_MESSAGE, EXTENSIONS_IN_NEW_TAB, VIEW_NEW_TAB_ERROR_MESSAGE, } from '../../../constants';
4
3
  import { useGenerateLocalFileURL } from '../../../hooks/useGenerateLocalFileURL';
5
4
  import { MimeTypeRegistry } from '../../../services/MimeTypeRegistry';
6
5
  import { generateAttrLinkNewTab } from '../../../utils/generateAttrLinkNewTab';
7
6
  export const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }) => {
8
- const { captureException } = useContext(ConfigContext);
9
7
  const { generateUrl } = useGenerateLocalFileURL();
10
8
  const { controller } = selfFiles[fileId] || {};
11
9
  const isVisibleAbortButton = Boolean(controller);
@@ -55,7 +53,7 @@ export const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloa
55
53
  onClick: () => {
56
54
  // biome-ignore lint/suspicious/noConsole: Ошибка для интеграторов
57
55
  console.warn(VIEW_NEW_TAB_ERROR_MESSAGE);
58
- captureException(`FileId: ${fileId}: ${VIEW_NEW_TAB_ERROR_MESSAGE}`);
56
+ ErrorService.getInstance().captureCustomError('FileUploader', `FileId: ${fileId}: ${VIEW_NEW_TAB_ERROR_MESSAGE}`);
59
57
  },
60
58
  };
61
59
  };
@@ -1,11 +1,9 @@
1
- import { useContext } from 'react';
2
- import { ConfigContext } from '../../../../ConfigProvider';
1
+ import { ErrorService } from '../../../../services/ErrorService';
3
2
  import { EXTENSIONS_IN_NEW_TAB, VIEW_NEW_TAB_ERROR_MESSAGE, } from '../../../constants';
4
3
  import { useGenerateLocalFileURL } from '../../../hooks/useGenerateLocalFileURL';
5
4
  import { MimeTypeRegistry } from '../../../services/MimeTypeRegistry';
6
5
  import { generateAttrLinkNewTab } from '../../../utils/generateAttrLinkNewTab';
7
6
  export const useLogic = ({ fileId, file, fileUrl, generateDownloadLink, onDelete, onView, fileType, }) => {
8
- const { captureException } = useContext(ConfigContext);
9
7
  const { generateUrl } = useGenerateLocalFileURL();
10
8
  const isPdfFile = MimeTypeRegistry.getInstance()
11
9
  .getExtensionsByMimeType((file?.type || fileType))
@@ -48,7 +46,7 @@ export const useLogic = ({ fileId, file, fileUrl, generateDownloadLink, onDelete
48
46
  onClick: () => {
49
47
  // biome-ignore lint/suspicious/noConsole: Ошибка для интеграторов
50
48
  console.warn(VIEW_NEW_TAB_ERROR_MESSAGE);
51
- captureException(`FileId: ${fileId}: ${VIEW_NEW_TAB_ERROR_MESSAGE}`);
49
+ ErrorService.getInstance().captureCustomError('PreviewFileUploader', `FileId: ${fileId}: ${VIEW_NEW_TAB_ERROR_MESSAGE}`);
52
50
  },
53
51
  };
54
52
  };
@@ -1,3 +1,13 @@
1
+ export type CaptureException = (error: unknown, data?: {
2
+ extra?: Record<string, unknown>;
3
+ }) => void;
4
+ type ErrorExtra = {
5
+ /**
6
+ * Место, где произошла ошибка. Например, название компонента
7
+ */
8
+ place: string;
9
+ [key: string]: unknown;
10
+ };
1
11
  /**
2
12
  * Занимается логированием ошибок и отправкой их в sentry
3
13
  */
@@ -6,12 +16,14 @@ export declare class ErrorService {
6
16
  private static instance;
7
17
  private _captureException?;
8
18
  private constructor();
9
- init(captureException: (error: Error) => void): void;
10
- captureException: (error: Error) => void;
19
+ init(captureException: CaptureException): void;
20
+ captureException: (error: unknown, extra?: ErrorExtra) => void;
21
+ captureCustomError: (place: string, message: string) => void;
11
22
  /**
12
23
  * Логирует ошибку в консоль и отправляет в sentry
13
24
  * */
14
- logError: (componentName: string, message: string) => void;
25
+ logError: (place: string, message: string) => void;
15
26
  static getInstance(): ErrorService;
16
27
  private createError;
17
28
  }
29
+ export {};
@@ -4,16 +4,19 @@
4
4
  export class ErrorService {
5
5
  constructor(logger) {
6
6
  this.logger = logger;
7
- this.captureException = (error) => {
7
+ this.captureException = (error, extra) => {
8
8
  if (this._captureException) {
9
- this._captureException(error);
9
+ this._captureException(error, extra ? { extra } : undefined);
10
10
  }
11
11
  };
12
+ this.captureCustomError = (place, message) => {
13
+ this.captureException(this.createError(place, message));
14
+ };
12
15
  /**
13
16
  * Логирует ошибку в консоль и отправляет в sentry
14
17
  * */
15
- this.logError = (componentName, message) => {
16
- const error = this.createError(componentName, message);
18
+ this.logError = (place, message) => {
19
+ const error = this.createError(place, message);
17
20
  this.logger.error(error);
18
21
  this.captureException(error);
19
22
  };
@@ -1,5 +1,5 @@
1
- import { useContext, useMemo, useRef, useState } from 'react';
2
- import { ConfigContext } from '../../components/ConfigProvider';
1
+ import { useMemo, useRef, useState } from 'react';
2
+ import { ErrorService } from '../../components/services/ErrorService';
3
3
  import { useForm } from '../useForm';
4
4
  import { useFormWatchFields } from '../useFormWatchFields';
5
5
  import { CHANGE_STEP_REASON } from './constants';
@@ -20,7 +20,6 @@ import { compareSteps, getWatchFields } from './utils';
20
20
  * <FormWizard {...formWizardProps} />
21
21
  */
22
22
  export const useFormWizard = ({ initialStepId, defaultValues, isDisabled, steps, autoSaveStrategy, onChangeStep, onAutoSave, onSubmit, onAutoSaveError, }) => {
23
- const { captureException } = useContext(ConfigContext);
24
23
  const calculateInitialVisibleSteps = () => steps.filter(({ shouldSkip }) => shouldSkip?.calculate
25
24
  ? !shouldSkip.calculate(defaultValues)
26
25
  : true);
@@ -95,7 +94,11 @@ export const useFormWizard = ({ initialStepId, defaultValues, isDisabled, steps,
95
94
  setCurrentStepId(nextStepId);
96
95
  })
97
96
  .catch((error) => {
98
- captureException(error);
97
+ ErrorService.getInstance().captureException(error, {
98
+ place: 'useFormWizard',
99
+ currentStepId,
100
+ nextStepId,
101
+ });
99
102
  });
100
103
  }
101
104
  setCurrentStepId(nextStepId);
@@ -1,6 +1,7 @@
1
1
  import { type ReactElement, type ReactNode } from 'react';
2
2
  import { type LanguageMap } from '../DatePicker/types';
3
3
  import { type PlaceholderImageProps } from '../placeholders/Placeholder/Image';
4
+ import { type CaptureException } from '../services/ErrorService';
4
5
  import { type NextFeatureFlagsContextProps } from './NextFeatureFlagsContext';
5
6
  type Language = 'ru';
6
7
  type ImagesMap = {
@@ -45,7 +46,7 @@ export type ConfigContextProps = {
45
46
  * @default russianMap
46
47
  */
47
48
  datePickerLanguageMap: LanguageMap;
48
- captureException: (error: any) => void;
49
+ captureException: CaptureException;
49
50
  /**
50
51
  * Карта для типовых изображений.
51
52
  * Используется в компонентах ui-kit, где требуется отображение декоративных
@@ -1,5 +1,4 @@
1
1
  import React, { type ReactNode } from 'react';
2
- import { ConfigContext } from '../ConfigProvider';
3
2
  import { ErrorBoundaryTypeError } from './enums';
4
3
  export type State = {
5
4
  /**
@@ -23,14 +22,12 @@ type Props = {
23
22
  * @example <ErrorBoundary><InsecureComponent/></ErrorBoundary>
24
23
  */
25
24
  declare class ErrorBoundary extends React.Component<Props, State> {
26
- static contextType: React.Context<import("../ConfigProvider").ConfigContextProps>;
27
- context: React.ContextType<typeof ConfigContext>;
28
25
  state: State;
26
+ componentDidCatch(error: Error): void;
27
+ render(): React.ReactNode;
29
28
  static getDerivedStateFromError(error: Error): {
30
29
  hasError: boolean;
31
30
  typeError: ErrorBoundaryTypeError;
32
31
  };
33
- componentDidCatch(error: Error): void;
34
- render(): React.ReactNode;
35
32
  }
36
33
  export { ErrorBoundary };
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ErrorBoundary = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = __importDefault(require("react"));
9
- const ConfigProvider_1 = require("../ConfigProvider");
10
9
  const InternalErrorPlaceholder_1 = require("../placeholders/InternalErrorPlaceholder");
11
10
  const OutdatedReleasePlaceholder_1 = require("../placeholders/OutdatedReleasePlaceholder");
11
+ const ErrorService_1 = require("../services/ErrorService");
12
12
  const constants_1 = require("./constants");
13
13
  const enums_1 = require("./enums");
14
14
  /**
@@ -31,15 +31,8 @@ class ErrorBoundary extends react_1.default.Component {
31
31
  typeError: enums_1.ErrorBoundaryTypeError.Default,
32
32
  };
33
33
  }
34
- static getDerivedStateFromError(error) {
35
- return {
36
- hasError: true,
37
- typeError: constants_1.CONDITION_TYPE_ERROR.find(({ condition }) => condition(error))?.type ??
38
- enums_1.ErrorBoundaryTypeError.Default,
39
- };
40
- }
41
34
  componentDidCatch(error) {
42
- this.context.captureException(error);
35
+ ErrorService_1.ErrorService.getInstance().captureException(error);
43
36
  }
44
37
  render() {
45
38
  if (this.state.hasError) {
@@ -47,6 +40,12 @@ class ErrorBoundary extends react_1.default.Component {
47
40
  }
48
41
  return this.props.children;
49
42
  }
43
+ static getDerivedStateFromError(error) {
44
+ return {
45
+ hasError: true,
46
+ typeError: constants_1.CONDITION_TYPE_ERROR.find(({ condition }) => condition(error))?.type ??
47
+ enums_1.ErrorBoundaryTypeError.Default,
48
+ };
49
+ }
50
50
  }
51
51
  exports.ErrorBoundary = ErrorBoundary;
52
- ErrorBoundary.contextType = ConfigProvider_1.ConfigContext;
@@ -10,7 +10,7 @@ const MobilePageActions_1 = require("./MobilePageActions");
10
10
  const styles_1 = require("./styles");
11
11
  const Title_1 = require("./Title");
12
12
  const useLogic_1 = require("./useLogic");
13
- const mobilePageHeader = (0, cva_1.cva)(constants_1.pageHeaderClassnames.pageHeaderMobileTitle, {
13
+ const mobilePageHeaderCva = (0, cva_1.cva)(constants_1.pageHeaderClassnames.pageHeaderMobileTitle, {
14
14
  variants: {
15
15
  hasTitle: {
16
16
  true: constants_1.pageHeaderClassnames.hasTitle,
@@ -20,12 +20,19 @@ const mobilePageHeader = (0, cva_1.cva)(constants_1.pageHeaderClassnames.pageHea
20
20
  },
21
21
  },
22
22
  });
23
+ const rootCva = (0, cva_1.cva)(constants_1.pageHeaderClassnames.root, {
24
+ variants: {
25
+ hasActions: {
26
+ true: constants_1.pageHeaderClassnames.hasActions,
27
+ },
28
+ },
29
+ });
23
30
  const PageHeader = (props) => {
24
31
  const { title, description, subheader, breadcrumbs, actions, backButton, className, filters, } = props;
25
32
  const { isLoading, mobileTitleActions, isShowMobileActions } = (0, useLogic_1.useLogic)(props);
26
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(styles_1.MobileTitleWrapper, { className: mobilePageHeader({
33
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(styles_1.MobileTitleWrapper, { className: mobilePageHeaderCva({
27
34
  hasTitle: Boolean(title) || isLoading,
28
35
  hasBackButton: Boolean(backButton),
29
- }), children: [(0, jsx_runtime_1.jsx)(Title_1.Title, { backButton: backButton, title: title, isLoading: isLoading }), mobileTitleActions && mobileTitleActions] }), (0, jsx_runtime_1.jsx)(styles_1.Wrapper, { className: (0, classNames_1.classNames)(constants_1.pageHeaderClassnames.root, className), children: (0, jsx_runtime_1.jsx)(HeaderContent_1.HeaderContent, { breadcrumbs: breadcrumbs, backButton: backButton, title: title, description: description, actions: actions, subheader: subheader, filters: filters, isLoading: isLoading }) }), isShowMobileActions && ((0, jsx_runtime_1.jsx)(MobilePageActions_1.MobilePageActions, { className: (0, classNames_1.classNames)(constants_1.pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, ...actions }))] }));
36
+ }), children: [(0, jsx_runtime_1.jsx)(Title_1.Title, { backButton: backButton, title: title, isLoading: isLoading }), mobileTitleActions && mobileTitleActions] }), (0, jsx_runtime_1.jsx)(styles_1.Wrapper, { className: (0, classNames_1.classNames)(rootCva({ hasActions: Boolean(actions) }), className), children: (0, jsx_runtime_1.jsx)(HeaderContent_1.HeaderContent, { breadcrumbs: breadcrumbs, backButton: backButton, title: title, description: description, actions: actions, subheader: subheader, filters: filters, isLoading: isLoading }) }), isShowMobileActions && ((0, jsx_runtime_1.jsx)(MobilePageActions_1.MobilePageActions, { className: (0, classNames_1.classNames)(constants_1.pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, ...actions }))] }));
30
37
  };
31
38
  exports.PageHeader = PageHeader;
@@ -9,5 +9,6 @@ export declare const pageHeaderClassnames: {
9
9
  quickFilters: string;
10
10
  hasFilters: string;
11
11
  hasSubheader: string;
12
+ hasActions: string;
12
13
  };
13
14
  export declare const PAGE_HEADER_HEIGHT_MOBILE = "48px";
@@ -13,5 +13,6 @@ exports.pageHeaderClassnames = {
13
13
  quickFilters: (0, createUIKitClassname_1.createUIKitClassname)('page-header__quick-filters'),
14
14
  hasFilters: (0, createUIKitClassname_1.createUIKitClassname)('page-header_has-filters'),
15
15
  hasSubheader: (0, createUIKitClassname_1.createUIKitClassname)('page-header_has-subheader'),
16
+ hasActions: (0, createUIKitClassname_1.createUIKitClassname)('page-header_has-actions'),
16
17
  };
17
18
  exports.PAGE_HEADER_HEIGHT_MOBILE = '48px';
@@ -15,6 +15,10 @@ exports.Wrapper = styled_1.styled.header `
15
15
 
16
16
  ${({ theme }) => theme.breakpoints.down('laptop')} {
17
17
  padding: ${({ theme }) => theme.spacing(0, 4)};
18
+
19
+ &.${constants_1.pageHeaderClassnames.hasActions} {
20
+ grid-template-columns: min-content 1fr auto auto;
21
+ }
18
22
  }
19
23
 
20
24
  ${({ theme }) => theme.breakpoints.down('sm')} {
@@ -2,13 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useLogic = void 0;
4
4
  const react_1 = require("react");
5
- const ConfigProvider_1 = require("../../ConfigProvider");
5
+ const ErrorService_1 = require("../../services/ErrorService");
6
6
  const useMenu_1 = require("../../useMenu");
7
7
  const useLogic = ({ getProducts, filter }) => {
8
8
  const [products, setProducts] = (0, react_1.useState)([]);
9
9
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
10
10
  const [isError, setIsError] = (0, react_1.useState)(false);
11
- const { captureException } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
12
11
  const { open, anchorRef, handleOpenMenu, handleCloseMenu } = (0, useMenu_1.useMenu)();
13
12
  const filterProductList = (productList) => {
14
13
  const { hostname } = new URL(window.origin);
@@ -35,7 +34,9 @@ const useLogic = ({ getProducts, filter }) => {
35
34
  }
36
35
  catch (error) {
37
36
  setIsError(true);
38
- captureException(error);
37
+ ErrorService_1.ErrorService.getInstance().captureException(error, {
38
+ place: 'ProductSwitcher',
39
+ });
39
40
  }
40
41
  finally {
41
42
  setIsLoading(false);
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useLogic = void 0;
4
- const react_1 = require("react");
5
- const ConfigProvider_1 = require("../../../../ConfigProvider");
4
+ const ErrorService_1 = require("../../../../services/ErrorService");
6
5
  const constants_1 = require("../../../constants");
7
6
  const useGenerateLocalFileURL_1 = require("../../../hooks/useGenerateLocalFileURL");
8
7
  const MimeTypeRegistry_1 = require("../../../services/MimeTypeRegistry");
9
8
  const generateAttrLinkNewTab_1 = require("../../../utils/generateAttrLinkNewTab");
10
9
  const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink, onDelete, onRetry, onView, setErrorStatusFile, selfFiles, isLoading, isError, isDeletingFile, fileName, }) => {
11
- const { captureException } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
12
10
  const { generateUrl } = (0, useGenerateLocalFileURL_1.useGenerateLocalFileURL)();
13
11
  const { controller } = selfFiles[fileId] || {};
14
12
  const isVisibleAbortButton = Boolean(controller);
@@ -58,7 +56,7 @@ const useLogic = ({ fileId, file, fileUrl, isUploadError, generateDownloadLink,
58
56
  onClick: () => {
59
57
  // biome-ignore lint/suspicious/noConsole: Ошибка для интеграторов
60
58
  console.warn(constants_1.VIEW_NEW_TAB_ERROR_MESSAGE);
61
- captureException(`FileId: ${fileId}: ${constants_1.VIEW_NEW_TAB_ERROR_MESSAGE}`);
59
+ ErrorService_1.ErrorService.getInstance().captureCustomError('FileUploader', `FileId: ${fileId}: ${constants_1.VIEW_NEW_TAB_ERROR_MESSAGE}`);
62
60
  },
63
61
  };
64
62
  };
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useLogic = void 0;
4
- const react_1 = require("react");
5
- const ConfigProvider_1 = require("../../../../ConfigProvider");
4
+ const ErrorService_1 = require("../../../../services/ErrorService");
6
5
  const constants_1 = require("../../../constants");
7
6
  const useGenerateLocalFileURL_1 = require("../../../hooks/useGenerateLocalFileURL");
8
7
  const MimeTypeRegistry_1 = require("../../../services/MimeTypeRegistry");
9
8
  const generateAttrLinkNewTab_1 = require("../../../utils/generateAttrLinkNewTab");
10
9
  const useLogic = ({ fileId, file, fileUrl, generateDownloadLink, onDelete, onView, fileType, }) => {
11
- const { captureException } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
12
10
  const { generateUrl } = (0, useGenerateLocalFileURL_1.useGenerateLocalFileURL)();
13
11
  const isPdfFile = MimeTypeRegistry_1.MimeTypeRegistry.getInstance()
14
12
  .getExtensionsByMimeType((file?.type || fileType))
@@ -51,7 +49,7 @@ const useLogic = ({ fileId, file, fileUrl, generateDownloadLink, onDelete, onVie
51
49
  onClick: () => {
52
50
  // biome-ignore lint/suspicious/noConsole: Ошибка для интеграторов
53
51
  console.warn(constants_1.VIEW_NEW_TAB_ERROR_MESSAGE);
54
- captureException(`FileId: ${fileId}: ${constants_1.VIEW_NEW_TAB_ERROR_MESSAGE}`);
52
+ ErrorService_1.ErrorService.getInstance().captureCustomError('PreviewFileUploader', `FileId: ${fileId}: ${constants_1.VIEW_NEW_TAB_ERROR_MESSAGE}`);
55
53
  },
56
54
  };
57
55
  };
@@ -1,3 +1,13 @@
1
+ export type CaptureException = (error: unknown, data?: {
2
+ extra?: Record<string, unknown>;
3
+ }) => void;
4
+ type ErrorExtra = {
5
+ /**
6
+ * Место, где произошла ошибка. Например, название компонента
7
+ */
8
+ place: string;
9
+ [key: string]: unknown;
10
+ };
1
11
  /**
2
12
  * Занимается логированием ошибок и отправкой их в sentry
3
13
  */
@@ -6,12 +16,14 @@ export declare class ErrorService {
6
16
  private static instance;
7
17
  private _captureException?;
8
18
  private constructor();
9
- init(captureException: (error: Error) => void): void;
10
- captureException: (error: Error) => void;
19
+ init(captureException: CaptureException): void;
20
+ captureException: (error: unknown, extra?: ErrorExtra) => void;
21
+ captureCustomError: (place: string, message: string) => void;
11
22
  /**
12
23
  * Логирует ошибку в консоль и отправляет в sentry
13
24
  * */
14
- logError: (componentName: string, message: string) => void;
25
+ logError: (place: string, message: string) => void;
15
26
  static getInstance(): ErrorService;
16
27
  private createError;
17
28
  }
29
+ export {};
@@ -7,16 +7,19 @@ exports.ErrorService = void 0;
7
7
  class ErrorService {
8
8
  constructor(logger) {
9
9
  this.logger = logger;
10
- this.captureException = (error) => {
10
+ this.captureException = (error, extra) => {
11
11
  if (this._captureException) {
12
- this._captureException(error);
12
+ this._captureException(error, extra ? { extra } : undefined);
13
13
  }
14
14
  };
15
+ this.captureCustomError = (place, message) => {
16
+ this.captureException(this.createError(place, message));
17
+ };
15
18
  /**
16
19
  * Логирует ошибку в консоль и отправляет в sentry
17
20
  * */
18
- this.logError = (componentName, message) => {
19
- const error = this.createError(componentName, message);
21
+ this.logError = (place, message) => {
22
+ const error = this.createError(place, message);
20
23
  this.logger.error(error);
21
24
  this.captureException(error);
22
25
  };
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useFormWizard = void 0;
4
4
  const react_1 = require("react");
5
- const ConfigProvider_1 = require("../../components/ConfigProvider");
5
+ const ErrorService_1 = require("../../components/services/ErrorService");
6
6
  const useForm_1 = require("../useForm");
7
7
  const useFormWatchFields_1 = require("../useFormWatchFields");
8
8
  const constants_1 = require("./constants");
@@ -23,7 +23,6 @@ const utils_1 = require("./utils");
23
23
  * <FormWizard {...formWizardProps} />
24
24
  */
25
25
  const useFormWizard = ({ initialStepId, defaultValues, isDisabled, steps, autoSaveStrategy, onChangeStep, onAutoSave, onSubmit, onAutoSaveError, }) => {
26
- const { captureException } = (0, react_1.useContext)(ConfigProvider_1.ConfigContext);
27
26
  const calculateInitialVisibleSteps = () => steps.filter(({ shouldSkip }) => shouldSkip?.calculate
28
27
  ? !shouldSkip.calculate(defaultValues)
29
28
  : true);
@@ -98,7 +97,11 @@ const useFormWizard = ({ initialStepId, defaultValues, isDisabled, steps, autoSa
98
97
  setCurrentStepId(nextStepId);
99
98
  })
100
99
  .catch((error) => {
101
- captureException(error);
100
+ ErrorService_1.ErrorService.getInstance().captureException(error, {
101
+ place: 'useFormWizard',
102
+ currentStepId,
103
+ nextStepId,
104
+ });
102
105
  });
103
106
  }
104
107
  setCurrentStepId(nextStepId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astral/ui",
3
- "version": "4.55.2",
3
+ "version": "4.55.4",
4
4
  "browser": "./index.js",
5
5
  "main": "./node/index.js",
6
6
  "dependencies": {