@astral/ui 4.51.0 → 4.52.1

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 (89) hide show
  1. package/components/DashboardContext/DashboardContext.d.ts +2 -0
  2. package/components/DashboardContext/DashboardContext.js +2 -0
  3. package/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.d.ts +2 -2
  4. package/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.js +4 -1
  5. package/components/DashboardLayout/DashboardLayout.d.ts +1 -1
  6. package/components/DashboardLayout/DashboardLayout.js +2 -2
  7. package/components/DashboardLayout/Header/Header.js +28 -3
  8. package/components/DashboardLayout/Header/constants.d.ts +5 -1
  9. package/components/DashboardLayout/Header/constants.js +5 -1
  10. package/components/DashboardLayout/Header/styles.d.ts +4 -3
  11. package/components/DashboardLayout/Header/styles.js +66 -24
  12. package/components/DashboardLayout/Header/useLogic/useLogic.d.ts +4 -1
  13. package/components/DashboardLayout/Header/useLogic/useLogic.js +16 -11
  14. package/components/DashboardLayout/types.d.ts +5 -0
  15. package/components/DashboardSidebar/DashboardSidebar.js +17 -2
  16. package/components/DashboardSidebar/constants.d.ts +1 -0
  17. package/components/DashboardSidebar/constants.js +1 -0
  18. package/components/DashboardSidebar/styles.js +1 -1
  19. package/components/DashboardSidebar/useLogic/useLogic.d.ts +2 -1
  20. package/components/DashboardSidebar/useLogic/useLogic.js +5 -6
  21. package/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.d.ts +2 -0
  22. package/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.js +2 -1
  23. package/components/DatePicker/hooks/useMaskedValue/useMaskedValue.d.ts +4 -0
  24. package/components/DatePicker/hooks/useMaskedValue/useMaskedValue.js +37 -8
  25. package/components/DatePicker/useLogic/useLogic.d.ts +1 -0
  26. package/components/DatePicker/useLogic/useLogic.js +19 -13
  27. package/components/DateRangePicker/useLogic/useLogic.d.ts +2 -0
  28. package/components/DateRangePicker/useLogic/useLogic.js +27 -3
  29. package/components/DateRangePicker/useLogic/utils/index.d.ts +0 -1
  30. package/components/DateRangePicker/useLogic/utils/index.js +0 -1
  31. package/components/MenuOrganization/OrganizationButton/OrganizationButton.js +1 -1
  32. package/components/MenuOrganization/constants.d.ts +1 -0
  33. package/components/MenuOrganization/constants.js +1 -0
  34. package/components/Profile/Profile.js +1 -1
  35. package/components/Profile/constants.d.ts +3 -0
  36. package/components/Profile/constants.js +3 -0
  37. package/components/utils/date/format/index.d.ts +1 -0
  38. package/components/utils/date/format/index.js +1 -0
  39. package/{node/components/DateRangePicker/useLogic/utils → components/utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.d.ts +1 -1
  40. package/components/utils/date/format/parseDate/parseDate.d.ts +1 -0
  41. package/components/utils/date/format/parseDate/parseDate.js +42 -13
  42. package/node/components/DashboardContext/DashboardContext.d.ts +2 -0
  43. package/node/components/DashboardContext/DashboardContext.js +2 -0
  44. package/node/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.d.ts +2 -2
  45. package/node/components/DashboardContext/DashboardContextProvider/DashboardContextProvider.js +4 -1
  46. package/node/components/DashboardLayout/DashboardLayout.d.ts +1 -1
  47. package/node/components/DashboardLayout/DashboardLayout.js +2 -2
  48. package/node/components/DashboardLayout/Header/Header.js +27 -2
  49. package/node/components/DashboardLayout/Header/constants.d.ts +5 -1
  50. package/node/components/DashboardLayout/Header/constants.js +5 -1
  51. package/node/components/DashboardLayout/Header/styles.d.ts +4 -3
  52. package/node/components/DashboardLayout/Header/styles.js +74 -32
  53. package/node/components/DashboardLayout/Header/useLogic/useLogic.d.ts +4 -1
  54. package/node/components/DashboardLayout/Header/useLogic/useLogic.js +15 -10
  55. package/node/components/DashboardLayout/types.d.ts +5 -0
  56. package/node/components/DashboardSidebar/DashboardSidebar.js +17 -2
  57. package/node/components/DashboardSidebar/constants.d.ts +1 -0
  58. package/node/components/DashboardSidebar/constants.js +1 -0
  59. package/node/components/DashboardSidebar/styles.js +1 -1
  60. package/node/components/DashboardSidebar/useLogic/useLogic.d.ts +2 -1
  61. package/node/components/DashboardSidebar/useLogic/useLogic.js +4 -5
  62. package/node/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.d.ts +2 -0
  63. package/node/components/DatePicker/hooks/useDatePickerOptions/useDatePickerOptions.js +2 -1
  64. package/node/components/DatePicker/hooks/useMaskedValue/useMaskedValue.d.ts +4 -0
  65. package/node/components/DatePicker/hooks/useMaskedValue/useMaskedValue.js +35 -6
  66. package/node/components/DatePicker/useLogic/useLogic.d.ts +1 -0
  67. package/node/components/DatePicker/useLogic/useLogic.js +19 -13
  68. package/node/components/DateRangePicker/useLogic/useLogic.d.ts +2 -0
  69. package/node/components/DateRangePicker/useLogic/useLogic.js +28 -4
  70. package/node/components/DateRangePicker/useLogic/utils/index.d.ts +0 -1
  71. package/node/components/DateRangePicker/useLogic/utils/index.js +0 -1
  72. package/node/components/MenuOrganization/OrganizationButton/OrganizationButton.js +1 -1
  73. package/node/components/MenuOrganization/constants.d.ts +1 -0
  74. package/node/components/MenuOrganization/constants.js +1 -0
  75. package/node/components/Profile/Profile.js +1 -1
  76. package/node/components/Profile/constants.d.ts +3 -0
  77. package/node/components/Profile/constants.js +3 -0
  78. package/node/components/utils/date/format/index.d.ts +1 -0
  79. package/node/components/utils/date/format/index.js +1 -0
  80. package/{components/DateRangePicker/useLogic/utils → node/components/utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.d.ts +1 -1
  81. package/node/components/utils/date/format/parseDate/parseDate.d.ts +1 -0
  82. package/node/components/utils/date/format/parseDate/parseDate.js +45 -13
  83. package/package.json +1 -1
  84. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.d.ts +0 -0
  85. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.js +0 -0
  86. /package/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.js +0 -0
  87. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.d.ts +0 -0
  88. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/index.js +0 -0
  89. /package/node/components/{DateRangePicker/useLogic/utils → utils/date/format}/isMaskedDateSyntacticallyComplete/isMaskedDateSyntacticallyComplete.js +0 -0
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MenuOrganizationWrapper = exports.HeaderContent = exports.ExitButton = exports.ProfileWrapper = exports.ProductSwitcherWrapper = exports.HeaderContentSection = exports.HeaderSection = exports.MobileSidebarTogglerWrapper = exports.HeaderRoot = void 0;
3
+ exports.PriorityFeatureWrapper = exports.HeaderContent = exports.ExitButton = exports.ProfileWrapper = exports.ProductSwitcherWrapper = exports.HeaderContentSection = exports.HeaderSection = exports.MobileSidebarTogglerWrapper = exports.HeaderRoot = void 0;
4
4
  const Button_1 = require("@mui/material/Button");
5
5
  const constants_1 = require("../../DashboardSidebar/constants");
6
6
  const IconButton_1 = require("../../IconButton");
7
7
  const constants_2 = require("../../MenuOrganization/constants");
8
8
  const constants_3 = require("../../MenuOrganization/OrganizationButton/constants");
9
+ const constants_4 = require("../../Profile/constants");
9
10
  const styled_1 = require("../../styled");
10
- const constants_4 = require("../constants");
11
- const constants_5 = require("./constants");
11
+ const constants_5 = require("../constants");
12
+ const constants_6 = require("./constants");
12
13
  exports.HeaderRoot = (0, styled_1.styled)('header', {
13
14
  shouldForwardProp: (prop) => !['$isFocusedMode'].includes(prop),
14
15
  }) `
@@ -21,8 +22,8 @@ exports.HeaderRoot = (0, styled_1.styled)('header', {
21
22
  justify-content: space-between;
22
23
 
23
24
  width: 100%;
24
- height: ${constants_4.HEADER_HEIGHT_DESKTOP};
25
- margin-top: ${({ $isFocusedMode }) => $isFocusedMode ? `-${constants_4.HEADER_HEIGHT_DESKTOP}` : 0};
25
+ height: ${constants_5.HEADER_HEIGHT_DESKTOP};
26
+ margin-top: ${({ $isFocusedMode }) => $isFocusedMode ? `-${constants_5.HEADER_HEIGHT_DESKTOP}` : 0};
26
27
  margin-bottom: ${({ theme }) => theme.spacing(4)};
27
28
 
28
29
  transition: ${({ theme }) => {
@@ -32,14 +33,14 @@ exports.HeaderRoot = (0, styled_1.styled)('header', {
32
33
  }};
33
34
 
34
35
  ${({ theme }) => theme.breakpoints.down('laptop')} {
35
- height: ${constants_4.HEADER_HEIGHT_LAPTOP};
36
+ height: ${constants_5.HEADER_HEIGHT_LAPTOP};
36
37
  }
37
38
 
38
39
  ${({ theme }) => theme.breakpoints.down('sm')} {
39
40
  grid-row: 2;
40
41
  justify-content: flex-start;
41
42
 
42
- height: ${constants_4.HEADER_HEIGHT_MOBILE};
43
+ height: ${constants_5.HEADER_HEIGHT_MOBILE};
43
44
  margin-bottom: 0;
44
45
  padding: ${({ theme }) => theme.spacing(0, 2, 0, 1)};
45
46
 
@@ -60,7 +61,7 @@ exports.MobileSidebarTogglerWrapper = styled_1.styled.div `
60
61
 
61
62
  /* Причина игнора: Не критично для отображения */
62
63
  /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
63
- .${constants_4.dashboardLayoutClassnames.root}:not(:has(.${constants_1.dashboardSidebarClassnames.root}))
64
+ .${constants_5.dashboardLayoutClassnames.root}:not(:has(.${constants_1.dashboardSidebarClassnames.root}))
64
65
  & {
65
66
  display: none;
66
67
  }
@@ -80,6 +81,15 @@ exports.HeaderContentSection = (0, styled_1.styled)(exports.HeaderSection) `
80
81
 
81
82
  ${({ theme }) => theme.breakpoints.down('sm')} {
82
83
  gap: ${({ theme }) => theme.spacing(2)};
84
+
85
+ &.${constants_6.dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
86
+ & .${constants_2.menuOrganizationClassnames.organizationData} {
87
+ display: none;
88
+ }
89
+ & .${constants_2.menuOrganizationClassnames.button} {
90
+ border-radius: ${({ theme }) => theme.shape.medium};
91
+ }
92
+ }
83
93
  }
84
94
  `;
85
95
  exports.ProductSwitcherWrapper = styled_1.styled.div `
@@ -114,45 +124,77 @@ exports.HeaderContent = styled_1.styled.div `
114
124
  padding: 0;
115
125
  }
116
126
  `;
117
- exports.MenuOrganizationWrapper = styled_1.styled.div `
127
+ /**
128
+ * Обертка для элементов которые должны быть в мобильном хедере или помещены в sidebar.
129
+ */
130
+ exports.PriorityFeatureWrapper = styled_1.styled.div `
118
131
  ${({ theme }) => theme.breakpoints.down('sm')} {
119
- position: absolute;
120
- z-index: ${({ theme }) => theme.zIndex.appBar - 1};
121
- top: ${({ $alertHeight }) => `calc(${$alertHeight}px + ${constants_4.HEADER_HEIGHT_MOBILE}) `};
122
- left: 0;
123
-
124
- /* Необходимо для анимации компонента вместе с sidebar */
125
- transform: translateX(-100vw);
126
132
 
127
- display: flex;
128
- flex-direction: column;
133
+ &.${constants_6.dashboardLayoutHeaderClassnames.featureInSidebar} {
134
+ position: absolute;
135
+ z-index: ${({ theme }) => theme.zIndex.appBar - 1};
136
+ top: calc(var(--alert-height, 0px) + ${constants_5.HEADER_HEIGHT_MOBILE});
137
+ left: 0;
138
+
139
+ /* Необходимо для анимации компонента вместе с sidebar */
140
+ transform: translateX(-100vw);
129
141
 
130
- width: 100vw;
142
+ display: flex;
143
+ flex-direction: column;
131
144
 
132
- background-color: ${({ theme }) => theme.palette.background.default};
145
+ width: 100vw;
133
146
 
134
- transition: ${({ theme }) => {
147
+ background-color: ${({ theme }) => theme.palette.background.default};
148
+
149
+ transition: ${({ theme }) => {
135
150
  return theme.transitions.create(['transform'], {
136
151
  duration: theme.transitions.duration.standard,
137
152
  });
138
153
  }};
139
154
 
140
- &.${constants_5.dashboardLayoutHeaderClassnames.mobileMenuOrganizationVisible} {
141
- transform: translateX(0);
142
- }
143
-
144
- & .${constants_2.menuOrganizationClassnames.button} {
145
- height: ${constants_3.MOBILE_BUTTON_HEIGHT};
146
- padding: ${({ theme }) => theme.spacing(3, 4)};
155
+ &.${constants_6.dashboardLayoutHeaderClassnames.mobileSidebarPriorityFeatureVisible} {
156
+ transform: translateX(0);
157
+ }
147
158
 
148
- border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
159
+ & .${constants_2.menuOrganizationClassnames.button}, & .${constants_4.profileClassnames.button} {
160
+ height: ${constants_3.MOBILE_BUTTON_HEIGHT};
161
+ padding: ${({ theme }) => theme.spacing(3, 4)};
149
162
 
150
- &:hover {
151
163
  border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
164
+
165
+ &:hover {
166
+ border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
167
+ }
168
+
169
+ &:active {
170
+ border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
171
+ }
152
172
  }
153
173
 
154
- &:active {
155
- border-bottom: 1px solid ${({ theme }) => theme.palette.grey[300]};
174
+ &.${constants_6.dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
175
+ & .${constants_6.dashboardLayoutHeaderClassnames.profile} {
176
+ display: block;
177
+ }
178
+
179
+
180
+ & .${constants_4.profileClassnames.button} {
181
+ width: 100%;
182
+ max-width: unset;
183
+
184
+ border-radius: 0;
185
+ }
186
+
187
+ & .${constants_4.profileClassnames.avatar} {
188
+ display: none;
189
+ }
190
+
191
+ & .${constants_4.profileClassnames.user} {
192
+ display: flex;
193
+ align-items: center;
194
+ justify-content: space-between;
195
+
196
+ width: 100%;
197
+ }
156
198
  }
157
199
  }
158
200
  }
@@ -1,12 +1,15 @@
1
+ import { type CSSProperties } from 'react';
1
2
  import { type HeaderProps } from '../types';
2
3
  export declare const useLogic: ({ profile, menuOrganization }: HeaderProps) => {
3
4
  isShowExitButton: boolean;
4
5
  isShowProfile: boolean;
5
6
  isMobile: boolean;
6
7
  isFocusedMode: boolean;
8
+ mobileHeaderPriorityFeature: "profile" | "menuOrg";
7
9
  isLoading: boolean;
8
10
  collapsedIn: boolean;
9
11
  onToggleSidebar: (newValue?: boolean | undefined) => void;
10
12
  alertHeight: number;
11
- menuOrganizationClassnames: string;
13
+ isPinned: boolean;
14
+ headerStyle: CSSProperties;
12
15
  };
@@ -5,31 +5,36 @@ const react_1 = require("react");
5
5
  const DashboardContext_1 = require("../../../DashboardContext");
6
6
  const DashboardSidebarProvider_1 = require("../../../DashboardSidebarProvider");
7
7
  const useViewportType_1 = require("../../../useViewportType");
8
- const classNames_1 = require("../../../utils/classNames");
9
- const constants_1 = require("../constants");
10
8
  const useLogic = ({ profile, menuOrganization }) => {
11
- const { isFocusedMode, isLoading, hasMenuOrganizationRef, alertHeight } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
9
+ const { isFocusedMode, isLoading, hasMenuOrganizationRef, hasProfileRef, alertHeight, mobileHeaderPriorityFeature, } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
12
10
  const { collapsedIn, onToggleSidebar, isPinned } = (0, react_1.useContext)(DashboardSidebarProvider_1.DashboardSidebarContext);
13
11
  (0, react_1.useEffect)(() => {
14
12
  hasMenuOrganizationRef.current = Boolean(menuOrganization);
15
- }, [menuOrganization]);
13
+ hasProfileRef.current = Boolean(profile);
14
+ }, [menuOrganization, profile]);
16
15
  const { isMobile } = (0, useViewportType_1.useViewportType)();
17
16
  const hasMenu = Boolean(profile?.menu || profile?.menuList);
18
- const isShowProfile = (Boolean(profile) && !isMobile) || (hasMenu && isMobile);
19
- const isShowExitButton = isMobile && !hasMenu && Boolean(profile?.exitButton);
20
- const menuOrganizationClassnames = (0, react_1.useMemo)(() => (0, classNames_1.classNames)({
21
- [constants_1.dashboardLayoutHeaderClassnames.mobileMenuOrganizationVisible]: isPinned,
22
- }), [isPinned]);
17
+ const isShowProfile = (Boolean(profile) && !isMobile) ||
18
+ (hasMenu && isMobile && mobileHeaderPriorityFeature === 'profile');
19
+ const isShowExitButton = isMobile &&
20
+ !hasMenu &&
21
+ Boolean(profile?.exitButton) &&
22
+ mobileHeaderPriorityFeature === 'profile';
23
+ const headerStyle = {
24
+ '--alert-height': `${alertHeight}px`,
25
+ };
23
26
  return {
24
27
  isShowExitButton,
25
28
  isShowProfile,
26
29
  isMobile,
27
30
  isFocusedMode,
31
+ mobileHeaderPriorityFeature,
28
32
  isLoading,
29
33
  collapsedIn,
30
34
  onToggleSidebar,
31
35
  alertHeight,
32
- menuOrganizationClassnames,
36
+ isPinned,
37
+ headerStyle,
33
38
  };
34
39
  };
35
40
  exports.useLogic = useLogic;
@@ -10,4 +10,9 @@ export type DashboardLayoutProps = {
10
10
  * Если true, отображается состояние загрузки
11
11
  */
12
12
  isLoading?: boolean;
13
+ /**
14
+ * Элемент, отображаемый в мобильном хедере.
15
+ * Второстепенный будет помещен в sidebar.
16
+ */
17
+ mobileHeaderPriorityFeature?: 'profile' | 'menuOrg';
13
18
  };
@@ -6,17 +6,32 @@ const react_1 = require("react");
6
6
  const DashboardSidebarSkeleton_1 = require("../DashboardSidebarSkeleton");
7
7
  const NavMenu_1 = require("../NavMenu");
8
8
  const PinButton_1 = require("../PinButton");
9
+ const cva_1 = require("../utils/cva");
9
10
  const getInertProps_1 = require("../utils/getInertProps");
11
+ const constants_1 = require("./constants");
10
12
  const SidebarNav_1 = require("./SidebarNav");
11
13
  const styles_1 = require("./styles");
12
14
  const useLogic_1 = require("./useLogic");
15
+ const sidebar = (0, cva_1.cva)('', {
16
+ variants: {
17
+ hasProfile: {
18
+ true: constants_1.dashboardSidebarClassnames.hasProfile,
19
+ },
20
+ hasMenuOrganization: {
21
+ true: constants_1.dashboardSidebarClassnames.hasMenuOrganization,
22
+ },
23
+ },
24
+ });
13
25
  /**
14
26
  * Основной sidebar приложения
15
27
  */
16
28
  exports.DashboardSidebar = (0, react_1.forwardRef)((props, ref) => {
17
- const { isPinned, isMobile, collapsedIn, onTogglePin, onMouseEnter, onMouseLeave, alertHeight, classnames, wrapperClassnames, menu, header, isLoading, } = (0, useLogic_1.useLogic)(props);
29
+ const { isPinned, isMobile, collapsedIn, onTogglePin, onMouseEnter, onMouseLeave, alertHeight, classnames, menu, header, isLoading, hasMenuOrganization, hasProfile, } = (0, useLogic_1.useLogic)(props);
18
30
  if (isLoading) {
19
31
  return (0, jsx_runtime_1.jsx)(DashboardSidebarSkeleton_1.DashboardSidebarSkeleton, {});
20
32
  }
21
- return ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { "$isPinned": isPinned, "$alertHeight": alertHeight, className: wrapperClassnames, children: (0, jsx_runtime_1.jsx)(styles_1.SidebarRoot, { ref: ref, "$isPinned": isPinned, "$collapsedIn": collapsedIn, className: classnames, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ...(0, getInertProps_1.getInertProps)(isMobile && !isPinned), children: (0, jsx_runtime_1.jsxs)(styles_1.StyledPaper, { variant: "outlined", children: [(0, jsx_runtime_1.jsxs)(styles_1.SidebarContent, { "$collapsedIn": collapsedIn, "$isPinned": isPinned, "$hasHeader": Boolean(header), children: [header && (0, jsx_runtime_1.jsx)(styles_1.SidebarHeader, { children: header }), (0, jsx_runtime_1.jsx)(SidebarNav_1.SidebarNav, { menu: (0, jsx_runtime_1.jsx)(NavMenu_1.NavMenu, { collapsedIn: collapsedIn, items: menu.items }) })] }), (0, jsx_runtime_1.jsx)(styles_1.Footer, { children: (0, jsx_runtime_1.jsx)(PinButton_1.PinButton, { isPinned: isPinned, collapsedIn: collapsedIn, onClick: onTogglePin }) })] }) }) }));
33
+ return ((0, jsx_runtime_1.jsx)(styles_1.Wrapper, { "$isPinned": isPinned, "$alertHeight": alertHeight, className: sidebar({
34
+ hasProfile,
35
+ hasMenuOrganization,
36
+ }), children: (0, jsx_runtime_1.jsx)(styles_1.SidebarRoot, { ref: ref, "$isPinned": isPinned, "$collapsedIn": collapsedIn, className: classnames, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ...(0, getInertProps_1.getInertProps)(isMobile && !isPinned), children: (0, jsx_runtime_1.jsxs)(styles_1.StyledPaper, { variant: "outlined", children: [(0, jsx_runtime_1.jsxs)(styles_1.SidebarContent, { "$collapsedIn": collapsedIn, "$isPinned": isPinned, "$hasHeader": Boolean(header), children: [header && (0, jsx_runtime_1.jsx)(styles_1.SidebarHeader, { children: header }), (0, jsx_runtime_1.jsx)(SidebarNav_1.SidebarNav, { menu: (0, jsx_runtime_1.jsx)(NavMenu_1.NavMenu, { collapsedIn: collapsedIn, items: menu.items }) })] }), (0, jsx_runtime_1.jsx)(styles_1.Footer, { children: (0, jsx_runtime_1.jsx)(PinButton_1.PinButton, { isPinned: isPinned, collapsedIn: collapsedIn, onClick: onTogglePin }) })] }) }) }));
22
37
  });
@@ -1,5 +1,6 @@
1
1
  export declare const dashboardSidebarClassnames: {
2
2
  root: string;
3
+ hasProfile: string;
3
4
  hasMenuOrganization: string;
4
5
  };
5
6
  export declare const LABEL_WIDTH: {
@@ -4,6 +4,7 @@ exports.LABEL_WIDTH = exports.dashboardSidebarClassnames = void 0;
4
4
  const createUIKitClassname_1 = require("../utils/createUIKitClassname");
5
5
  exports.dashboardSidebarClassnames = {
6
6
  root: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout-sidebar'),
7
+ hasProfile: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout-sidebar_has-profile'),
7
8
  hasMenuOrganization: (0, createUIKitClassname_1.createUIKitClassname)('dashboard-layout-sidebar_has-menu-organization'),
8
9
  };
9
10
  exports.LABEL_WIDTH = {
@@ -38,7 +38,7 @@ exports.Wrapper = (0, styled_1.styled)('div', {
38
38
  });
39
39
  }};
40
40
 
41
- &.${constants_4.dashboardSidebarClassnames.hasMenuOrganization} {
41
+ &.${constants_4.dashboardSidebarClassnames.hasMenuOrganization}, &.${constants_4.dashboardSidebarClassnames.hasProfile} {
42
42
  top: ${({ $alertHeight }) => `calc(${$alertHeight}px + ${constants_2.HEADER_HEIGHT_MOBILE} + ${OrganizationButton_1.MOBILE_BUTTON_HEIGHT}) `};
43
43
  }
44
44
  }
@@ -28,5 +28,6 @@ export declare const useLogic: (props: DashboardSidebarProps) => {
28
28
  header: import("react").ReactNode;
29
29
  isLoading: boolean;
30
30
  classnames: string;
31
- wrapperClassnames: string;
31
+ hasMenuOrganization: boolean | null;
32
+ hasProfile: boolean | null;
32
33
  };
@@ -13,7 +13,7 @@ const constants_1 = require("../constants");
13
13
  const useLogic = (props) => {
14
14
  const { className, menu, header, isLoading } = props;
15
15
  const { onToggleSidebar, isPinned, onTogglePin, collapsedIn, setIsPopupOpen, } = (0, react_1.useContext)(DashboardSidebarProvider_1.DashboardSidebarContext);
16
- const { alertHeight, isLoading: isDashboardLoading, hasMenuOrganizationRef, } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
16
+ const { alertHeight, isLoading: isDashboardLoading, hasMenuOrganizationRef, hasProfileRef, mobileHeaderPriorityFeature, } = (0, react_1.useContext)(DashboardContext_1.DashboardContext);
17
17
  const { isMobile } = (0, useViewportType_1.useViewportType)();
18
18
  const hoverTimerRef = (0, react_1.useRef)(null);
19
19
  const theme = (0, useTheme_1.useTheme)();
@@ -83,9 +83,6 @@ const useLogic = (props) => {
83
83
  }
84
84
  };
85
85
  }, [collapsedIn, isPinned]);
86
- const wrapperClassnames = (0, react_1.useMemo)(() => (0, classNames_1.classNames)({
87
- [constants_1.dashboardSidebarClassnames.hasMenuOrganization]: hasMenuOrganizationRef.current,
88
- }), [hasMenuOrganizationRef.current]);
89
86
  const classnames = (0, classNames_1.classNames)(className, constants_1.dashboardSidebarClassnames.root);
90
87
  return {
91
88
  isPinned,
@@ -99,7 +96,9 @@ const useLogic = (props) => {
99
96
  header,
100
97
  isLoading: isLoading || isDashboardLoading,
101
98
  classnames,
102
- wrapperClassnames,
99
+ hasMenuOrganization: hasMenuOrganizationRef.current &&
100
+ mobileHeaderPriorityFeature === 'profile',
101
+ hasProfile: hasProfileRef.current && mobileHeaderPriorityFeature === 'menuOrg',
103
102
  };
104
103
  };
105
104
  exports.useLogic = useLogic;
@@ -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;
@@ -7,7 +7,6 @@ const usePopover_1 = require("../../usePopover");
7
7
  const useViewportType_1 = require("../../useViewportType");
8
8
  const constants_1 = require("../constants");
9
9
  const useDatePickerOptions_1 = require("../hooks/useDatePickerOptions");
10
- const useMaskedValue_1 = require("../hooks/useMaskedValue");
11
10
  const MinMaxDateContext_1 = require("../MinMaxDateContext");
12
11
  const useLogic = ({ label, value, maxDate = MinMaxDateContext_1.DEFAULT_MAX_DATE, minDate = MinMaxDateContext_1.DEFAULT_MIN_DATE, mask = constants_1.DEFAULT_DATE_MASK, onOpen, onClose, onBlur, onChange, forwardedRef, }) => {
13
12
  const ref = (0, useForwardedRef_1.useForwardedRef)(forwardedRef);
@@ -15,21 +14,11 @@ const useLogic = ({ label, value, maxDate = MinMaxDateContext_1.DEFAULT_MAX_DATE
15
14
  const { isOpen, actions } = (0, usePopover_1.usePopover)();
16
15
  const { open, close } = actions;
17
16
  const { isMobile } = (0, useViewportType_1.useViewportType)();
18
- const { maskedValue } = (0, useMaskedValue_1.useMaskedValue)({
19
- currentValue: value,
20
- mask,
21
- onChangeValue: onChange,
22
- });
23
17
  const isTitleShow = isMobile && typeof label === 'string';
24
18
  const handleOpen = (event) => {
25
19
  onOpen?.();
26
20
  open(event);
27
21
  };
28
- const handleClose = () => {
29
- onBlur?.();
30
- onClose?.();
31
- close();
32
- };
33
22
  const handleDayPick = (date) => {
34
23
  if (isMobile) {
35
24
  setSelectedDate(date);
@@ -42,7 +31,7 @@ const useLogic = ({ label, value, maxDate = MinMaxDateContext_1.DEFAULT_MAX_DATE
42
31
  onChange?.(date);
43
32
  }
44
33
  };
45
- const { onAccept, inputProps: calculatedInputProps, pickerProps, } = (0, useDatePickerOptions_1.useDatePickerOptions)({
34
+ const { onAccept, inputProps: calculatedInputProps, pickerProps, onMaskedValueBlur, } = (0, useDatePickerOptions_1.useDatePickerOptions)({
46
35
  currentValue: value,
47
36
  maxDate,
48
37
  minDate,
@@ -50,6 +39,22 @@ const useLogic = ({ label, value, maxDate = MinMaxDateContext_1.DEFAULT_MAX_DATE
50
39
  onDatePick: handleDayPick,
51
40
  onChange: handleChange,
52
41
  });
42
+ /** Blur: неполный ввод -Invalid Date в onChange (при isMobile onChange не шлём), потом внешний onBlur. */
43
+ const flushMaskedValueAndCallOnBlur = () => {
44
+ onMaskedValueBlur();
45
+ onBlur?.();
46
+ };
47
+ function handleClose() {
48
+ flushMaskedValueAndCallOnBlur();
49
+ onClose?.();
50
+ close();
51
+ }
52
+ const handleInputBlur = () => {
53
+ if (isOpen) {
54
+ return;
55
+ }
56
+ flushMaskedValueAndCallOnBlur();
57
+ };
53
58
  const handleConfirm = () => {
54
59
  onChange?.(selectedDate);
55
60
  handleClose();
@@ -61,7 +66,8 @@ const useLogic = ({ label, value, maxDate = MinMaxDateContext_1.DEFAULT_MAX_DATE
61
66
  title: isTitleShow ? label : undefined,
62
67
  };
63
68
  const DatePickerInputProps = {
64
- value: isMobile ? maskedValue : calculatedInputProps.value,
69
+ value: calculatedInputProps.value,
70
+ onBlur: handleInputBlur,
65
71
  };
66
72
  const confirmButtonProps = {
67
73
  onClick: handleConfirm,
@@ -7,12 +7,14 @@ export declare const useLogic: ({ value, minDate, maxDate, mask, onChange, onOpe
7
7
  ref: import("react").RefObject<HTMLInputElement | null>;
8
8
  value: string;
9
9
  onAccept: (_: string, maskRef: IMask.InputMask<IMask.AnyMaskedOptions>) => void;
10
+ onBlur: () => void;
10
11
  onClick: (e: SyntheticEvent) => void;
11
12
  };
12
13
  endDatePickerInputProps: {
13
14
  ref: import("react").RefObject<HTMLInputElement | null>;
14
15
  value: string;
15
16
  onAccept: (_: string, maskRef: IMask.InputMask<IMask.AnyMaskedOptions>) => void;
17
+ onBlur: () => void;
16
18
  onClick: (e: SyntheticEvent) => void;
17
19
  };
18
20
  popoverHoveredContextProviderProps: {