@evergis/react 4.0.114 → 4.0.116

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.
@@ -43,3 +43,17 @@ export declare const DEFAULT_DROPDOWN_WIDTH = 312;
43
43
  export declare const DEFAULT_FILTER_PADDING = 12;
44
44
  /** Базовый отступ обёртки контейнера. Снимается, когда контейнер занимает ячейку целиком. */
45
45
  export declare const BASE_CONTAINER_STYLE: CSSObject;
46
+ /**
47
+ * Маркер тела контейнера внутри `ContainerRoot` — содержимое без заголовка.
48
+ *
49
+ * Нужен, чтобы находить тело по DOM снаружи: `#<id контейнера>` теперь указывает на корень,
50
+ * то есть на пару «заголовок + тело».
51
+ */
52
+ export declare const CONTAINER_BODY_ATTRIBUTE = "data-container-body";
53
+ /**
54
+ * Заданная высота контейнера достаётся телу — за вычетом заголовка.
55
+ *
56
+ * Сама высота остаётся на корне, поэтому тело забирает остаток ячейки, а заголовок сохраняет
57
+ * `flex-shrink: 0` и не сжимается.
58
+ */
59
+ export declare const CONTAINER_BODY_FILL_STYLE: CSSObject;
@@ -2,6 +2,7 @@ export * from './useAttachmentItems';
2
2
  export * from './useAttachmentPreviewImages';
3
3
  export * from './useAutoCompleteControl';
4
4
  export * from './useContainerAttributes';
5
+ export * from './useContainerRoot';
5
6
  export * from './useEditGroupAttributes';
6
7
  export * from './useFetchImageWithAuth';
7
8
  export * from './useFetchWithAuth';
@@ -0,0 +1,29 @@
1
+ import { CSSObject } from 'styled-components';
2
+ import { CONTAINER_BODY_ATTRIBUTE } from '../constants';
3
+ import { WrapperRootProps } from './useWrapperSize';
4
+ import { ConfigContainerChild } from '../types';
5
+ interface UseContainerRootParams {
6
+ elementConfig?: ConfigContainerChild;
7
+ /** Внутренние дефолты корневой обёртки. Ссылка должна быть стабильной (константа или useMemo). */
8
+ defaults?: CSSObject;
9
+ }
10
+ /** Пропсы тела контейнера — узла с содержимым, соседнего с заголовком внутри `ContainerRoot`. */
11
+ export interface ContainerBodyProps {
12
+ [CONTAINER_BODY_ATTRIBUTE]?: string;
13
+ $sizeCss?: CSSObject;
14
+ }
15
+ export interface ContainerRootParts {
16
+ /** Пропсы корневого узла: идентификаторы, авторский `style`, размеры. */
17
+ root: WrapperRootProps;
18
+ /** Пропсы тела: маркер для поиска по DOM и доля высоты, оставшаяся от корня. */
19
+ body: ContainerBodyProps;
20
+ }
21
+ /**
22
+ * Пропсы двух узлов контейнера с заголовком: корня (`ContainerRoot`) и тела.
23
+ *
24
+ * Контейнер обязан иметь ОДИН корневой узел — иначе в строке (`options.column: false`) заголовок
25
+ * и тело становятся двумя ячейками родительского flex-row. Размеры из конфига поэтому уходят на
26
+ * корень, а тело получает лишь остаток высоты под заголовком.
27
+ */
28
+ export declare const useContainerRoot: ({ elementConfig, defaults }: UseContainerRootParams) => ContainerRootParts;
29
+ export {};
@@ -18,6 +18,18 @@ export declare const ElementValueWrapper: import('styled-components').StyledComp
18
18
  noMargin?: boolean;
19
19
  $sizeTransparent?: boolean;
20
20
  }, never>;
21
+ /**
22
+ * Единственный корневой узел контейнера: внутри — заголовок (`ExpandableTitle`) и тело.
23
+ *
24
+ * Два корня (фрагмент из заголовка и тела) ломают раскладку родителя: в строке
25
+ * (`options.column: false`) они становятся ДВУМЯ ячейками flex-row и делят её ширину между собой,
26
+ * а доля из `options.width` достаётся только телу. Поэтому `id`, `data-templatename`, авторский
27
+ * `style` и `$sizeCss` живут здесь, а не на теле — см. `useContainerRoot`.
28
+ *
29
+ * Всегда flex-колонка: заголовок и тело раньше были flex-элементами родительского `Container`,
30
+ * и блочная обёртка вернула бы схлопывание вертикальных отступов между ними.
31
+ */
32
+ export declare const ContainerRoot: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps & ContainerRootProps, never>;
21
33
  export declare const Container: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps & ContainerRootProps & {
22
34
  isTitle?: boolean;
23
35
  isColumn?: boolean;
package/dist/index.js CHANGED
@@ -3534,6 +3534,24 @@ const DEFAULT_FILTER_PADDING = 12;
3534
3534
  const BASE_CONTAINER_STYLE = {
3535
3535
  marginBottom: "1rem",
3536
3536
  };
3537
+ /**
3538
+ * Маркер тела контейнера внутри `ContainerRoot` — содержимое без заголовка.
3539
+ *
3540
+ * Нужен, чтобы находить тело по DOM снаружи: `#<id контейнера>` теперь указывает на корень,
3541
+ * то есть на пару «заголовок + тело».
3542
+ */
3543
+ const CONTAINER_BODY_ATTRIBUTE = "data-container-body";
3544
+ /**
3545
+ * Заданная высота контейнера достаётся телу — за вычетом заголовка.
3546
+ *
3547
+ * Сама высота остаётся на корне, поэтому тело забирает остаток ячейки, а заголовок сохраняет
3548
+ * `flex-shrink: 0` и не сжимается.
3549
+ */
3550
+ const CONTAINER_BODY_FILL_STYLE = {
3551
+ flex: "1 1 auto",
3552
+ minHeight: 0,
3553
+ minWidth: 0,
3554
+ };
3537
3555
 
3538
3556
  const StackBarContainer = styled(uilibGl.Flex).withConfig({ displayName: "StackBarContainer", componentId: "sc-stc97k" }) `
3539
3557
  flex-wrap: nowrap;
@@ -3809,15 +3827,16 @@ const debounce = (callback, delay) => {
3809
3827
  const MILLION = 1000000;
3810
3828
  const TEN_THOUSANDS = 10000;
3811
3829
  const THOUSAND = 1000;
3812
- const FRACTION_DIGITS = 1;
3813
- const roundTotalSum = (value) => {
3830
+ const COMPACT_FRACTION_DIGITS = 1;
3831
+ const roundTotalSum = (value, fractionDigits) => {
3814
3832
  if (!value)
3815
3833
  return "";
3834
+ const digits = fractionDigits ?? COMPACT_FRACTION_DIGITS;
3816
3835
  if (value >= MILLION) {
3817
- return `${(value / MILLION).toFixed(FRACTION_DIGITS)}M`;
3836
+ return `${(value / MILLION).toFixed(digits)}M`;
3818
3837
  }
3819
3838
  if (value >= TEN_THOUSANDS) {
3820
- return `${(value / THOUSAND).toFixed(FRACTION_DIGITS)}K`;
3839
+ return `${(value / THOUSAND).toFixed(digits)}K`;
3821
3840
  }
3822
3841
  return value;
3823
3842
  };
@@ -3962,11 +3981,14 @@ const formatNumberValue = (stringFormat, value, type, noUnits = false) => {
3962
3981
  if (scalingFactor) {
3963
3982
  currentValue *= scalingFactor;
3964
3983
  }
3965
- const compactValue = roundDigitGroup ? roundTotalSum(Number(currentValue)) : null;
3984
+ const hasRounding = !lodash.isNil(rounding);
3985
+ const compactValue = roundDigitGroup
3986
+ ? roundTotalSum(Number(currentValue), hasRounding ? rounding : undefined)
3987
+ : null;
3966
3988
  if (typeof compactValue === "string" && compactValue) {
3967
3989
  return appendUnitsLabel(compactValue, unitsLabel, noUnits);
3968
3990
  }
3969
- if ((rounding || rounding === 0) && (!isIntValue || (isIntValue && !isDefaultScaling))) {
3991
+ if (hasRounding && (!isIntValue || !isDefaultScaling)) {
3970
3992
  currentValue = currentValue && Number(currentValue).toFixed(rounding);
3971
3993
  }
3972
3994
  if (splitDigitGroup) {
@@ -4587,7 +4609,24 @@ const ElementValueWrapper = styled.div.withConfig({ displayName: "ElementValueWr
4587
4609
  }
4588
4610
  `};
