@astral/ui 4.52.0 → 4.53.0

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 (81) hide show
  1. package/components/DashboardContext/DashboardContext.d.ts +2 -3
  2. package/components/DashboardContext/DashboardContext.js +1 -0
  3. package/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.d.ts +2 -2
  4. package/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.js +2 -1
  5. package/components/DashboardLayout/Container/Container.d.ts +6 -0
  6. package/components/DashboardLayout/Container/Container.js +24 -0
  7. package/components/DashboardLayout/Container/constants.d.ts +6 -0
  8. package/components/DashboardLayout/Container/constants.js +7 -0
  9. package/components/DashboardLayout/Container/index.d.ts +1 -0
  10. package/components/DashboardLayout/Container/index.js +1 -0
  11. package/components/DashboardLayout/Container/styles.d.ts +5 -0
  12. package/components/DashboardLayout/Container/styles.js +55 -0
  13. package/components/DashboardLayout/DashboardLayout.d.ts +1 -1
  14. package/components/DashboardLayout/DashboardLayout.js +2 -2
  15. package/components/DashboardLayout/DashboardWrapper/DashboardWrapper.js +3 -2
  16. package/components/DashboardLayout/DashboardWrapper/constants.d.ts +6 -0
  17. package/components/DashboardLayout/DashboardWrapper/constants.js +7 -0
  18. package/components/DashboardLayout/DashboardWrapper/styles.d.ts +0 -6
  19. package/components/DashboardLayout/DashboardWrapper/styles.js +0 -45
  20. package/components/DashboardLayout/Header/useLogic/useLogic.d.ts +1 -1
  21. package/components/DashboardLayout/types.d.ts +5 -0
  22. package/components/DashboardLayoutSkeleton/DashboardLayoutSkeleton.js +3 -2
  23. package/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.d.ts +2 -0
  24. package/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.js +2 -1
  25. package/components/DatePicker/hooks/useMaskedValue/useMaskedValue.d.ts +4 -0
  26. package/components/DatePicker/hooks/useMaskedValue/useMaskedValue.js +37 -8
  27. package/components/DatePicker/useLogic/useLogic.d.ts +1 -0
  28. package/components/DatePicker/useLogic/useLogic.js +19 -13
  29. package/components/DateRangePicker/useLogic/useLogic.d.ts +2 -0
  30. package/components/DateRangePicker/useLogic/useLogic.js +27 -3
  31. package/components/DateRangePicker/useLogic/utils/index.d.ts +0 -1
  32. package/components/DateRangePicker/useLogic/utils/index.js +0 -1
  33. package/components/utils/date/format/index.d.ts +1 -0
  34. package/components/utils/date/format/index.js +1 -0
  35. package/{node/components/DateRangePicker/useLogic/utils → components/utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.d.ts +1 -1
  36. package/components/utils/date/format/parseDate/parseDate.d.ts +1 -0
  37. package/components/utils/date/format/parseDate/parseDate.js +42 -13
  38. package/node/components/DashboardContext/DashboardContext.d.ts +2 -3
  39. package/node/components/DashboardContext/DashboardContext.js +1 -0
  40. package/node/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.d.ts +2 -2
  41. package/node/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.js +2 -1
  42. package/node/components/DashboardLayout/Container/Container.d.ts +6 -0
  43. package/node/components/DashboardLayout/Container/Container.js +28 -0
  44. package/node/components/DashboardLayout/Container/constants.d.ts +6 -0
  45. package/node/components/DashboardLayout/Container/constants.js +10 -0
  46. package/node/components/DashboardLayout/Container/index.d.ts +1 -0
  47. package/node/components/DashboardLayout/Container/index.js +17 -0
  48. package/node/components/DashboardLayout/Container/styles.d.ts +5 -0
  49. package/node/components/DashboardLayout/Container/styles.js +58 -0
  50. package/node/components/DashboardLayout/DashboardLayout.d.ts +1 -1
  51. package/node/components/DashboardLayout/DashboardLayout.js +2 -2
  52. package/node/components/DashboardLayout/DashboardWrapper/DashboardWrapper.js +2 -1
  53. package/node/components/DashboardLayout/DashboardWrapper/constants.d.ts +6 -0
  54. package/node/components/DashboardLayout/DashboardWrapper/constants.js +10 -0
  55. package/node/components/DashboardLayout/DashboardWrapper/styles.d.ts +0 -6
  56. package/node/components/DashboardLayout/DashboardWrapper/styles.js +4 -49
  57. package/node/components/DashboardLayout/Header/useLogic/useLogic.d.ts +1 -1
  58. package/node/components/DashboardLayout/types.d.ts +5 -0
  59. package/node/components/DashboardLayoutSkeleton/DashboardLayoutSkeleton.js +2 -1
  60. package/node/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.d.ts +2 -0
  61. package/node/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.js +2 -1
  62. package/node/components/DatePicker/hooks/useMaskedValue/useMaskedValue.d.ts +4 -0
  63. package/node/components/DatePicker/hooks/useMaskedValue/useMaskedValue.js +35 -6
  64. package/node/components/DatePicker/useLogic/useLogic.d.ts +1 -0
  65. package/node/components/DatePicker/useLogic/useLogic.js +19 -13
  66. package/node/components/DateRangePicker/useLogic/useLogic.d.ts +2 -0
  67. package/node/components/DateRangePicker/useLogic/useLogic.js +28 -4
  68. package/node/components/DateRangePicker/useLogic/utils/index.d.ts +0 -1
  69. package/node/components/DateRangePicker/useLogic/utils/index.js +0 -1
  70. package/node/components/utils/date/format/index.d.ts +1 -0
  71. package/node/components/utils/date/format/index.js +1 -0
  72. package/{components/DateRangePicker/useLogic/utils → node/components/utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.d.ts +1 -1
  73. package/node/components/utils/date/format/parseDate/parseDate.d.ts +1 -0
  74. package/node/components/utils/date/format/parseDate/parseDate.js +45 -13
  75. package/package.json +1 -1
  76. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.d.ts +0 -0
  77. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.js +0 -0
  78. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.js +0 -0
  79. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.d.ts +0 -0
  80. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.js +0 -0
  81. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.js +0 -0
@@ -1,3 +1,4 @@
1
1
  export * from './formatDate';
2
+ export * from './isMaskedDateSyntacticallyComplete';
2
3
  export * from './maskDate';
3
4
  export * from './parseDate';
@@ -1,4 +1,4 @@
1
- import { type DateMask } from '../../../../utils/date/format';
1
+ import { type DateMask } from '../maskDate';
2
2
  /**
3
3
  * Все ли части строки по маске заполнены цифрами полностью (без промежуточных состояний IMask).
4
4
  */
@@ -1,5 +1,6 @@
1
1
  import { type DateMask } from '../maskDate';
2
2
  /**
3
3
  * утилита конвертации строковой даты созданной по маске обратно в Date
4
+ * Строгий разбор UTC через `dayjs` + `customParseFormat`; при невалидной строке — Invalid Date
4
5
  */
5
6
  export declare const parseDate: (date: string, mask: DateMask, separator?: string) => Date;
@@ -1,21 +1,50 @@
1
- import { buildIsoDate, } from '../../buildIsoDate';
1
+ import dayjs from 'dayjs';
2
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
3
+ import utc from 'dayjs/plugin/utc';
2
4
  import { DateMaskElements } from '../maskDate';
3
- const orderMap = {
4
- [DateMaskElements.Year]: 'year',
5
- [DateMaskElements.Month]: 'month',
6
- [DateMaskElements.Day]: 'day',
7
- [DateMaskElements.Hour]: 'hour',
8
- [DateMaskElements.Minute]: 'minute',
9
- [DateMaskElements.Second]: 'second',
5
+ dayjs.extend(customParseFormat);
6
+ dayjs.extend(utc);
7
+ /**
8
+ * Токен маски UI → литерал формата `dayjs` (strict UTC).
9
+ * В маске час — `hh`, в дате используются сутки 0–23 как в `formatDate` (UTC), поэтому `HH`.
10
+ */
11
+ const maskElementToDayjs = {
12
+ [DateMaskElements.Day]: 'DD',
13
+ [DateMaskElements.Month]: 'MM',
14
+ [DateMaskElements.Year]: 'YYYY',
15
+ [DateMaskElements.Hour]: 'HH',
16
+ [DateMaskElements.Minute]: 'mm',
17
+ [DateMaskElements.Second]: 'ss',
18
+ };
19
+ const buildDayjsFormat = (mask, separator) => {
20
+ const parts = mask.split(separator);
21
+ const tokens = [];
22
+ for (const part of parts) {
23
+ const t = maskElementToDayjs[part];
24
+ if (t == null) {
25
+ return null;
26
+ }
27
+ tokens.push(t);
28
+ }
29
+ return tokens.join(separator);
10
30
  };
11
31
  /**
12
32
  * утилита конвертации строковой даты созданной по маске обратно в Date
33
+ * Строгий разбор UTC через `dayjs` + `customParseFormat`; при невалидной строке — Invalid Date
13
34
  */
14
35
  export const parseDate = (date, mask, separator = '.') => {
15
36
  const dateArr = date.split(separator);
16
- const options = { year: 1900 };
17
- mask.split('.').forEach((element, index) => {
18
- options[orderMap[element]] = parseInt(dateArr[index]);
19
- });
20
- return buildIsoDate(options);
37
+ const maskSplit = mask.split(separator);
38
+ if (dateArr.length !== maskSplit.length) {
39
+ return new Date(Number.NaN);
40
+ }
41
+ const format = buildDayjsFormat(mask, separator);
42
+ if (format == null) {
43
+ return new Date(Number.NaN);
44
+ }
45
+ const parsed = dayjs.utc(date, format, true);
46
+ if (!parsed.isValid()) {
47
+ return new Date(Number.NaN);
48
+ }
49
+ return parsed.toDate();
21
50
  };
@@ -1,7 +1,6 @@
1
1
  import { type RefObject } from 'react';
2
- export type DashboardContextProps = {
3
- isFocusedMode: boolean;
4
- mobileHeaderPriorityFeature: 'profile' | 'menuOrg';
2
+ import { type DashboardLayoutProps } from '../DashboardLayout';
3
+ export type DashboardContextProps = Required<Pick<DashboardLayoutProps, 'isFocusedMode' | 'mobileHeaderPriorityFeature' | 'desktopViewMode'>> & {
5
4
  setAlertElement?: (element: HTMLElement | null) => void;
6
5
  alertHeight: number;
7
6
  isLoading: boolean;
@@ -5,6 +5,7 @@ const react_1 = require("react");
5
5
  exports.DashboardContext = (0, react_1.createContext)({
6
6
  isFocusedMode: false,
7
7
  mobileHeaderPriorityFeature: 'menuOrg',
8
+ desktopViewMode: 'compact',
8
9
  alertHeight: 0,
9
10
  isLoading: false,
10
11
  hasMenuOrganizationRef: (0, react_1.createRef)(),
@@ -1,8 +1,8 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import { type DashboardContextProps } from '../DashboardContext';
3
- type Props = Pick<DashboardContextProps, 'isFocusedMode' | 'mobileHeaderPriorityFeature'> & {
3
+ type Props = Pick<DashboardContextProps, 'isFocusedMode' | 'mobileHeaderPriorityFeature' | 'desktopViewMode'> & {
4
4
  children: ReactNode;
5
5
  isLoading: boolean;
6
6
  };
7
- export declare const DashboardContextProvider: ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, }: Props) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const DashboardContextProvider: ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, desktopViewMode, }: Props) => import("react/jsx-runtime").JSX.Element;
8
8
  export {};
@@ -4,7 +4,7 @@ exports.DashboardContextProvider = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const DashboardContext_1 = require("../DashboardContext");
7
- const DashboardContextProvider = ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, }) => {
7
+ const DashboardContextProvider = ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, desktopViewMode, }) => {
8
8
  const [alertElement, setAlertElement] = (0, react_1.useState)(null);
9
9
  const [alertHeight, setAlertHeight] = (0, react_1.useState)(0);
10
10
  const [isFocusedModeInternal, setFocusedMode] = (0, react_1.useState)(isFocusedMode);
@@ -32,6 +32,7 @@ const DashboardContextProvider = ({ children, isFocusedMode, isLoading, mobileHe
32
32
  return ((0, jsx_runtime_1.jsx)(DashboardContext_1.DashboardContext.Provider, { value: {
33
33
  isFocusedMode: isFocusedModeInternal,
34
34
  mobileHeaderPriorityFeature,
35
+ desktopViewMode,
35
36
  setAlertElement,
36
37
  alertHeight,
37
38
  isLoading,
@@ -0,0 +1,6 @@
1
+ import { type ReactNode } from 'react';
2
+ type Props = {
3
+ children: ReactNode;
4
+ };
5
+ export declare const Container: ({ children }: Props) => import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Container = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const DashboardContext_1 = require("../../DashboardContext");
7
+ const cva_1 = require("../../utils/cva");
8
+ const constants_1 = require("./constants");
9
+ const styles_1 = require("./styles");
10
+ const containerCva = (0, cva_1.cva)(constants_1.containerClassnames.root, {
11
+ variants: {
12
+ desktopViewMode: {
13
+ compact: constants_1.containerClassnames.compact,
14
+ wide: constants_1.containerClassnames.wide,
15
+ },
16
+ isFocusedMode: {
17
+ true: constants_1.containerClassnames.focusedMode,
18
+ },
19
+ },
20
+ });
21
+ const Container = ({ children }) => {
22
+ const { isFocusedMode, desktopViewMode } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
23
+ return ((0, jsx_runtime_1.jsx)(styles_1.Root, { className: containerCva({
24
+ desktopViewMode,
25
+ isFocusedMode,
26
+ }), children: children }));
27
+ };
28
+ exports.Container = Container;
@@ -0,0 +1,6 @@
1
+ export declare const containerClassnames: {
2
+ root: string;
3
+ compact: string;
4
+ wide: string;
5
+ focusedMode: string;
6
+ };
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.containerClassnames = void 0;
4
+ const createUIKitClassname_1 = require("../../utils/createUIKitClassname");
5
+ exports.containerClassnames = {
6
+ root: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container'),
7
+ compact: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_compact'),
8
+ wide: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_wide'),
9
+ focusedMode: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_focused-mode'),
10
+ };
@@ -0,0 +1 @@
1
+ export * from './Container';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Container"), exports);
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export declare const Root: import("@emotion/styled/dist/declarations/src/types").StyledComponent<{
3
+ theme?: import("@emotion/react").Theme | undefined;
4
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
5
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Root = void 0;
4
+ const constants_1 = require("../../DashboardSidebar/constants");
5
+ const styled_1 = require("../../styled");
6
+ const constants_2 = require("./constants");
7
+ exports.Root = styled_1.styled.div `
8
+ display: grid;
9
+ grid-template-columns: auto 1fr;
10
+ grid-template-rows: auto auto 1fr;
11
+ flex-grow: 1;
12
+
13
+ height: 100vh;
14
+ padding: ${({ theme }) => theme.spacing(0, 4, 4)};
15
+
16
+ transition: ${({ theme }) => {
17
+ return theme.transitions.create(['max-width'], {
18
+ duration: theme.transitions.duration.complex,
19
+ });
20
+ }};
21
+
22
+ /* Причина игнора: Не критично для отображения */
23
+ /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
24
+ &:has(.${constants_1.dashboardSidebarClassnames.root}) {
25
+ column-gap: ${({ theme }) => theme.spacing(4)};
26
+
27
+ ${({ theme }) => theme.breakpoints.down('sm')} {
28
+ column-gap: 0;
29
+ }
30
+ }
31
+
32
+ /* Причина игнора: Прогрессивное улучшение */
33
+ /* stylelint-disable plugin/no-unsupported-browser-features */
34
+ @supports (height: 100dvh) {
35
+ height: 100dvh;
36
+ }
37
+ /* stylelint-enable plugin/no-unsupported-browser-features */
38
+
39
+ ${({ theme }) => theme.breakpoints.down('sm')} {
40
+ column-gap: 0;
41
+
42
+ min-width: unset;
43
+ max-width: unset;
44
+ padding: 0;
45
+ }
46
+
47
+ &.${constants_2.containerClassnames.compact} {
48
+ max-width: 1572px;
49
+ }
50
+
51
+ &.${constants_2.containerClassnames.wide} {
52
+ max-width: 1920px;
53
+ }
54
+
55
+ &.${constants_2.containerClassnames.focusedMode} {
56
+ max-width: 100%;
57
+ }
58
+ `;
@@ -4,7 +4,7 @@ import { type DashboardLayoutProps } from './types';
4
4
  * Общий Layout приложения
5
5
  */
6
6
  export declare const DashboardLayout: {
7
- ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, }: DashboardLayoutProps): import("react/jsx-runtime").JSX.Element;
7
+ ({ children, isFocusedMode, isLoading, mobileHeaderPriorityFeature, desktopViewMode, }: DashboardLayoutProps): import("react/jsx-runtime").JSX.Element;
8
8
  Header: import("react").ForwardRefExoticComponent<import("./Header").HeaderProps & import("react").RefAttributes<HTMLDivElement>>;
9
9
  Sidebar: import("react").ForwardRefExoticComponent<import("../DashboardSidebar").DashboardSidebarProps & import("react").RefAttributes<HTMLBaseElement>>;
10
10
  Main: import("react").ForwardRefExoticComponent<import("./Main").MainProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -10,8 +10,8 @@ const Main_1 = require("./Main");
10
10
  /**
11
11
  * Общий Layout приложения
12
12
  */
13
- const DashboardLayout = ({ children, isFocusedMode = false, isLoading = false, mobileHeaderPriorityFeature = 'menuOrg', }) => {
14
- return ((0, jsx_runtime_1.jsx)(DashboardContext_1.DashboardContextProvider, { isFocusedMode: isFocusedMode, isLoading: isLoading, mobileHeaderPriorityFeature: mobileHeaderPriorityFeature, children: (0, jsx_runtime_1.jsx)(DashboardWrapper_1.DashboardWrapper, { children: children }) }));
13
+ const DashboardLayout = ({ children, isFocusedMode = false, isLoading = false, mobileHeaderPriorityFeature = 'menuOrg', desktopViewMode = 'compact', }) => {
14
+ return ((0, jsx_runtime_1.jsx)(DashboardContext_1.DashboardContextProvider, { isFocusedMode: isFocusedMode, isLoading: isLoading, desktopViewMode: desktopViewMode, mobileHeaderPriorityFeature: mobileHeaderPriorityFeature, children: (0, jsx_runtime_1.jsx)(DashboardWrapper_1.DashboardWrapper, { children: children }) }));
15
15
  };
16
16
  exports.DashboardLayout = DashboardLayout;
17
17
  exports.DashboardLayout.Header = Header_1.Header;
@@ -5,10 +5,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const DashboardContext_1 = require("../../DashboardContext");
7
7
  const DashboardSidebarProvider_1 = require("../../DashboardSidebarProvider");
8
+ const Container_1 = require("../Container");
8
9
  const constants_1 = require("../constants");
9
10
  const styles_1 = require("./styles");
10
11
  const DashboardWrapper = ({ children }) => {
11
12
  const { isFocusedMode } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
12
- return ((0, jsx_runtime_1.jsx)(DashboardSidebarProvider_1.DashboardSidebarProvider, { isFocusedMode: isFocusedMode, children: (0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { className: constants_1.dashboardLayoutClassnames.root, children: [(0, jsx_runtime_1.jsx)(styles_1.DecorativeHeaderBackground, { role: "presentation", "$isFocusedMode": isFocusedMode }), (0, jsx_runtime_1.jsx)(styles_1.LayoutContent, { "$isFocusedMode": isFocusedMode, children: children })] }) }));
13
+ return ((0, jsx_runtime_1.jsx)(DashboardSidebarProvider_1.DashboardSidebarProvider, { isFocusedMode: isFocusedMode, children: (0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { className: constants_1.dashboardLayoutClassnames.root, children: [(0, jsx_runtime_1.jsx)(styles_1.DecorativeHeaderBackground, { role: "presentation", "$isFocusedMode": isFocusedMode }), (0, jsx_runtime_1.jsx)(Container_1.Container, { children: children })] }) }));
13
14
  };
14
15
  exports.DashboardWrapper = DashboardWrapper;
@@ -0,0 +1,6 @@
1
+ export declare const dashboardLayoutContainerClassnames: {
2
+ root: string;
3
+ compact: string;
4
+ wide: string;
5
+ focusedMode: string;
6
+ };
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dashboardLayoutContainerClassnames = void 0;
4
+ const createUIKitClassname_1 = require("../../utils/createUIKitClassname");
5
+ exports.dashboardLayoutContainerClassnames = {
6
+ root: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container'),
7
+ compact: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_compact'),
8
+ wide: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_wide'),
9
+ focusedMode: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout__container_focused-mode'),
10
+ };
@@ -9,9 +9,3 @@ export declare const DecorativeHeaderBackground: import("@emotion/styled/dist/de
9
9
  } & {
10
10
  $isFocusedMode: boolean;
11
11
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
12
- export declare const LayoutContent: import("@emotion/styled/dist/declarations/src/types").StyledComponent<{
13
- theme?: import("@emotion/react").Theme | undefined;
14
- as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
15
- } & {
16
- $isFocusedMode: boolean;
17
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LayoutContent = exports.DecorativeHeaderBackground = exports.Wrapper = void 0;
4
- const constants_1 = require("../../DashboardSidebar/constants");
3
+ exports.DecorativeHeaderBackground = exports.Wrapper = void 0;
5
4
  const styled_1 = require("../../styled");
6
- const constants_2 = require("../constants");
5
+ const constants_1 = require("../constants");
7
6
  exports.Wrapper = (0, styled_1.styled)('div') `
8
7
  display: flex;
9
8
  justify-content: center;
@@ -20,7 +19,7 @@ exports.DecorativeHeaderBackground = styled_1.styled.div `
20
19
  left: 0;
21
20
 
22
21
  width: 100%;
23
- height: ${({ $isFocusedMode }) => ($isFocusedMode ? 0 : constants_2.HEADER_HEIGHT_DESKTOP)};
22
+ height: ${({ $isFocusedMode }) => ($isFocusedMode ? 0 : constants_1.HEADER_HEIGHT_DESKTOP)};
24
23
 
25
24
  background-color: ${({ theme }) => theme.palette.background.default};
26
25
  border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
@@ -32,54 +31,10 @@ exports.DecorativeHeaderBackground = styled_1.styled.div `
32
31
  }};
33
32
 
34
33
  ${({ theme }) => theme.breakpoints.down('laptop')} {
35
- height: ${({ $isFocusedMode }) => ($isFocusedMode ? 0 : constants_2.HEADER_HEIGHT_LAPTOP)}
34
+ height: ${({ $isFocusedMode }) => ($isFocusedMode ? 0 : constants_1.HEADER_HEIGHT_LAPTOP)}
36
35
  }
37
36
 
38
37
  ${({ theme }) => theme.breakpoints.down('sm')} {
39
38
  display: none;
40
39
  }
41
40
  `;
42
- exports.LayoutContent = (0, styled_1.styled)('div', {
43
- shouldForwardProp: (prop) => !['$isFocusedMode'].includes(prop),
44
- }) `
45
- display: grid;
46
- grid-template-columns: auto 1fr;
47
- grid-template-rows: auto auto 1fr;
48
- flex-grow: 1;
49
-
50
- /* Максимальная ширина с отступами */
51
- max-width: ${({ $isFocusedMode }) => ($isFocusedMode ? '100%' : '1572px')};
52
- height: 100vh;
53
- padding: ${({ theme }) => theme.spacing(0, 4, 4)};
54
-
55
- transition: ${({ theme }) => {
56
- return theme.transitions.create(['max-width'], {
57
- duration: theme.transitions.duration.complex,
58
- });
59
- }};
60
-
61
- /* Причина игнора: Не критично для отображения */
62
- /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
63
- &:has(.${constants_1.dashboardSidebarClassnames.root}) {
64
- column-gap: ${({ theme }) => theme.spacing(4)};
65
-
66
- ${({ theme }) => theme.breakpoints.down('sm')} {
67
- column-gap: 0;
68
- }
69
- }
70
-
71
- /* Причина игнора: Прогрессивное улучшение */
72
- /* stylelint-disable plugin/no-unsupported-browser-features */
73
- @supports (height: 100dvh) {
74
- height: 100dvh;
75
- }
76
- /* stylelint-enable plugin/no-unsupported-browser-features */
77
-
78
- ${({ theme }) => theme.breakpoints.down('sm')} {
79
- column-gap: 0;
80
-
81
- min-width: unset;
82
- max-width: unset;
83
- padding: 0;
84
- }
85
- `;
@@ -5,7 +5,7 @@ export declare const useLogic: ({ profile, menuOrganization }: HeaderProps) => {
5
5
  isShowProfile: boolean;
6
6
  isMobile: boolean;
7
7
  isFocusedMode: boolean;
8
- mobileHeaderPriorityFeature: "profile" | "menuOrg";
8
+ mobileHeaderPriorityFeature: "menuOrg" | "profile";
9
9
  isLoading: boolean;
10
10
  collapsedIn: boolean;
11
11
  onToggleSidebar: (newValue?: boolean | undefined) => void;
@@ -15,4 +15,9 @@ export type DashboardLayoutProps = {
15
15
  * Второстепенный будет помещен в sidebar.
16
16
  */
17
17
  mobileHeaderPriorityFeature?: 'profile' | 'menuOrg';
18
+ /**
19
+ * Compact - ширина layout ограничена 1572px. Необходимо для удобного чтения контента, без лишнего растягивания
20
+ * Wide - ширина layout ограничена 1920px. Применяйте, когда в вашем приложении отображается много табличных данных с большим количеством колонок. Пример - админки
21
+ */
22
+ desktopViewMode?: 'wide' | 'compact';
18
23
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DashboardLayoutSkeleton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Container_1 = require("../DashboardLayout/Container");
5
6
  const constants_1 = require("../DashboardLayout/constants");
6
7
  const DashboardLayout_1 = require("../DashboardLayout/DashboardLayout");
7
8
  const styles_1 = require("../DashboardLayout/DashboardWrapper/styles");
@@ -14,7 +15,7 @@ const styles_2 = require("./styles");
14
15
  * Компонент можно использовать для отображения состояния загрузки дашборда
15
16
  */
16
17
  const DashboardLayoutSkeleton = ({ product, productSwitcher, hasSidebar = true, hasProfile = true, hasMenuOrganization = true, }) => {
17
- return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { className: constants_1.dashboardLayoutClassnames.root, children: [(0, jsx_runtime_1.jsx)(styles_1.DecorativeHeaderBackground, { role: "presentation", "$isFocusedMode": false }), (0, jsx_runtime_1.jsxs)(styles_1.LayoutContent, { "$isFocusedMode": false, children: [hasSidebar && (0, jsx_runtime_1.jsx)(DashboardSidebarSkeleton_1.DashboardSidebarSkeleton, {}), (0, jsx_runtime_1.jsx)(Header_1.Header, { productSwitcher: productSwitcher, product: product, menuOrganization: hasMenuOrganization ? () => (0, jsx_runtime_1.jsx)(MenuOrganization_1.MenuOrganizationSkeleton, {}) : undefined, profile: hasProfile
18
+ return ((0, jsx_runtime_1.jsxs)(styles_1.Wrapper, { className: constants_1.dashboardLayoutClassnames.root, children: [(0, jsx_runtime_1.jsx)(styles_1.DecorativeHeaderBackground, { role: "presentation", "$isFocusedMode": false }), (0, jsx_runtime_1.jsxs)(Container_1.Container, { children: [hasSidebar && (0, jsx_runtime_1.jsx)(DashboardSidebarSkeleton_1.DashboardSidebarSkeleton, {}), (0, jsx_runtime_1.jsx)(Header_1.Header, { productSwitcher: productSwitcher, product: product, menuOrganization: hasMenuOrganization ? () => (0, jsx_runtime_1.jsx)(MenuOrganization_1.MenuOrganizationSkeleton, {}) : undefined, profile: hasProfile
18
19
  ? { displayName: '', isLoading: true, menuList: [] }
19
20
  : undefined }), (0, jsx_runtime_1.jsx)(DashboardLayout_1.DashboardLayout.Main, { children: (0, jsx_runtime_1.jsx)(styles_2.Content, { children: (0, jsx_runtime_1.jsx)(LoadingPlaceholder_1.LoadingPlaceholder, { title: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0434\u0430\u043D\u043D\u044B\u0445" }) }) })] })] }));
20
21
  };
@@ -30,6 +30,8 @@ type UseMaskedValueAndSelectedBaseDateReturn = {
30
30
  */
31
31
  value: string;
32
32
  };
33
+ /** При blur неполной даты - в onChange уходит Invalid Date (тот же стейт, что у маски). */
34
+ onMaskedValueBlur: () => void;
33
35
  };
34
36
  /**
35
37
  * хук объединяющий повторяющуюся логику в работе DatePicker и RangeDatePicker:
@@ -15,7 +15,7 @@ const useSelectedBaseDate_1 = require("../useSelectedBaseDate");
15
15
  */
16
16
  const useDatePickerOptions = ({ onChange, mask, currentValue, minDate, maxDate, monthOffset, onDatePick, }) => {
17
17
  const baseDate = (0, useBaseDateInRange_1.useBaseDateInRange)({ minDate, maxDate, monthOffset });
18
- const { maskedValue, onMaskedValueChange, onMaskedDateChange } = (0, useMaskedValue_1.useMaskedValue)({
18
+ const { maskedValue, onMaskedValueChange, onMaskedValueBlur, onMaskedDateChange, } = (0, useMaskedValue_1.useMaskedValue)({
19
19
  currentValue,
20
20
  mask,
21
21
  onChangeValue: onChange,
@@ -42,6 +42,7 @@ const useDatePickerOptions = ({ onChange, mask, currentValue, minDate, maxDate,
42
42
  onChange: handleDatePick,
43
43
  date: selectedBaseDate || baseDate,
44
44
  },
45
+ onMaskedValueBlur,
45
46
  };
46
47
  };
47
48
  exports.useDatePickerOptions = useDatePickerOptions;
@@ -19,6 +19,10 @@ type Returned = {
19
19
  * Изменение maskedValue
20
20
  * */
21
21
  onMaskedValueChange: (value: string) => void;
22
+ /**
23
+ * Реакция на blur maskedValue
24
+ * */
25
+ onMaskedValueBlur: () => void;
22
26
  };
23
27
  /**
24
28
  * Хук для управления значением для MaskField
@@ -9,19 +9,43 @@ const date_1 = require("../../../utils/date");
9
9
  */
10
10
  const useMaskedValue = ({ currentValue, mask, onChangeValue, }) => {
11
11
  const [maskedValue, setMaskedValue] = (0, react_1.useState)(() => currentValue ? (0, date_1.formatDate)(currentValue, mask) : '');
12
+ const maskedValueRef = (0, react_1.useRef)(maskedValue);
13
+ /**
14
+ * Ввод в маску: синхронизируем локальное значение и ref (ref нужен на blur и после выбора даты из календаря,
15
+ * чтобы не читать устаревший state).
16
+ * `onChangeValue` вызываем только при пустой строке (`null`) или когда маска синтаксически полная —
17
+ * иначе partial не уходит наружу до завершения ввода или до blur (см. `handleMaskedValueBlur`).
18
+ */
12
19
  const handleMaskedValueChange = (value) => {
13
20
  setMaskedValue(value);
14
- // При отсутствии value указываем null, так как если задать undefined, то отобразится defaultValue при наличии
21
+ maskedValueRef.current = value;
15
22
  if (!value) {
16
23
  onChangeValue?.(null, value);
24
+ return;
25
+ }
26
+ if (!(0, date_1.isMaskedDateSyntacticallyComplete)(value, mask)) {
27
+ return;
17
28
  }
18
- else {
19
- onChangeValue?.((0, date_1.parseDate)(value, mask), value);
29
+ onChangeValue?.((0, date_1.parseDate)(value, mask), value);
30
+ };
31
+ /**
32
+ * Blur поля: если осталась непустая неполная маска — один раз отдаём `Invalid Date` в `onChangeValue`,
33
+ * чтобы формы могли показать ошибку. Пустая строка и полная маска не дублируют уже отправленный `onChange`.
34
+ */
35
+ const handleMaskedValueBlur = () => {
36
+ const currentMaskedValue = maskedValueRef.current;
37
+ if (!currentMaskedValue) {
38
+ return;
39
+ }
40
+ if ((0, date_1.isMaskedDateSyntacticallyComplete)(currentMaskedValue, mask)) {
41
+ return;
20
42
  }
43
+ onChangeValue?.(new Date(Number.NaN), currentMaskedValue);
21
44
  };
22
45
  const handleChangeMaskedDate = (date) => {
23
46
  const formatted = (0, date_1.formatDate)(date, mask);
24
47
  setMaskedValue(formatted);
48
+ maskedValueRef.current = formatted;
25
49
  onChangeValue?.(date, formatted);
26
50
  };
27
51
  // здесь происходит реакция на изменение value из вне (управляемый компонент)
@@ -29,6 +53,7 @@ const useMaskedValue = ({ currentValue, mask, onChangeValue, }) => {
29
53
  // если новое значение пустое, то сбрасываем значение MaskField
30
54
  if (!currentValue) {
31
55
  setMaskedValue('');
56
+ maskedValueRef.current = '';
32
57
  return;
33
58
  }
34
59
  // здесь обрабатывается сценарий, когда в инпут вводится невалидная дата и при этом currentValue становится Invalid Date
@@ -36,16 +61,20 @@ const useMaskedValue = ({ currentValue, mask, onChangeValue, }) => {
36
61
  if (!(0, isDate_1.isDate)(currentValue) && maskedValue) {
37
62
  return;
38
63
  }
39
- // проверяем равны ли даты
40
- const isEqualValueAndMaskedDate = currentValue.getTime() === (0, date_1.parseDate)(maskedValue, mask).getTime();
64
+ // сравнение только при полной маске, иначе getTime() от parseDate может быть NaN
65
+ const isEqualValueAndMaskedDate = (0, date_1.isMaskedDateSyntacticallyComplete)(maskedValue, mask) &&
66
+ currentValue.getTime() === (0, date_1.parseDate)(maskedValue, mask).getTime();
41
67
  // если даты не равны, то значит изменился currentValue из вне и надо синхронизировать maskedValue
42
68
  if (!isEqualValueAndMaskedDate) {
43
- setMaskedValue((0, date_1.formatDate)(currentValue, mask));
69
+ const formatted = (0, date_1.formatDate)(currentValue, mask);
70
+ setMaskedValue(formatted);
71
+ maskedValueRef.current = formatted;
44
72
  }
45
73
  }, [currentValue]);
46
74
  return {
47
75
  maskedValue,
48
76
  onMaskedValueChange: handleMaskedValueChange,
77
+ onMaskedValueBlur: handleMaskedValueBlur,
49
78
  onMaskedDateChange: handleChangeMaskedDate,
50
79
  };
51
80
  };
@@ -13,6 +13,7 @@ export declare const useLogic: ({ label, value, maxDate, minDate, mask, onOpen,
13
13
  };
14
14
  DatePickerInputProps: {
15
15
  value: string;
16
+ onBlur: () => void;
16
17
  };
17
18
  onAccept: ((value: string, maskRef: import("imask").default.InputMask<import("imask").default.AnyMaskedOptions>, e?: InputEvent | undefined, onChange?: ((changeValue: string) => void) | undefined) => void) | undefined;
18
19
  pickerProps: import("../types").PickerProps;