@astral/ui 4.39.0 → 4.41.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 (47) hide show
  1. package/components/PageLayoutSection/PageLayoutSection.d.ts +21 -0
  2. package/components/PageLayoutSection/PageLayoutSection.js +19 -0
  3. package/components/PageLayoutSection/PageLayoutSectionContainer/PageLayoutSectionContainer.d.ts +25 -0
  4. package/components/PageLayoutSection/PageLayoutSectionContainer/PageLayoutSectionContainer.js +28 -0
  5. package/components/PageLayoutSection/PageLayoutSectionContainer/constants.d.ts +4 -0
  6. package/components/PageLayoutSection/PageLayoutSectionContainer/constants.js +4 -0
  7. package/components/PageLayoutSection/PageLayoutSectionContainer/index.d.ts +1 -0
  8. package/components/PageLayoutSection/PageLayoutSectionContainer/index.js +1 -0
  9. package/components/PageLayoutSection/PageLayoutSectionContainer/styles.d.ts +5 -0
  10. package/components/PageLayoutSection/PageLayoutSectionContainer/styles.js +51 -0
  11. package/components/PageLayoutSection/index.d.ts +2 -0
  12. package/components/PageLayoutSection/index.js +2 -0
  13. package/components/PageLayoutSection/public.d.ts +2 -0
  14. package/components/PageLayoutSection/public.js +2 -0
  15. package/components/PageLayoutSection/styles.d.ts +9 -0
  16. package/components/PageLayoutSection/styles.js +21 -0
  17. package/components/index.d.ts +1 -0
  18. package/components/index.js +1 -0
  19. package/hook-form/EditableText/EditableText.d.ts +10 -1
  20. package/hook-form/EditableText/EditableText.js +16 -2
  21. package/hook-form/EditableText/constants.d.ts +3 -0
  22. package/hook-form/EditableText/constants.js +4 -0
  23. package/hook-form/EditableText/styles.js +9 -0
  24. package/node/components/PageLayoutSection/PageLayoutSection.d.ts +21 -0
  25. package/node/components/PageLayoutSection/PageLayoutSection.js +22 -0
  26. package/node/components/PageLayoutSection/PageLayoutSectionContainer/PageLayoutSectionContainer.d.ts +25 -0
  27. package/node/components/PageLayoutSection/PageLayoutSectionContainer/PageLayoutSectionContainer.js +32 -0
  28. package/node/components/PageLayoutSection/PageLayoutSectionContainer/constants.d.ts +4 -0
  29. package/node/components/PageLayoutSection/PageLayoutSectionContainer/constants.js +7 -0
  30. package/node/components/PageLayoutSection/PageLayoutSectionContainer/index.d.ts +1 -0
  31. package/node/components/PageLayoutSection/PageLayoutSectionContainer/index.js +5 -0
  32. package/node/components/PageLayoutSection/PageLayoutSectionContainer/styles.d.ts +5 -0
  33. package/node/components/PageLayoutSection/PageLayoutSectionContainer/styles.js +54 -0
  34. package/node/components/PageLayoutSection/index.d.ts +2 -0
  35. package/node/components/PageLayoutSection/index.js +7 -0
  36. package/node/components/PageLayoutSection/public.d.ts +2 -0
  37. package/node/components/PageLayoutSection/public.js +7 -0
  38. package/node/components/PageLayoutSection/styles.d.ts +9 -0
  39. package/node/components/PageLayoutSection/styles.js +24 -0
  40. package/node/components/index.d.ts +1 -0
  41. package/node/components/index.js +5 -2
  42. package/node/hook-form/EditableText/EditableText.d.ts +10 -1
  43. package/node/hook-form/EditableText/EditableText.js +16 -2
  44. package/node/hook-form/EditableText/constants.d.ts +3 -0
  45. package/node/hook-form/EditableText/constants.js +5 -1
  46. package/node/hook-form/EditableText/styles.js +9 -0
  47. package/package.json +1 -1