4589
4611
  `;
4590
- const Container = styled(uilibGl.Flex).withConfig({ displayName: "Container", componentId: "sc-1gpmkbq" }) `
4612
+ /**
4613
+ * Единственный корневой узел контейнера: внутри — заголовок (`ExpandableTitle`) и тело.
4614
+ *
4615
+ * Два корня (фрагмент из заголовка и тела) ломают раскладку родителя: в строке
4616
+ * (`options.column: false`) они становятся ДВУМЯ ячейками flex-row и делят её ширину между собой,
4617
+ * а доля из `options.width` достаётся только телу. Поэтому `id`, `data-templatename`, авторский
4618
+ * `style` и `$sizeCss` живут здесь, а не на теле — см. `useContainerRoot`.
4619
+ *
4620
+ * Всегда flex-колонка: заголовок и тело раньше были flex-элементами родительского `Container`,
4621
+ * и блочная обёртка вернула бы схлопывание вертикальных отступов между ними.
4622
+ */
4623
+ const ContainerRoot = styled(uilibGl.Flex).withConfig({ displayName: "ContainerRoot", componentId: "sc-2j6lbd" }) `
4624
+ flex-direction: column;
4625
+ min-width: 0;
4626
+
4627
+ ${sizeCssMixin};
4628
+ `;
4629
+ const Container = styled(uilibGl.Flex).withConfig({ displayName: "Container", componentId: "sc-1o8dsu2" }) `
4591
4630
  flex-direction: column;
4592
4631
  width: 100%;
4593
4632
 
@@ -4641,7 +4680,7 @@ const Container = styled(uilibGl.Flex).withConfig({ displayName: "Container", co
4641
4680
 
4642
4681
  ${sizeCssMixin};
4643
4682
  `;
4644
- const ContainerWrapper = styled(uilibGl.Flex).withConfig({ displayName: "ContainerWrapper", componentId: "sc-4nlisz" }) `
4683
+ const ContainerWrapper = styled(uilibGl.Flex).withConfig({ displayName: "ContainerWrapper", componentId: "sc-16tb6s0" }) `
4645
4684
  position: relative;
4646
4685
  box-sizing: border-box;
4647
4686
  width: 100%;
@@ -4662,7 +4701,7 @@ const ContainerWrapper = styled(uilibGl.Flex).withConfig({ displayName: "Contain
4662
4701
  }
4663
4702
  `}
4664
4703
  `;
4665
- const DashboardChip = styled(uilibGl.Chip).withConfig({ displayName: "DashboardChip", componentId: "sc-8os072" }) `
4704
+ const DashboardChip = styled(uilibGl.Chip).withConfig({ displayName: "DashboardChip", componentId: "sc-19j7obx" }) `
4666
4705
  margin: 0 0.25rem 0.25rem 0;
4667
4706
  background: ${({ $isDefault, $bgColor, theme: { palette } }) => $isDefault ? palette.element : $bgColor || palette.primary};
4668
4707
  border-radius: ${({ $radius, theme: { borderRadius } }) => $radius || borderRadius.medium};
@@ -4678,7 +4717,7 @@ const DashboardChip = styled(uilibGl.Chip).withConfig({ displayName: "DashboardC
4678
4717
  color: ${({ $isDefault, $fontColor, theme: { palette } }) => $isDefault ? palette.icon : $fontColor || "#fff"};
4679
4718
  }
4680
4719
  `;
4681
- const DashboardPlaceholderWrap = styled(uilibGl.Flex).withConfig({ displayName: "DashboardPlaceholderWrap", componentId: "sc-1qpd82p" }) `
4720
+ const DashboardPlaceholderWrap = styled(uilibGl.Flex).withConfig({ displayName: "DashboardPlaceholderWrap", componentId: "sc-anwihw" }) `
4682
4721
  flex-grow: 1;
4683
4722
  flex-direction: column;
4684
4723
  justify-content: center;
@@ -4686,7 +4725,7 @@ const DashboardPlaceholderWrap = styled(uilibGl.Flex).withConfig({ displayName:
4686
4725
  width: 100%;
4687
4726
  margin-bottom: 2rem;
4688
4727
  `;
4689
- const DashboardPlaceholder = styled(uilibGl.Flex).withConfig({ displayName: "DashboardPlaceholder", componentId: "sc-1ls3oxv" }) `
4728
+ const DashboardPlaceholder = styled(uilibGl.Flex).withConfig({ displayName: "DashboardPlaceholder", componentId: "sc-jry8vp" }) `
4690
4729
  flex-direction: column;
4691
4730
  justify-content: center;
4692
4731
  align-items: center;
@@ -4719,7 +4758,7 @@ const DashboardPlaceholder = styled(uilibGl.Flex).withConfig({ displayName: "Das
4719
4758
  }
4720
4759
  }
4721
4760
  `;
4722
- const DashboardWrapper = styled(uilibGl.Flex).withConfig({ displayName: "DashboardWrapper", componentId: "sc-bx93vz" }) `
4761
+ const DashboardWrapper = styled(uilibGl.Flex).withConfig({ displayName: "DashboardWrapper", componentId: "sc-100ipup" }) `
4723
4762
  flex-direction: column;
4724
4763
  flex-wrap: nowrap;
4725
4764
  flex-grow: 1;
@@ -4732,7 +4771,7 @@ const DashboardWrapper = styled(uilibGl.Flex).withConfig({ displayName: "Dashboa
4732
4771
  margin-top: -0.35rem;
4733
4772
  `}
4734
4773
  `;
4735
- const DashboardContent = styled(uilibGl.Flex).withConfig({ displayName: "DashboardContent", componentId: "sc-mslago" }) `
4774
+ const DashboardContent = styled(uilibGl.Flex).withConfig({ displayName: "DashboardContent", componentId: "sc-77il9k" }) `
4736
4775
  flex-grow: 1;
4737
4776
  width: 100%;
4738
4777
  padding: 1.5rem 1.5rem 2rem;
@@ -4747,16 +4786,16 @@ const PresentationWrapperCss = styled.css `
4747
4786
  border-radius: ${({ theme: { borderRadius } }) => borderRadius.medium};
4748
4787
  box-shadow: ${uilibGl.shadows.raised};
4749
4788
  `;
4750
- const PresentationWrapper = styled.div.withConfig({ displayName: "PresentationWrapper", componentId: "sc-1aajdp8" }) `
4789
+ const PresentationWrapper = styled.div.withConfig({ displayName: "PresentationWrapper", componentId: "sc-891z9z" }) `
4751
4790
  ${PresentationWrapperCss};
4752
4791
  position: relative;
4753
4792
  z-index: 1;
4754
4793
  `;
4755
- const PresentationPanelWrapper = styled(PresentationWrapper).withConfig({ displayName: "PresentationPanelWrapper", componentId: "sc-9w36pj" }) `
4794
+ const PresentationPanelWrapper = styled(PresentationWrapper).withConfig({ displayName: "PresentationPanelWrapper", componentId: "sc-1ptpbt9" }) `
4756
4795
  margin-top: 0.75rem;
4757
4796
  transition: background-color ${uilibGl.transition.toggle};
4758
4797
  `;
4759
- const PresentationHeader = styled.div.withConfig({ displayName: "PresentationHeader", componentId: "sc-xe6ev3" }) `
4798
+ const PresentationHeader = styled.div.withConfig({ displayName: "PresentationHeader", componentId: "sc-182b7wg" }) `
4760
4799
  margin: -1.5rem -1.5rem 0 -1.5rem;
4761
4800
  padding: 1.5rem;
4762
4801
  // background: url(images.presentationHeader) 0 0 no-repeat;
@@ -4768,7 +4807,7 @@ const PresentationHeader = styled.div.withConfig({ displayName: "PresentationHea
4768
4807
  padding-top: 7rem;
4769
4808
  `};
4770
4809
  `;
4771
- const PresentationHeaderTools = styled(uilibGl.Flex).withConfig({ displayName: "PresentationHeaderTools", componentId: "sc-13dyz78" }) `
4810
+ const PresentationHeaderTools = styled(uilibGl.Flex).withConfig({ displayName: "PresentationHeaderTools", componentId: "sc-dms7fm" }) `
4772
4811
  justify-content: space-between;
4773
4812
  align-items: center;
4774
4813
  margin-bottom: -0.5rem;
@@ -4786,7 +4825,7 @@ const PresentationHeaderTools = styled(uilibGl.Flex).withConfig({ displayName: "
4786
4825
  }
4787
4826
  }
4788
4827
  `;
4789
- const LayerGroupList = styled(uilibGl.Flex).withConfig({ displayName: "LayerGroupList", componentId: "sc-110h1r0" }) `
4828
+ const LayerGroupList = styled(uilibGl.Flex).withConfig({ displayName: "LayerGroupList", componentId: "sc-19uothl" }) `
4790
4829
  flex-direction: column;
4791
4830
  height: 100%;
4792
4831
  flex-wrap: nowrap;