@@ -0,0 +1,21 @@
1
+ import { type ReactNode } from 'react';
2
+ export type PageLayoutSectionProps = {
3
+ children: ReactNode;
4
+ /**
5
+ * Название класса, применяется к корневому компоненту
6
+ */
7
+ className?: string;
8
+ };
9
+ /**
10
+ * Секция страницы. На десктопе между секциями отображается разделитель или отступ. На мобильных разрешениях секции оформляются как карточки.
11
+ *
12
+ * @example
13
+ * <PageLayout content={
14
+ * <PageLayoutSectionContainer>
15
+ * <PageLayoutSection>
16
+ * Секция 1
17
+ * </PageLayoutSection>
18
+ * </PageLayoutSectionContainer>
19
+ * } />
20
+ */
21
+ export declare const PageLayoutSection: import("react").ForwardRefExoticComponent<PageLayoutSectionProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from 'react';
3
+ import { Section, SectionInner } from './styles';
4
+ /**
5
+ * Секция страницы. На десктопе между секциями отображается разделитель или отступ. На мобильных разрешениях секции оформляются как карточки.
6
+ *
7
+ * @example
8
+ * <PageLayout content={
9
+ * <PageLayoutSectionContainer>
10
+ * <PageLayoutSection>
11
+ * Секция 1
12
+ * </PageLayoutSection>
13
+ * </PageLayoutSectionContainer>
14
+ * } />
15
+ */
16
+ export const PageLayoutSection = forwardRef((props, ref) => {
17
+ const { children, className } = props;
18
+ return (_jsx(Section, { className: className, ref: ref, children: _jsx(SectionInner, { children: children }) }));
19
+ });
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from 'react';
2
+ export type PageLayoutSectionContainerProps = {
3
+ children: ReactNode;
4
+ /**
5
+ * Название класса, применяется к корневому компоненту
6
+ */
7
+ className?: string;
8
+ /**
9
+ * На десктопе между секциями отображается разделитель; на мобиле по-прежнему карточки с отступами между ними.
10
+ */
11
+ isShowDivider?: boolean;
12
+ };
13
+ /**
14
+ * Контейнер для секций страницы.
15
+ *
16
+ * @example
17
+ * <PageLayout content={
18
+ * <PageLayoutSectionContainer>
19
+ * <PageLayoutSection>
20
+ * Секция 1
21
+ * </PageLayoutSection>
22
+ * </PageLayoutSectionContainer>
23
+ * } />
24
+ */
25
+ export declare const PageLayoutSectionContainer: ({ children, className, isShowDivider, }: PageLayoutSectionContainerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext, useMemo } from 'react';
3
+ import { PageContext } from '../../PageContext';
4
+ import { classNames } from '../../utils/classNames';
5
+ import { pageLayoutSectionContainerClassnames } from './constants';
6
+ import { SectionContainer } from './styles';
7
+ /**
8
+ * Контейнер для секций страницы.
9
+ *
10
+ * @example
11
+ * <PageLayout content={
12
+ * <PageLayoutSectionContainer>
13
+ * <PageLayoutSection>
14
+ * Секция 1
15
+ * </PageLayoutSection>
16
+ * </PageLayoutSectionContainer>
17
+ * } />
18
+ */
19
+ export const PageLayoutSectionContainer = ({ children, className, isShowDivider = false, }) => {
20
+ const { hasAside } = useContext(PageContext);
21
+ const classes = useMemo(() => {
22
+ return classNames(className, {
23
+ [pageLayoutSectionContainerClassnames.withAside]: hasAside,
24
+ [pageLayoutSectionContainerClassnames.withDivider]: isShowDivider,
25
+ });
26
+ }, [className, hasAside, isShowDivider]);
27
+ return _jsx(SectionContainer, { className: classes, children: children });
28
+ };
@@ -0,0 +1,4 @@
1
+ export declare const pageLayoutSectionContainerClassnames: {
2
+ withAside: string;
3
+ withDivider: string;
4
+ };
@@ -0,0 +1,4 @@
1
+ export const pageLayoutSectionContainerClassnames = {
2
+ withAside: 'page-layout-section__container_with-aside',
3
+ withDivider: 'page-layout-section__container_with-divider',
4
+ };
@@ -0,0 +1 @@
1
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1 @@
1
+ export { PageLayoutSectionContainer, } from './PageLayoutSectionContainer';
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export declare const SectionContainer: import("../../styled").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,51 @@
1
+ import { styled } from '../../styled';
2
+ import { pageLayoutSectionContainerClassnames } from './constants';
3
+ export const SectionContainer = styled.div `
4
+ overflow-y: auto;
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: ${({ theme }) => theme.spacing(6)};
8
+
9
+ padding-top: 0;
10
+ padding-bottom: ${({ theme }) => theme.spacing(4)};
11
+
12
+ border-top: none;
13
+
14
+ &.${pageLayoutSectionContainerClassnames.withAside} {
15
+ padding-top: ${({ theme }) => theme.spacing(4)};
16
+
17
+ border-top: ${({ theme }) => `1px solid ${theme.palette.grey[300]}`};
18
+ }
19
+
20
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
21
+ gap: ${({ theme }) => theme.spacing(5)};
22
+ }
23
+
24
+ ${({ theme }) => theme.breakpoints.up('sm')} {
25
+ &.${pageLayoutSectionContainerClassnames.withDivider} {
26
+ & > :not(:last-child)::after {
27
+ content: '';
28
+
29
+ display: block;
30
+
31
+ width: 100%;
32
+ height: 1px;
33
+ margin-top: ${({ theme }) => theme.spacing(6)};
34
+
35
+ background-color: ${({ theme }) => theme.palette.grey[300]};
36
+ }
37
+ }
38
+ }
39
+
40
+ ${({ theme }) => theme.breakpoints.down('sm')} {
41
+ overflow: unset;
42
+ gap: ${({ theme }) => theme.spacing(4)};
43
+ order: 4;
44
+
45
+ &.${pageLayoutSectionContainerClassnames.withAside} {
46
+ padding-top: 0;
47
+
48
+ border-top: none;
49
+ }
50
+ }
51
+ `;
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, type PageLayoutSectionProps, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, } from './PageLayoutSectionContainer';
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, type PageLayoutSectionProps, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, } from './PageLayoutSectionContainer';
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ export declare const Section: import("../styled").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<HTMLElement>, HTMLElement>, {}>;
6
+ export declare const SectionInner: import("../styled").StyledComponent<{
7
+ theme?: import("@emotion/react").Theme | undefined;
8
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -0,0 +1,21 @@
1
+ import { styled } from '../styled';
2
+ export const Section = styled.section `
3
+ ${({ theme }) => theme.breakpoints.down('sm')} {
4
+ margin: ${({ theme }) => theme.spacing(0, 4)};
5
+
6
+ background-color: ${({ theme }) => theme.palette.background.default};
7
+ border: 1px solid ${({ theme }) => theme.palette.grey[300]};
8
+ border-radius: ${({ theme }) => theme.shape.medium};
9
+ }
10
+ `;
11
+ export const SectionInner = styled.div `
12
+ padding: ${({ theme }) => theme.spacing(0, 6)};
13
+
14
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
15
+ padding: ${({ theme }) => theme.spacing(0, 4)};
16
+ }
17
+
18
+ ${({ theme }) => theme.breakpoints.down('sm')} {
19
+ padding: ${({ theme }) => theme.spacing(4)};
20
+ }
21
+ `;
@@ -146,6 +146,7 @@ export * from './OverflowTypography';
146
146
  export { PageAlert, type PageAlertProps, } from './PageAlert';
147
147
  export { PageAside, type PageAsideProps, } from './PageAside';
148
148
  export { PageLayout, type PageLayoutProps, } from './PageLayout';
149
+ export { PageLayoutSection, type PageLayoutSectionProps, PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSection';
149
150
  export { PageAsideBlock, type PageAsideBlockProps, } from './PageAsideBlock';
150
151
  export { PageContent, PageContentHeader, PageContentHeaderActions, type PageContentHeaderActionsProps, type PageContentHeaderProps, type PageContentProps, pageContentClassnames, } from './PageContent';
151
152
  export { PageContext, type PageContextProps, PageContextProvider, } from './PageContext';
@@ -145,6 +145,7 @@ export * from './OverflowTypography';
145
145
  export { PageAlert, } from './PageAlert';
146
146
  export { PageAside, } from './PageAside';
147
147
  export { PageLayout, } from './PageLayout';
148
+ export { PageLayoutSection, PageLayoutSectionContainer, } from './PageLayoutSection';
148
149
  export { PageAsideBlock, } from './PageAsideBlock';
149
150
  export { PageContent, PageContentHeader, PageContentHeaderActions, pageContentClassnames, } from './PageContent';
150
151
  export { PageContext, PageContextProvider, } from './PageContext';
@@ -2,6 +2,7 @@ import { type ReactElement, type ReactNode } from 'react';
2
2
  import { type UseFormReturn } from '../useForm';
3
3
  import { type FIELD_NAME } from './constants';
4
4
  import type { FormValues, ValidationFn } from './types';
5
+ export type ShowEditIconMode = 'always' | 'none' | 'onHover';
5
6
  export type EditableTextProps<TValue = string> = {
6
7
  /**
7
8
  * Название класса, применяется к корневому компоненту
@@ -13,10 +14,18 @@ export type EditableTextProps<TValue = string> = {
13
14
  */
14
15
  initialValue?: TValue;
15
16
  /**
16
- * Если false, иконка редактирования не будет отображаться
17
+ * Если false, иконка редактирования не будет отображаться.
18
+ * Для новых сценариев предпочтительнее `showEditIcon`.
19
+ * Если переданы оба параметра, для отображения иконки используется `showEditIcon`.
17
20
  * @default true
18
21
  */
19
22
  isShowIcon?: boolean;
23
+ /**
24
+ * Режим отображения иконки редактирования (аналогично `CopyTypography.showCopyIcon`).
25
+ * Имеет приоритет над `isShowIcon`.
26
+ * @default если не задан — наследуется из `isShowIcon` (true → always, false → none)
27
+ */
28
+ showEditIcon?: ShowEditIconMode;
20
29
  /**
21
30
  * Если true, будет отображаться лоадер
22
31
  */
@@ -1,17 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Tooltip } from '../../components/Tooltip';
3
+ import { classNames } from '../../components/utils/classNames';
4
+ import { editableTextClassnames } from './constants';
3
5
  import { EditingForm } from './EditingForm';
4
6
  import { DisplayValue, StyledEditIcon, StyledLoader, StyledPopover, } from './styles';
5
7
  import { useLogic } from './useLogic';
8
+ const getShowEditIconMode = ({ showEditIcon, isShowIcon = true, }) => {
9
+ if (showEditIcon !== undefined) {
10
+ return showEditIcon;
11
+ }
12
+ return isShowIcon === false ? 'none' : 'always';
13
+ };
6
14
  // biome-ignore lint/complexity/noUselessTypeConstraint: Фикс типизации в тестах
7
15
  export const EditableText = (props) => {
8
16
  const { isIconOnLeft, onClose, displayValueProps, tooltipProps, popoverProps, } = useLogic(props);
9
- const { className, children, isShowIcon = true, isLoading, iconPosition = 'right', ...restProps } = props;
17
+ const { className, children, isShowIcon = true, isLoading, showEditIcon, iconPosition = 'right', ...restProps } = props;
18
+ const showEditIconMode = getShowEditIconMode({ showEditIcon, isShowIcon });
10
19
  const renderIcon = () => {
11
20
  if (isLoading) {
12
21
  return _jsx(StyledLoader, { "$iconPosition": iconPosition });
13
22
  }
14
- return isShowIcon ? _jsx(StyledEditIcon, { "$iconPosition": iconPosition }) : null;
23
+ if (showEditIconMode === 'none') {
24
+ return null;
25
+ }
26
+ return (_jsx(StyledEditIcon, { "$iconPosition": iconPosition, className: classNames({
27
+ [editableTextClassnames.showIconOnHover]: showEditIconMode === 'onHover',
28
+ }) }));
15
29
  };
16
30
  return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { ...tooltipProps, placement: "bottom", children: _jsxs(DisplayValue, { "$isLoading": isLoading, className: className, variant: "inherit", ...displayValueProps, children: [isIconOnLeft && renderIcon(), children, !isIconOnLeft && renderIcon()] }) }), _jsx(StyledPopover, { anchorOrigin: {
17
31
  vertical: 'bottom',
@@ -1 +1,4 @@
1
1
  export declare const FIELD_NAME = "editableField";
2
+ export declare const editableTextClassnames: {
3
+ showIconOnHover: string;
4
+ };
@@ -1 +1,5 @@
1
+ import { createUIKitClassname } from '../../components/utils/createUIKitClassname';
1
2
  export const FIELD_NAME = 'editableField';
3
+ export const editableTextClassnames = {
4
+ showIconOnHover: createUIKitClassname('editable-text__edit-icon_show-on-hover'),
5
+ };
@@ -3,6 +3,7 @@ import { Popover } from '../../components/Popover';
3
3
  import { styled } from '../../components/styled';
4
4
  import { Typography } from '../../components/Typography';
5
5
  import { EditOutlineMd } from '../../icons/EditOutlineMd';
6
+ import { editableTextClassnames } from './constants';
6
7
  const getBackgroundColor = (theme, $isEdited, $isLoading) => {
7
8
  if ($isEdited) {
8
9
  return theme.palette.primary[100];
@@ -33,6 +34,10 @@ export const DisplayValue = styled(Typography, {
33
34
  cursor: ${({ $isLoading }) => ($isLoading ? 'default' : 'pointer')};
34
35
 
35
36
  text-decoration: ${({ $isLoading }) => $isLoading ? 'inherit' : 'underline'};
37
+
38
+ .${editableTextClassnames.showIconOnHover} {
39
+ display: unset;
40
+ }
36
41
  }
37
42
  `;
38
43
  export const StyledEditIcon = styled(EditOutlineMd, {
@@ -49,6 +54,10 @@ export const StyledEditIcon = styled(EditOutlineMd, {
49
54
  margin-left: ${({ $iconPosition, theme }) => $iconPosition === 'right' ? theme.spacing(1) : ''};
50
55
 
51
56
  font-size: inherit;
57
+
58
+ &.${editableTextClassnames.showIconOnHover} {
59
+ display: none;
60
+ }
52
61
  `;
53
62
  export const StyledLoader = styled(Loader, {
54
63
  shouldForwardProp: (prop) => !['$iconPosition'].includes(prop),
@@ -0,0 +1,21 @@
1
+ import { type ReactNode } from 'react';
2
+ export type PageLayoutSectionProps = {
3
+ children: ReactNode;
4
+ /**
5
+ * Название класса, применяется к корневому компоненту
6
+ */
7
+ className?: string;
8
+ };
9
+ /**
10
+ * Секция страницы. На десктопе между секциями отображается разделитель или отступ. На мобильных разрешениях секции оформляются как карточки.
11
+ *
12
+ * @example
13
+ * <PageLayout content={
14
+ * <PageLayoutSectionContainer>
15
+ * <PageLayoutSection>
16
+ * Секция 1
17
+ * </PageLayoutSection>
18
+ * </PageLayoutSectionContainer>
19
+ * } />
20
+ */
21
+ export declare const PageLayoutSection: import("react").ForwardRefExoticComponent<PageLayoutSectionProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageLayoutSection = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const styles_1 = require("./styles");
7
+ /**
8
+ * Секция страницы. На десктопе между секциями отображается разделитель или отступ. На мобильных разрешениях секции оформляются как карточки.
9
+ *
10
+ * @example
11
+ * <PageLayout content={
12
+ * <PageLayoutSectionContainer>
13
+ * <PageLayoutSection>
14
+ * Секция 1
15
+ * </PageLayoutSection>
16
+ * </PageLayoutSectionContainer>
17
+ * } />
18
+ */
19
+ exports.PageLayoutSection = (0, react_1.forwardRef)((props, ref) => {
20
+ const { children, className } = props;
21
+ return ((0, jsx_runtime_1.jsx)(styles_1.Section, { className: className, ref: ref, children: (0, jsx_runtime_1.jsx)(styles_1.SectionInner, { children: children }) }));
22
+ });
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from 'react';
2
+ export type PageLayoutSectionContainerProps = {
3
+ children: ReactNode;
4
+ /**
5
+ * Название класса, применяется к корневому компоненту
6
+ */
7
+ className?: string;
8
+ /**
9
+ * На десктопе между секциями отображается разделитель; на мобиле по-прежнему карточки с отступами между ними.
10
+ */
11
+ isShowDivider?: boolean;
12
+ };
13
+ /**
14
+ * Контейнер для секций страницы.
15
+ *
16
+ * @example
17
+ * <PageLayout content={
18
+ * <PageLayoutSectionContainer>
19
+ * <PageLayoutSection>
20
+ * Секция 1
21
+ * </PageLayoutSection>
22
+ * </PageLayoutSectionContainer>
23
+ * } />
24
+ */
25
+ export declare const PageLayoutSectionContainer: ({ children, className, isShowDivider, }: PageLayoutSectionContainerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageLayoutSectionContainer = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const PageContext_1 = require("../../PageContext");
7
+ const classNames_1 = require("../../utils/classNames");
8
+ const constants_1 = require("./constants");
9
+ const styles_1 = require("./styles");
10
+ /**
11
+ * Контейнер для секций страницы.
12
+ *
13
+ * @example
14
+ * <PageLayout content={
15
+ * <PageLayoutSectionContainer>
16
+ * <PageLayoutSection>
17
+ * Секция 1
18
+ * </PageLayoutSection>
19
+ * </PageLayoutSectionContainer>
20
+ * } />
21
+ */
22
+ const PageLayoutSectionContainer = ({ children, className, isShowDivider = false, }) => {
23
+ const { hasAside } = (0, react_1.useContext)(PageContext_1.PageContext);
24
+ const classes = (0, react_1.useMemo)(() => {
25
+ return (0, classNames_1.classNames)(className, {
26
+ [constants_1.pageLayoutSectionContainerClassnames.withAside]: hasAside,
27
+ [constants_1.pageLayoutSectionContainerClassnames.withDivider]: isShowDivider,
28
+ });
29
+ }, [className, hasAside, isShowDivider]);
30
+ return (0, jsx_runtime_1.jsx)(styles_1.SectionContainer, { className: classes, children: children });
31
+ };
32
+ exports.PageLayoutSectionContainer = PageLayoutSectionContainer;
@@ -0,0 +1,4 @@
1
+ export declare const pageLayoutSectionContainerClassnames: {
2
+ withAside: string;
3
+ withDivider: string;
4
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pageLayoutSectionContainerClassnames = void 0;
4
+ exports.pageLayoutSectionContainerClassnames = {
5
+ withAside: 'page-layout-section__container_with-aside',
6
+ withDivider: 'page-layout-section__container_with-divider',
7
+ };
@@ -0,0 +1 @@
1
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageLayoutSectionContainer = void 0;
4
+ var PageLayoutSectionContainer_1 = require("./PageLayoutSectionContainer");
5
+ Object.defineProperty(exports, "PageLayoutSectionContainer", { enumerable: true, get: function () { return PageLayoutSectionContainer_1.PageLayoutSectionContainer; } });
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export declare const SectionContainer: 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,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SectionContainer = void 0;
4
+ const styled_1 = require("../../styled");
5
+ const constants_1 = require("./constants");
6
+ exports.SectionContainer = styled_1.styled.div `
7
+ overflow-y: auto;
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: ${({ theme }) => theme.spacing(6)};
11
+
12
+ padding-top: 0;
13
+ padding-bottom: ${({ theme }) => theme.spacing(4)};
14
+
15
+ border-top: none;
16
+
17
+ &.${constants_1.pageLayoutSectionContainerClassnames.withAside} {
18
+ padding-top: ${({ theme }) => theme.spacing(4)};
19
+
20
+ border-top: ${({ theme }) => `1px solid ${theme.palette.grey[300]}`};
21
+ }
22
+
23
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
24
+ gap: ${({ theme }) => theme.spacing(5)};
25
+ }
26
+
27
+ ${({ theme }) => theme.breakpoints.up('sm')} {
28
+ &.${constants_1.pageLayoutSectionContainerClassnames.withDivider} {
29
+ & > :not(:last-child)::after {
30
+ content: '';
31
+
32
+ display: block;
33
+
34
+ width: 100%;
35
+ height: 1px;
36
+ margin-top: ${({ theme }) => theme.spacing(6)};
37
+
38
+ background-color: ${({ theme }) => theme.palette.grey[300]};
39
+ }
40
+ }
41
+ }
42
+
43
+ ${({ theme }) => theme.breakpoints.down('sm')} {
44
+ overflow: unset;
45
+ gap: ${({ theme }) => theme.spacing(4)};
46
+ order: 4;
47
+
48
+ &.${constants_1.pageLayoutSectionContainerClassnames.withAside} {
49
+ padding-top: 0;
50
+
51
+ border-top: none;
52
+ }
53
+ }
54
+ `;
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, type PageLayoutSectionProps, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageLayoutSectionContainer = exports.PageLayoutSection = void 0;
4
+ var PageLayoutSection_1 = require("./PageLayoutSection");
5
+ Object.defineProperty(exports, "PageLayoutSection", { enumerable: true, get: function () { return PageLayoutSection_1.PageLayoutSection; } });
6
+ var PageLayoutSectionContainer_1 = require("./PageLayoutSectionContainer");
7
+ Object.defineProperty(exports, "PageLayoutSectionContainer", { enumerable: true, get: function () { return PageLayoutSectionContainer_1.PageLayoutSectionContainer; } });
@@ -0,0 +1,2 @@
1
+ export { PageLayoutSection, type PageLayoutSectionProps, } from './PageLayoutSection';
2
+ export { PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSectionContainer';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageLayoutSectionContainer = exports.PageLayoutSection = void 0;
4
+ var PageLayoutSection_1 = require("./PageLayoutSection");
5
+ Object.defineProperty(exports, "PageLayoutSection", { enumerable: true, get: function () { return PageLayoutSection_1.PageLayoutSection; } });
6
+ var PageLayoutSectionContainer_1 = require("./PageLayoutSectionContainer");
7
+ Object.defineProperty(exports, "PageLayoutSectionContainer", { enumerable: true, get: function () { return PageLayoutSectionContainer_1.PageLayoutSectionContainer; } });
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ export declare const Section: 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<HTMLElement>, HTMLElement>, {}>;
6
+ export declare const SectionInner: import("@emotion/styled/dist/declarations/src/types").StyledComponent<{
7
+ theme?: import("@emotion/react").Theme | undefined;
8
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SectionInner = exports.Section = void 0;
4
+ const styled_1 = require("../styled");
5
+ exports.Section = styled_1.styled.section `
6
+ ${({ theme }) => theme.breakpoints.down('sm')} {
7
+ margin: ${({ theme }) => theme.spacing(0, 4)};
8
+
9
+ background-color: ${({ theme }) => theme.palette.background.default};
10
+ border: 1px solid ${({ theme }) => theme.palette.grey[300]};
11
+ border-radius: ${({ theme }) => theme.shape.medium};
12
+ }
13
+ `;
14
+ exports.SectionInner = styled_1.styled.div `
15
+ padding: ${({ theme }) => theme.spacing(0, 6)};
16
+
17
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
18
+ padding: ${({ theme }) => theme.spacing(0, 4)};
19
+ }
20
+
21
+ ${({ theme }) => theme.breakpoints.down('sm')} {
22
+ padding: ${({ theme }) => theme.spacing(4)};
23
+ }
24
+ `;
@@ -146,6 +146,7 @@ export * from './OverflowTypography';
146
146
  export { PageAlert, type PageAlertProps, } from './PageAlert';
147
147
  export { PageAside, type PageAsideProps, } from './PageAside';
148
148
  export { PageLayout, type PageLayoutProps, } from './PageLayout';
149
+ export { PageLayoutSection, type PageLayoutSectionProps, PageLayoutSectionContainer, type PageLayoutSectionContainerProps, } from './PageLayoutSection';
149
150
  export { PageAsideBlock, type PageAsideBlockProps, } from './PageAsideBlock';
150
151
  export { PageContent, PageContentHeader, PageContentHeaderActions, type PageContentHeaderActionsProps, type PageContentHeaderProps, type PageContentProps, pageContentClassnames, } from './PageContent';
151
152
  export { PageContext, type PageContextProps, PageContextProvider, } from './PageContext';
@@ -16,8 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.FileUploaderFile = exports.FileUploaderDropzone = exports.FileUploader = exports.Filename = exports.Fieldset = exports.Zoom = exports.Slide = exports.Grow = exports.Fade = exports.expansionPanelClassnames = exports.ExpansionPanel = exports.EmailOrPhoneField = exports.EmailField = exports.DescriptionList = exports.DescriptionCell = exports.datePickerClassnames = exports.DatePicker = exports.DataGridMinimalisticPagination = exports.DataGridSecondaryActionsSkeleton = exports.DataGridSecondaryActions = exports.DataGridMainActions = exports.DataGridActionCell = exports.SidebarContext = exports.SidebarSkeleton = exports.SidebarPopover = exports.MenuSidebarButton = exports.SidebarCounter = exports.SidebarButton = exports.DashboardContext = exports.DashboardLayout = exports.DashboardAlert = exports.Counter = exports.CopyTypography = exports.confirmActionClassnames = exports.ConfirmAction = exports.ComplianceStatus = exports.CodeField = exports.BulletListItem = exports.BulletListInlineItem = exports.BulletList = exports.Breadcrumbs = exports.AvatarGroup = exports.Avatar = exports.AutoSaveIndicator = exports.AsyncAutocomplete = exports.Alert = exports.alertClassnames = exports.AddressAutocomplete = exports.useMainActions = exports.ActionGroup = void 0;
18
18
  exports.NumberedListItem = exports.NumberedList = exports.notFoundPageClassnames = exports.NotFoundPage = exports.MenuOrganizationSkeleton = exports.MenuOrganization = exports.DateRangePicker = exports.DataGridColumnHintIcon = exports.DataGridInfinite = exports.DataGrid = exports.MinimalisticPagination = exports.loaderClassnames = exports.Loader = exports.Link = exports.InfiniteDataList = exports.InputGroup = exports.Iframe = exports.useViewportType = exports.useUpdateEffect = exports.useToggle = exports.useStickyButton = exports.useSet = exports.useSecondsCountdown = exports.useScrollManagement = exports.useRadioGroup = exports.usePopoverAnimation = exports.usePopover = exports.useMenu = exports.useLocalStorage = exports.useLocaleDateTimeFormat = exports.useLoadingState = exports.useInterval = exports.useInputPopover = exports.useForwardedRef = exports.useFocusAwayEffect = exports.useFirstMountState = exports.useFeatureFlags = exports.useEscapeClickEffect = exports.useClickAwayEffect = exports.useCheckControlled = exports.useAsyncOptions = exports.HintIcon = exports.GuidTypography = exports.previewFileUploaderClassnames = exports.fileUploaderClassnames = exports.PreviewFileUploaderFile = exports.PreviewFileUploaderDropZone = exports.PreviewFileUploader = exports.usePreviewFileUploader = exports.useFileUploader = void 0;
19
- exports.getInertProps = exports.redirectToLink = exports.createUIKitClassname = exports.classNames = exports.TreeLikeList = exports.TreeLikeAutocomplete = exports.TreeAutocomplete = exports.TreeList = exports.MultipleTreeList = exports.UNSTABLE_SecondsCountdownService = exports.svgIconClassnames = exports.SvgIcon = exports.StepSlider = exports.StepperWizard = exports.staticDaysCalendarClassnames = exports.StaticDaysCalendar = exports.Skeleton = exports.SearchField = exports.ScrollToTopButton = exports.RadioGroupContext = exports.RadioGroup = exports.RadioField = exports.radioCardClassnames = exports.RadioCard = exports.Radio = exports.radioClassnames = exports.LoadingPlaceholder = exports.Placeholder = exports.useHidePersonalData = exports.PersonalData = exports.Pagination = exports.PageLayoutLoader = exports.PagePinnableAside = exports.PageLayoutFooter = exports.PageLayoutContainer = exports.PageActions = exports.PageActionSkeleton = exports.PageHeader = exports.pageHeaderClassnames = exports.PageContextProvider = exports.PageContext = exports.pageContentClassnames = exports.PageContentHeaderActions = exports.PageContentHeader = exports.PageContent = exports.PageAsideBlock = exports.PageLayout = exports.PageAside = exports.PageAlert = exports.NumberField = void 0;
20
- exports.WelcomeScreen = void 0;
19
+ exports.createUIKitClassname = exports.classNames = exports.TreeLikeList = exports.TreeLikeAutocomplete = exports.TreeAutocomplete = exports.TreeList = exports.MultipleTreeList = exports.UNSTABLE_SecondsCountdownService = exports.svgIconClassnames = exports.SvgIcon = exports.StepSlider = exports.StepperWizard = exports.staticDaysCalendarClassnames = exports.StaticDaysCalendar = exports.Skeleton = exports.SearchField = exports.ScrollToTopButton = exports.RadioGroupContext = exports.RadioGroup = exports.RadioField = exports.radioCardClassnames = exports.RadioCard = exports.Radio = exports.radioClassnames = exports.LoadingPlaceholder = exports.Placeholder = exports.useHidePersonalData = exports.PersonalData = exports.Pagination = exports.PageLayoutLoader = exports.PagePinnableAside = exports.PageLayoutFooter = exports.PageLayoutContainer = exports.PageActions = exports.PageActionSkeleton = exports.PageHeader = exports.pageHeaderClassnames = exports.PageContextProvider = exports.PageContext = exports.pageContentClassnames = exports.PageContentHeaderActions = exports.PageContentHeader = exports.PageContent = exports.PageAsideBlock = exports.PageLayoutSectionContainer = exports.PageLayoutSection = exports.PageLayout = exports.PageAside = exports.PageAlert = exports.NumberField = void 0;
20
+ exports.WelcomeScreen = exports.getInertProps = exports.redirectToLink = void 0;
21
21
  __exportStar(require("./Accordion"), exports);
22
22
  var ActionGroup_1 = require("./ActionGroup");
23
23
  Object.defineProperty(exports, "ActionGroup", { enumerable: true, get: function () { return ActionGroup_1.ActionGroup; } });
@@ -269,6 +269,9 @@ var PageAside_1 = require("./PageAside");
269
269
  Object.defineProperty(exports, "PageAside", { enumerable: true, get: function () { return PageAside_1.PageAside; } });
270
270
  var PageLayout_1 = require("./PageLayout");
271
271
  Object.defineProperty(exports, "PageLayout", { enumerable: true, get: function () { return PageLayout_1.PageLayout; } });
272
+ var PageLayoutSection_1 = require("./PageLayoutSection");
273
+ Object.defineProperty(exports, "PageLayoutSection", { enumerable: true, get: function () { return PageLayoutSection_1.PageLayoutSection; } });
274
+ Object.defineProperty(exports, "PageLayoutSectionContainer", { enumerable: true, get: function () { return PageLayoutSection_1.PageLayoutSectionContainer; } });
272
275
  var PageAsideBlock_1 = require("./PageAsideBlock");
273
276
  Object.defineProperty(exports, "PageAsideBlock", { enumerable: true, get: function () { return PageAsideBlock_1.PageAsideBlock; } });
274
277
  var PageContent_1 = require("./PageContent");
@@ -2,6 +2,7 @@ import { type ReactElement, type ReactNode } from 'react';
2
2
  import { type UseFormReturn } from '../useForm';
3
3
  import { type FIELD_NAME } from './constants';
4
4
  import type { FormValues, ValidationFn } from './types';
5
+ export type ShowEditIconMode = 'always' | 'none' | 'onHover';
5
6
  export type EditableTextProps<TValue = string> = {
6
7
  /**
7
8
  * Название класса, применяется к корневому компоненту
@@ -13,10 +14,18 @@ export type EditableTextProps<TValue = string> = {
13
14
  */
14
15
  initialValue?: TValue;
15
16
  /**
16
- * Если false, иконка редактирования не будет отображаться
17
+ * Если false, иконка редактирования не будет отображаться.
18
+ * Для новых сценариев предпочтительнее `showEditIcon`.
19
+ * Если переданы оба параметра, для отображения иконки используется `showEditIcon`.
17
20
  * @default true
18
21
  */
19
22
  isShowIcon?: boolean;
23
+ /**
24
+ * Режим отображения иконки редактирования (аналогично `CopyTypography.showCopyIcon`).
25
+ * Имеет приоритет над `isShowIcon`.
26
+ * @default если не задан — наследуется из `isShowIcon` (true → always, false → none)
27
+ */
28
+ showEditIcon?: ShowEditIconMode;
20
29
  /**
21
30
  * Если true, будет отображаться лоадер
22
31
  */
@@ -3,18 +3,32 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EditableText = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const Tooltip_1 = require("../../components/Tooltip");
6
+ const classNames_1 = require("../../components/utils/classNames");
7
+ const constants_1 = require("./constants");
6
8
  const EditingForm_1 = require("./EditingForm");
7
9
  const styles_1 = require("./styles");
8
10
  const useLogic_1 = require("./useLogic");
11
+ const getShowEditIconMode = ({ showEditIcon, isShowIcon = true, }) => {
12
+ if (showEditIcon !== undefined) {
13
+ return showEditIcon;
14
+ }
15
+ return isShowIcon === false ? 'none' : 'always';
16
+ };
9
17
  // biome-ignore lint/complexity/noUselessTypeConstraint: Фикс типизации в тестах
10
18
  const EditableText = (props) => {
11
19
  const { isIconOnLeft, onClose, displayValueProps, tooltipProps, popoverProps, } = (0, useLogic_1.useLogic)(props);
12
- const { className, children, isShowIcon = true, isLoading, iconPosition = 'right', ...restProps } = props;
20
+ const { className, children, isShowIcon = true, isLoading, showEditIcon, iconPosition = 'right', ...restProps } = props;
21
+ const showEditIconMode = getShowEditIconMode({ showEditIcon, isShowIcon });
13
22
  const renderIcon = () => {
14
23
  if (isLoading) {
15
24
  return (0, jsx_runtime_1.jsx)(styles_1.StyledLoader, { "$iconPosition": iconPosition });
16
25
  }
17
- return isShowIcon ? (0, jsx_runtime_1.jsx)(styles_1.StyledEditIcon, { "$iconPosition": iconPosition }) : null;
26
+ if (showEditIconMode === 'none') {
27
+ return null;
28
+ }
29
+ return ((0, jsx_runtime_1.jsx)(styles_1.StyledEditIcon, { "$iconPosition": iconPosition, className: (0, classNames_1.classNames)({
30
+ [constants_1.editableTextClassnames.showIconOnHover]: showEditIconMode === 'onHover',
31
+ }) }));
18
32
  };
19
33
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Tooltip_1.Tooltip, { ...tooltipProps, placement: "bottom", children: (0, jsx_runtime_1.jsxs)(styles_1.DisplayValue, { "$isLoading": isLoading, className: className, variant: "inherit", ...displayValueProps, children: [isIconOnLeft && renderIcon(), children, !isIconOnLeft && renderIcon()] }) }), (0, jsx_runtime_1.jsx)(styles_1.StyledPopover, { anchorOrigin: {
20
34
  vertical: 'bottom',
@@ -1 +1,4 @@
1
1
  export declare const FIELD_NAME = "editableField";
2
+ export declare const editableTextClassnames: {
3
+ showIconOnHover: string;
4
+ };
@@ -1,4 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FIELD_NAME = void 0;
3
+ exports.editableTextClassnames = exports.FIELD_NAME = void 0;
4
+ const createUIKitClassname_1 = require("../../components/utils/createUIKitClassname");
4
5
  exports.FIELD_NAME = 'editableField';
6
+ exports.editableTextClassnames = {
7
+ showIconOnHover: (0, createUIKitClassname_1.createUIKitClassname)('editable-text__edit-icon_show-on-hover'),
8
+ };
@@ -6,6 +6,7 @@ const Popover_1 = require("../../components/Popover");
6
6
  const styled_1 = require("../../components/styled");
7
7
  const Typography_1 = require("../../components/Typography");
8
8
  const EditOutlineMd_1 = require("../../icons/EditOutlineMd");
9
+ const constants_1 = require("./constants");
9
10
  const getBackgroundColor = (theme, $isEdited, $isLoading) => {
10
11
  if ($isEdited) {
11
12
  return theme.palette.primary[100];
@@ -36,6 +37,10 @@ exports.DisplayValue = (0, styled_1.styled)(Typography_1.Typography, {
36
37
  cursor: ${({ $isLoading }) => ($isLoading ? 'default' : 'pointer')};
37
38
 
38
39
  text-decoration: ${({ $isLoading }) => $isLoading ? 'inherit' : 'underline'};
40
+
41
+ .${constants_1.editableTextClassnames.showIconOnHover} {
42
+ display: unset;
43
+ }
39
44
  }
40
45
  `;
41
46
  exports.StyledEditIcon = (0, styled_1.styled)(EditOutlineMd_1.EditOutlineMd, {
@@ -52,6 +57,10 @@ exports.StyledEditIcon = (0, styled_1.styled)(EditOutlineMd_1.EditOutlineMd, {
52
57
  margin-left: ${({ $iconPosition, theme }) => $iconPosition === 'right' ? theme.spacing(1) : ''};
53
58
 
54
59
  font-size: inherit;
60
+
61
+ &.${constants_1.editableTextClassnames.showIconOnHover} {
62
+ display: none;
63
+ }
55
64
  `;
56
65
  exports.StyledLoader = (0, styled_1.styled)(Loader_1.Loader, {
57
66
  shouldForwardProp: (prop) => !['$iconPosition'].includes(prop),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astral/ui",
3
- "version": "4.39.0",
3
+ "version": "4.41.0",
4
4
  "browser": "./index.js",
5
5
  "main": "./node/index.js",
6
6
  "dependencies": {