@@ -4799,8 +4838,8 @@ const LayerGroupList = styled(uilibGl.Flex).withConfig({ displayName: "LayerGrou
4799
4838
  flex-grow: 1;
4800
4839
  }
4801
4840
  `;
4802
- const PresentationHeaderButtons = styled(uilibGl.Flex).withConfig({ displayName: "PresentationHeaderButtons", componentId: "sc-5xerc" }) ``;
4803
- const PresentationPanelContainer = styled.div.withConfig({ displayName: "PresentationPanelContainer", componentId: "sc-ok1jzl" }) `
4841
+ const PresentationHeaderButtons = styled(uilibGl.Flex).withConfig({ displayName: "PresentationHeaderButtons", componentId: "sc-c24t7n" }) ``;
4842
+ const PresentationPanelContainer = styled.div.withConfig({ displayName: "PresentationPanelContainer", componentId: "sc-17q0jzw" }) `
4804
4843
  position: absolute;
4805
4844
  top: 0;
4806
4845
  left: calc(${({ left }) => left || 0}px + 0.75rem);
@@ -4869,7 +4908,7 @@ const PresentationPanelContainer = styled.div.withConfig({ displayName: "Present
4869
4908
  }
4870
4909
  }
4871
4910
  `;
4872
- const DataSourceErrorContainer = styled(uilibGl.Flex).withConfig({ displayName: "DataSourceErrorContainer", componentId: "sc-16x60eq" }) `
4911
+ const DataSourceErrorContainer = styled(uilibGl.Flex).withConfig({ displayName: "DataSourceErrorContainer", componentId: "sc-nh93ry" }) `
4873
4912
  align-items: center;
4874
4913
  justify-content: center;
4875
4914
  flex-wrap: nowrap;
@@ -4888,12 +4927,12 @@ const DataSourceErrorContainer = styled(uilibGl.Flex).withConfig({ displayName:
4888
4927
  }
4889
4928
  }
4890
4929
  `;
4891
- const AttributeLabel = styled(uilibGl.Description).withConfig({ displayName: "AttributeLabel", componentId: "sc-1bou1dd" }) `
4930
+ const AttributeLabel = styled(uilibGl.Description).withConfig({ displayName: "AttributeLabel", componentId: "sc-9u3noy" }) `
4892
4931
  margin-top: 0 !important;
4893
4932
  margin-bottom: ${({ forCheckbox }) => forCheckbox ? "0.75rem" : "0.25rem"} !important;
4894
4933
  padding-left: ${({ isEdit }) => (isEdit ? "0.5rem" : "0")};
4895
4934
  `;
4896
- const FeatureControls = styled(uilibGl.Flex).withConfig({ displayName: "FeatureControls", componentId: "sc-fpl3fy" }) `
4935
+ const FeatureControls = styled(uilibGl.Flex).withConfig({ displayName: "FeatureControls", componentId: "sc-1wenq0r" }) `
4897
4936
  align-items: center;
4898
4937
  gap: 1rem;
4899
4938
  flex-wrap: nowrap;
@@ -6534,6 +6573,45 @@ const useContainerAttributes = ({ elementConfig, type, renderElement }) => {
6534
6573
  return { getRenderContainerItem, attributesToRender };
6535
6574
  };
6536
6575
 
6576
+ /**
6577
+ * Пропсы корневой обёртки контейнера: идентификаторы для внешних селекторов, авторский `style`
6578
+ * из конфига и css-объект размеров.
6579
+ *
6580
+ * Размеры уходят styled-пропом (класс), а не inline-стилем, поэтому перебиваются снаружи
6581
+ * без `!important`. Авторский `style` остаётся inline — у него приоритет по замыслу автора конфига.
6582
+ */
6583
+ const useWrapperSize = ({ elementConfig, defaults }) => {
6584
+ const { id, style, templateName, options } = elementConfig || {};
6585
+ const { width, height, overflow } = options || {};
6586
+ return React.useMemo(() => ({
6587
+ id,
6588
+ "data-templatename": templateName,
6589
+ style,
6590
+ $sizeCss: getWrapperSizeStyle({ style, width, height, overflow, defaults, defaultWidth: FILL_SIZE }),
6591
+ }), [id, templateName, style, width, height, overflow, defaults]);
6592
+ };
6593
+
6594
+ /**
6595
+ * Пропсы двух узлов контейнера с заголовком: корня (`ContainerRoot`) и тела.
6596
+ *
6597
+ * Контейнер обязан иметь ОДИН корневой узел — иначе в строке (`options.column: false`) заголовок
6598
+ * и тело становятся двумя ячейками родительского flex-row. Размеры из конфига поэтому уходят на
6599
+ * корень, а тело получает лишь остаток высоты под заголовком.
6600
+ */
6601
+ const useContainerRoot = ({ elementConfig, defaults }) => {
6602
+ const root = useWrapperSize({ elementConfig, defaults });
6603
+ // Гейт по РЕЗУЛЬТИРУЮЩЕЙ высоте, а не по `options.height`: высоту задаёт ещё и авторский `style`,
6604
+ // и внутренние `defaults` контейнера. `auto` высотой не считаем — делить нечего.
6605
+ const fillsHeight = !!root.$sizeCss?.height && root.$sizeCss.height !== "auto";
6606
+ return React.useMemo(() => ({
6607
+ root,
6608
+ body: {
6609
+ [CONTAINER_BODY_ATTRIBUTE]: "",
6610
+ $sizeCss: fillsHeight ? CONTAINER_BODY_FILL_STYLE : undefined,
6611
+ },
6612
+ }), [root, fillsHeight]);
6613
+ };
6614
+
6537
6615
  const useEditGroupAttributes = ({ elementConfig, type }) => {
6538
6616
  const { options } = elementConfig || {};
6539
6617
  const { controls, useProjectHiddenAttributes } = options || {};
@@ -7479,7 +7557,11 @@ const useExportPdf = (id, margin = 20) => {
7479
7557
  return;
7480
7558
  }
7481
7559
  setLoading(true);
7482
- const container = document.querySelector(`#${id}`);
7560
+ const target = document.querySelector(`#${id}`);
7561
+ // `#id` — корень контейнера, то есть пара «заголовок + тело». Постранично режем содержимое
7562
+ // тела: у самого корня детей всего два, и длинное тело уехало бы одной картинкой на первую
7563
+ // страницу. Fallback — для одноузловых целей вроде корня дашборда.
7564
+ const container = target?.querySelector(`:scope > [${CONTAINER_BODY_ATTRIBUTE}]`) ?? target;
7483
7565
  if (!container) {
7484
7566
  setLoading(false);
7485
7567
  return;
@@ -7863,32 +7945,14 @@ const useUpdateDataSource = ({ dataSource, config, filters, attributes, layerPar
7863
7945
  }, [dataSource, getDataSourcePromises, getUpdatedDataSources, dataSources]);
7864
7946
  };
7865
7947
 
7866
- /**
7867
- * Пропсы корневой обёртки контейнера: идентификаторы для внешних селекторов, авторский `style`
7868
- * из конфига и css-объект размеров.
7869
- *
7870
- * Размеры уходят styled-пропом (класс), а не inline-стилем, поэтому перебиваются снаружи
7871
- * без `!important`. Авторский `style` остаётся inline — у него приоритет по замыслу автора конфига.
7872
- */
7873
- const useWrapperSize = ({ elementConfig, defaults }) => {
7874
- const { id, style, templateName, options } = elementConfig || {};
7875
- const { width, height, overflow } = options || {};
7876
- return React.useMemo(() => ({
7877
- id,
7878
- "data-templatename": templateName,
7879
- style,
7880
- $sizeCss: getWrapperSizeStyle({ style, width, height, overflow, defaults, defaultWidth: FILL_SIZE }),
7881
- }), [id, templateName, style, width, height, overflow, defaults]);
7882
- };
7883
-
7884
7948
  const ContainersGroupContainer = React.memo(({ elementConfig, type, renderElement }) => {
7885
7949
  const { expandedContainers } = useWidgetContext(type);
7886
7950
  const { id, children, options } = elementConfig || {};
7887
7951
  const { column, expandable, expanded, alignItems } = options || {};
7888
7952
  const isColumn = column === undefined || column;
7889
7953
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
7890
- const root = useWrapperSize({ elementConfig });
7891
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { ...root, isColumn: isColumn, "$alignItems": alignItems, children: jsxRuntime.jsx(ContainerChildren, { type: type, items: children, elementConfig: elementConfig, isColumn: isColumn, isMain: id?.startsWith(CONFIG_PAGE_ID), renderElement: renderElement }) }))] }));
7954
+ const { root, body } = useContainerRoot({ elementConfig });
7955
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { ...body, isColumn: isColumn, "$alignItems": alignItems, children: jsxRuntime.jsx(ContainerChildren, { type: type, items: children, elementConfig: elementConfig, isColumn: isColumn, isMain: id?.startsWith(CONFIG_PAGE_ID), renderElement: renderElement }) }))] }));
7892
7956
  });
7893
7957
 
7894
7958
  const ChartLegendContainer = styled(uilibGl.Flex).withConfig({ displayName: "ChartLegendContainer", componentId: "sc-1di1zl9" }) `
@@ -8309,7 +8373,7 @@ const DataSourceProgressContainer = React.memo(({ config, elementConfig, type, i
8309
8373
  const { maxValue, showTotal, relatedDataSource, expandable, expanded } = options || {};
8310
8374
  const valueElement = children?.find(item => item.id === "value");
8311
8375
  const unitsElement = children?.find(item => item.id === "units");
8312
- const root = useWrapperSize({ elementConfig });
8376
+ const { root, body } = useContainerRoot({ elementConfig });
8313
8377
  const { sliceItems, checkIsSliced, showMore, onShowMore } = useShownOtherItems(options);
8314
8378
  const totalUnits = React.useMemo(() => unitsElement?.type === "attributeUnits"
8315
8379
  ? attributes?.find(({ attributeName }) => attributeName === unitsElement.attributeName)?.stringFormat
@@ -8340,7 +8404,7 @@ const DataSourceProgressContainer = React.memo(({ config, elementConfig, type, i
8340
8404
  return jsxRuntime.jsx(DataSourceError, { name: elementConfig.templateName });
8341
8405
  }
8342
8406
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
8343
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(DataSourceProgressContainerWrapper, { ...root, children: [sliceItems(dataSource?.features)?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { type: type, index: index, feature: feature, config: config, elementConfig: elementConfig, maxValue: currentMaxValue, innerComponent: innerComponent }, index))), checkIsSliced(dataSource?.features) && (jsxRuntime.jsx(ContainerToggler, { toggled: showMore, onClick: onShowMore, children: showMore ? t("hide", { ns: "dashboard", defaultValue: "Свернуть" }) : t("showAll", {
8407
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(DataSourceProgressContainerWrapper, { ...body, children: [sliceItems(dataSource?.features)?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { type: type, index: index, feature: feature, config: config, elementConfig: elementConfig, maxValue: currentMaxValue, innerComponent: innerComponent }, index))), checkIsSliced(dataSource?.features) && (jsxRuntime.jsx(ContainerToggler, { toggled: showMore, onClick: onShowMore, children: showMore ? t("hide", { ns: "dashboard", defaultValue: "Свернуть" }) : t("showAll", {
8344
8408
  ns: "dashboard",
8345
8409
  defaultValue: "Показать все",
8346
8410
  }) })), showTotal && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.Divider, {}), jsxRuntime.jsxs(ProgressTotal, { children: [jsxRuntime.jsx(ProgressTotalTitle, { children: t("total", { ns: "dashboard", defaultValue: "Итого" }) }), jsxRuntime.jsxs(ProgressValue, { children: [totalValue, jsxRuntime.jsx(ProgressUnits, { children: totalUnits })] })] })] }))] })) : (jsxRuntime.jsx(ContainerLoading, {})), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type })] }));
@@ -8601,7 +8665,7 @@ const FiltersContainer = React.memo(({ elementConfig, config, type, renderElemen
8601
8665
  const { filters: configFilters } = currentPage;
8602
8666
  const { id, options } = elementConfig || {};
8603
8667
  const { padding, bgColor, fontColor, fontSize, expandable, expanded } = options || {};
8604
- const root = useWrapperSize({ elementConfig });
8668
+ const { root, body } = useContainerRoot({ elementConfig });
8605
8669
  const isLoading = React.useMemo(() => checkIsLoading(dataSources, config, configFilters), [configFilters, config, dataSources]);
8606
8670
  const filterItems = React.useMemo(() => elementConfig?.children?.filter(child => child.options?.filterName), [elementConfig?.children]);
8607
8671
  const renderFilter = React.useCallback((filter, index) => {
@@ -8610,7 +8674,7 @@ const FiltersContainer = React.memo(({ elementConfig, config, type, renderElemen
8610
8674
  }, [config, type]);
8611
8675
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
8612
8676
  const selectedItems = React.useMemo(() => getFilterSelectedItems(filterItems, filters, configFilters), [configFilters, filters, filterItems]);
8613
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.Flex, { mb: !isVisible && selectedItems.length ? "2rem" : 0, children: jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }) }), isLoading && jsxRuntime.jsx(ContainerLoading, {}), !isLoading && isVisible && (jsxRuntime.jsx(FiltersContainerWrapper, { ...root, "$padding": padding, "$bgColor": bgColor, "$fontSize": fontSize, "$fontColor": fontColor, children: filterItems?.map(renderFilter) })), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type, filter: filterItems[0]?.options?.filterName })] }));
8677
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(uilibGl.Flex, { mb: !isVisible && selectedItems.length ? "2rem" : 0, children: jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }) }), isLoading && jsxRuntime.jsx(ContainerLoading, {}), !isLoading && isVisible && (jsxRuntime.jsx(FiltersContainerWrapper, { ...body, "$padding": padding, "$bgColor": bgColor, "$fontSize": fontSize, "$fontColor": fontColor, children: filterItems?.map(renderFilter) })), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type, filter: filterItems[0]?.options?.filterName })] }));
8614
8678
  });
8615
8679
 
8616
8680
  const DefaultAttributesContainer = React.memo(({ type, renderElement }) => {
@@ -8618,26 +8682,6 @@ const DefaultAttributesContainer = React.memo(({ type, renderElement }) => {
8618
8682
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: attributes?.map(({ attributeName }) => (jsxRuntime.jsx(Container, { isColumn: true, children: renderElement({ id: attributeName }) }, attributeName))) }));
8619
8683
  });
8620
8684
 
8621
- const ChartContainerWrapper = styled(uilibGl.FlexSpan).withConfig({ displayName: "ChartContainerWrapper", componentId: "sc-17oj4lo" }) `
8622
- flex-direction: column;
8623
- min-width: 0;
8624
-
8625
- /* Заданная высота контейнера достаётся телу графика — за вычетом заголовка. */
8626
- ${({ $sizeCss }) => !!$sizeCss?.height &&
8627
- styled.css `
8628
- /* Раздача высоты требует, чтобы обёртка была flex-колонкой (FlexSpan сам по себе не flex),
8629
- иначе Container с flex:1 1 auto не растянется на заданную высоту, а fill-график не впишется по высоте. */
8630
- display: flex;
8631
-
8632
- > ${Container} {
8633
- flex: 1 1 auto;
8634
- min-height: 0;
8635
- }
8636
- `}
8637
-
8638
- ${sizeCssMixin};
8639
- `;
8640
-
8641
8685
  /**
8642
8686
  * Контекст вписывания графика (`options.fill` контейнера Chart).
8643
8687
  *
@@ -8655,7 +8699,7 @@ const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderEleme
8655
8699
  const aliasElement = children.find(child => child.id === "alias");
8656
8700
  const chartElement = children.find(child => child.id === "chart");
8657
8701
  const legendElement = children.find(child => child.id === "legend");
8658
- const root = useWrapperSize({ elementConfig });
8702
+ const { root, body } = useContainerRoot({ elementConfig });
8659
8703
  const { data, loading } = useChartData({
8660
8704
  element: chartElement,
8661
8705
  type,
@@ -8666,7 +8710,7 @@ const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderEleme
8666
8710
  const hasItems = !!data[0]?.items?.length;
8667
8711
  if (!loading && !hasItems && hideEmpty)
8668
8712
  return null;
8669
- return (jsxRuntime.jsxs(ChartContainerWrapper, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { isColumn: true, children: [aliasElement && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { column: !twoColumns, alignItems: twoColumns && fill ? "stretch" : "center", "$fill": !!fill, children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { "$fill": !!fill, children: jsxRuntime.jsx(FillContext.Provider, { value: fillContextValue, children: renderElement({ id: "chart" }) }) }), jsxRuntime.jsx(ContainerLegend, { justifyContent: legendElement?.options?.center ? "center" : "flex-start", children: renderElement({ id: "legend" }) })] })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: "\u2014" })) })] }))] }));
8713
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { ...body, isColumn: true, children: [aliasElement && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { column: !twoColumns, alignItems: twoColumns && fill ? "stretch" : "center", "$fill": !!fill, children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { "$fill": !!fill, children: jsxRuntime.jsx(FillContext.Provider, { value: fillContextValue, children: renderElement({ id: "chart" }) }) }), jsxRuntime.jsx(ContainerLegend, { justifyContent: legendElement?.options?.center ? "center" : "flex-start", children: renderElement({ id: "legend" }) })] })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: "\u2014" })) })] }))] }));
8670
8714
  });
8671
8715
 
8672
8716
  const PagesContainer = React.memo(({ type = exports.WidgetType.Dashboard, noBorders }) => {
@@ -8892,13 +8936,13 @@ const DataSourceContainer = React.memo(({ config, elementConfig, type, innerComp
8892
8936
  gap: gap ?? DEFAULT_TILE_GAP,
8893
8937
  });
8894
8938
  const defaults = React.useMemo(() => ({ height: isLoading ? "3rem" : "auto" }), [isLoading]);
8895
- const root = useWrapperSize({ elementConfig, defaults });
8939
+ const { root, body } = useContainerRoot({ elementConfig, defaults });
8896
8940
  if (!relatedDataSource)
8897
8941
  return null;
8898
8942
  if (dataSource && !dataSource.features) {
8899
8943
  return jsxRuntime.jsx(DataSourceError, { name: elementConfig.templateName });
8900
8944
  }
8901
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(DataSourceContainerWrapper, { ...root, ref: tilesRef, isColumn: column, "$isRow": !column, "$columns": columns, "$gap": gap, "$align": align, "$stretch": stretch, "$tileWidth": tileWidth, children: sliceItems(dataSource.features)?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { index: index, type: type, config: config, feature: feature, elementConfig: elementConfig, innerComponent: innerComponent }, index))) }), checkIsSliced(dataSource.features) && (jsxRuntime.jsx(ContainerToggler, { toggled: showMore, onClick: onShowMore, children: showMore
8945
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(DataSourceContainerWrapper, { ...body, ref: tilesRef, isColumn: column, "$isRow": !column, "$columns": columns, "$gap": gap, "$align": align, "$stretch": stretch, "$tileWidth": tileWidth, children: sliceItems(dataSource.features)?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { index: index, type: type, config: config, feature: feature, elementConfig: elementConfig, innerComponent: innerComponent }, index))) }), checkIsSliced(dataSource.features) && (jsxRuntime.jsx(ContainerToggler, { toggled: showMore, onClick: onShowMore, children: showMore
8902
8946
  ? t("hide", { ns: "dashboard", defaultValue: "Свернуть" })
8903
8947
  : t("showAll", { ns: "dashboard", defaultValue: "Показать все" }) }))] })) : (jsxRuntime.jsx(ContainerLoading, {}))] }));
8904
8948
  });
@@ -9058,7 +9102,7 @@ const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
9058
9102
  const { id, options } = elementConfig || {};
9059
9103
  const { expandable, expanded } = options || {};
9060
9104
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
9061
- const root = useWrapperSize({ elementConfig });
9105
+ const { root, body } = useContainerRoot({ elementConfig });
9062
9106
  const render = React.useMemo(() => getRenderElement({
9063
9107
  config,
9064
9108
  elementConfig,
@@ -9084,11 +9128,11 @@ const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
9084
9128
  // Подпись `alias` не задают почти всегда — тогда обёртку не рендерим, чтобы в DOM не оставался
9085
9129
  // пустой блок, который вдобавок отъедал бы половину ширины у галереи (см. isColumn ниже).
9086
9130
  const aliasNode = render({ id: "alias" });
9087
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: render }), isVisible && (
9131
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: render }), isVisible && (
9088
9132
  // `isColumn`: подпись над галереей, а сама галерея на всю ширину. Без него Container
9089
9133
  // раскладывает alias и slideshow в ряд, и оба (Flex с `width: 100%`) сжимаются пополам —
9090
9134
  // картинка занимала лишь половину доступной ширины.
9091
- jsxRuntime.jsxs(Container, { ...root, isColumn: true, children: [aliasNode && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: aliasNode }), jsxRuntime.jsx(ContainerValue, { children: render({
9135
+ jsxRuntime.jsxs(Container, { ...body, isColumn: true, children: [aliasNode && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: aliasNode }), jsxRuntime.jsx(ContainerValue, { children: render({
9092
9136
  id: "slideshow",
9093
9137
  wrap: false,
9094
9138
  }) })] }))] }));
@@ -9099,8 +9143,8 @@ const CameraContainer = React.memo(({ elementConfig, type, renderElement }) => {
9099
9143
  const { id, options } = elementConfig || {};
9100
9144
  const { expandable, expanded } = options || {};
9101
9145
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
9102
- const root = useWrapperSize({ elementConfig });
9103
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { ...root, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value", wrap: false }) })] }))] }));
9146
+ const { root, body } = useContainerRoot({ elementConfig });
9147
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { ...body, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value", wrap: false }) })] }))] }));
9104
9148
  });
9105
9149
 
9106
9150
  const TabAnchor = styled.div.withConfig({ displayName: "TabAnchor", componentId: "sc-emqf31" }) `
@@ -9520,7 +9564,7 @@ const LayersContainer = React.memo(({ type, elementConfig, renderElement }) => {
9520
9564
  const { id, options } = elementConfig || {};
9521
9565
  const { layerNames, expandable, expanded } = options || {};
9522
9566
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
9523
- const root = useWrapperSize({ elementConfig });
9567
+ const { root, body } = useContainerRoot({ elementConfig });
9524
9568
  const layers = React.useMemo(() => {
9525
9569
  if (!currentPage?.layers)
9526
9570
  return [];
@@ -9528,7 +9572,7 @@ const LayersContainer = React.memo(({ type, elementConfig, renderElement }) => {
9528
9572
  return currentPage.layers;
9529
9573
  return currentPage.layers.filter(({ name }) => layerNames.includes(name));
9530
9574
  }, [currentPage?.layers, layerNames]);
9531
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { ...root, children: jsxRuntime.jsx(LayerTree, { layers: layers, onlyMainTools: true }) }))] }));
9575
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { ...body, children: jsxRuntime.jsx(LayerTree, { layers: layers, onlyMainTools: true }) }))] }));
9532
9576
  });
9533
9577
 
9534
9578
  const ExportPdfContainer = React.memo(({ type, elementConfig }) => {
@@ -9564,8 +9608,8 @@ const UploadContainer = React.memo(({ type, elementConfig, renderElement }) => {
9564
9608
  const { id, options } = elementConfig || {};
9565
9609
  const { expandable, expanded } = options || {};
9566
9610
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
9567
- const root = useWrapperSize({ elementConfig });
9568
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(UploadContainerWrapper, { ...root, children: renderElement({ id: "uploader", wrap: false }) }))] }));
9611
+ const { root, body } = useContainerRoot({ elementConfig });
9612
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(UploadContainerWrapper, { ...body, children: renderElement({ id: "uploader", wrap: false }) }))] }));
9569
9613
  });
9570
9614
 
9571
9615
  const StatusBadge = styled(uilibGl.Chip).withConfig({ displayName: "StatusBadge", componentId: "sc-1xmfl10" }) `
@@ -9785,7 +9829,7 @@ const TaskContainer = React.memo(({ type, elementConfig, renderElement }) => {
9785
9829
  const { taskId, runTask, stopTask, status, openLog, loading, isLogDialogOpen, closeLog, log, lastMessage, result, } = usePythonTask();
9786
9830
  const { options } = elementConfig || {};
9787
9831
  const { title, relatedResources, center, icon, statusColors, responseFilters, useNotifications, } = options || {};
9788
- const root = useWrapperSize({ elementConfig });
9832
+ const { root, body } = useContainerRoot({ elementConfig });
9789
9833
  const { setNotificationDismissed } = useTaskNotifications({
9790
9834
  enabled: !!useNotifications,
9791
9835
  suppressed: isLogDialogOpen,
@@ -9825,12 +9869,12 @@ const TaskContainer = React.memo(({ type, elementConfig, renderElement }) => {
9825
9869
  return runTask({ resourceId, parameters: newParams, script, fileName, methodName });
9826
9870
  }));
9827
9871
  }, [attributes, currentPage.filters, dataSources, ewktGeometry, layerInfo, projectDataSources, relatedResources, runTask, selectedFilters, stopTask, taskId]);
9828
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxRuntime.jsxs(TaskContainerWrapper, { ...root, justifyContent: center ? "center" : "flex-start", children: [jsxRuntime.jsx(StatusWaitingButton, { title: title || t("run", { ns: "dashboard", defaultValue: "Запуск" }), icon: icon, status: status, statusColors: statusColors, isWaiting: loading || !!taskId, isDisabled: !relatedResources?.length, onClick: onClick }), !!(log || taskId) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.IconButton, { kind: "info", onClick: openLog }), jsxRuntime.jsx(LogDialog, { logs: log, status: status, statusColors: statusColors, isOpen: isLogDialogOpen, onClose: onCloseLog, onMinimize: useNotifications ? onMinimizeLog : undefined })] }))] })] }));
9872
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxRuntime.jsxs(TaskContainerWrapper, { ...body, justifyContent: center ? "center" : "flex-start", children: [jsxRuntime.jsx(StatusWaitingButton, { title: title || t("run", { ns: "dashboard", defaultValue: "Запуск" }), icon: icon, status: status, statusColors: statusColors, isWaiting: loading || !!taskId, isDisabled: !relatedResources?.length, onClick: onClick }), !!(log || taskId) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.IconButton, { kind: "info", onClick: openLog }), jsxRuntime.jsx(LogDialog, { logs: log, status: status, statusColors: statusColors, isOpen: isLogDialogOpen, onClose: onCloseLog, onMinimize: useNotifications ? onMinimizeLog : undefined })] }))] })] }));
9829
9873
  });
9830
9874
 
9831
9875
  const EditContainer = ({ type, elementConfig, renderElement }) => {
9832
- const { id, style } = elementConfig || {};
9833
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxRuntime.jsxs(Container, { id: id, isColumn: true, style: style, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value" }) })] })] }));
9876
+ const { root, body } = useContainerRoot({ elementConfig });
9877
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxRuntime.jsxs(Container, { ...body, isColumn: true, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value" }) })] })] }));
9834
9878
  };
9835
9879
 
9836
9880
  const getControlTemplateName = (type) => {
@@ -10567,7 +10611,7 @@ const AttachmentContainer = React.memo(({ type, elementConfig, renderElement })
10567
10611
  const { items, visibleItems, viewMode, setViewMode, showMore, setShowMore, hasMore, hiddenCount } = useAttachmentContainer({ type, elementConfig });
10568
10612
  const { id, options } = elementConfig || {};
10569
10613
  const { expandable, expanded } = options || {};
10570
- const root = useWrapperSize({ elementConfig, defaults: BASE_CONTAINER_STYLE });
10614
+ const { root, body } = useContainerRoot({ elementConfig, defaults: BASE_CONTAINER_STYLE });
10571
10615
  const [previewIndex, setPreviewIndex] = React.useState(null);
10572
10616
  const previewImages = useAttachmentPreviewImages({ items, active: previewIndex !== null });
10573
10617
  const handlePreview = React.useCallback((link) => {
@@ -10578,7 +10622,7 @@ const AttachmentContainer = React.memo(({ type, elementConfig, renderElement })
10578
10622
  const handleClosePreview = React.useCallback(() => setPreviewIndex(null), []);
10579
10623
  const handleShowMore = React.useCallback(() => setShowMore(true), [setShowMore]);
10580
10624
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
10581
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { ...root, children: jsxRuntime.jsxs(uilibGl.Flex, { column: true, children: [jsxRuntime.jsx(AttachmentsHeader, { alias: renderElement?.({ id: "alias" }), count: items.length, viewMode: viewMode, onChangeViewMode: setViewMode }), jsxRuntime.jsx(AttachmentsContent, { children: viewMode === "grid" ? (jsxRuntime.jsx(AttachmentsGrid, { items: visibleItems, isEdit: false, onPreview: handlePreview })) : (jsxRuntime.jsx(AttachmentsList, { items: visibleItems, isEdit: false, onPreview: handlePreview })) }), hasMore && !showMore && (jsxRuntime.jsx(ShowMoreButton, { hiddenCount: hiddenCount, onClick: handleShowMore })), previewIndex !== null && (jsxRuntime.jsx(uilibGl.Preview, { images: previewImages, initialIndex: previewIndex, isOpen: previewIndex !== null, onClose: handleClosePreview, errorTitleText: t("attachments.resourceUnavailable", {
10625
+ return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { ...body, children: jsxRuntime.jsxs(uilibGl.Flex, { column: true, children: [jsxRuntime.jsx(AttachmentsHeader, { alias: renderElement?.({ id: "alias" }), count: items.length, viewMode: viewMode, onChangeViewMode: setViewMode }), jsxRuntime.jsx(AttachmentsContent, { children: viewMode === "grid" ? (jsxRuntime.jsx(AttachmentsGrid, { items: visibleItems, isEdit: false, onPreview: handlePreview })) : (jsxRuntime.jsx(AttachmentsList, { items: visibleItems, isEdit: false, onPreview: handlePreview })) }), hasMore && !showMore && (jsxRuntime.jsx(ShowMoreButton, { hiddenCount: hiddenCount, onClick: handleShowMore })), previewIndex !== null && (jsxRuntime.jsx(uilibGl.Preview, { images: previewImages, initialIndex: previewIndex, isOpen: previewIndex !== null, onClose: handleClosePreview, errorTitleText: t("attachments.resourceUnavailable", {
10582
10626
  ns: "common",
10583
10627
  defaultValue: "Ресурс недоступен",
10584
10628
  }) }, previewIndex))] }) }))] }));
@@ -15218,8 +15262,11 @@ exports.AttributeGalleryContainer = AttributeGalleryContainer;
15218
15262
  exports.AttributeLabel = AttributeLabel;
15219
15263
  exports.BASE_CONTAINER_STYLE = BASE_CONTAINER_STYLE;
15220
15264
  exports.CHART_TYPES = CHART_TYPES;
15265
+ exports.COMPACT_FRACTION_DIGITS = COMPACT_FRACTION_DIGITS;
15221
15266
  exports.CONFIG_PAGES_ID = CONFIG_PAGES_ID;
15222
15267
  exports.CONFIG_PAGE_ID = CONFIG_PAGE_ID;
15268
+ exports.CONTAINER_BODY_ATTRIBUTE = CONTAINER_BODY_ATTRIBUTE;
15269
+ exports.CONTAINER_BODY_FILL_STYLE = CONTAINER_BODY_FILL_STYLE;
15223
15270
  exports.CameraContainer = CameraContainer;
15224
15271
  exports.Chart = Chart;
15225
15272
  exports.ChartContainer = ChartContainer;
@@ -15228,6 +15275,7 @@ exports.ChartLoading = ChartLoading;
15228
15275
  exports.Container = Container;
15229
15276
  exports.ContainerChildren = ContainerChildren;
15230
15277
  exports.ContainerLoading = ContainerLoading;
15278
+ exports.ContainerRoot = ContainerRoot;
15231
15279
  exports.ContainerWrapper = ContainerWrapper;
15232
15280
  exports.ContainersGroupContainer = ContainersGroupContainer;
15233
15281
  exports.DEFAULT_ATTRIBUTE_NAME = DEFAULT_ATTRIBUTE_NAME;
@@ -15521,6 +15569,7 @@ exports.useBeforeSave = useBeforeSave;
15521
15569
  exports.useChartChange = useChartChange;
15522
15570
  exports.useChartData = useChartData;
15523
15571
  exports.useContainerAttributes = useContainerAttributes;
15572
+ exports.useContainerRoot = useContainerRoot;
15524
15573
  exports.useCurrentPageLayers = useCurrentPageLayers;
15525
15574
  exports.useCustomFeatureSelect = useCustomFeatureSelect;
15526
15575
  exports.useDashboardHeader = useDashboardHeader;