@evergis/react 3.1.42 → 3.1.47

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.
package/dist/index.js CHANGED
@@ -22,6 +22,8 @@ var MapGL = require('react-map-gl/mapbox');
22
22
  require('@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css');
23
23
  require('mapbox-gl/dist/mapbox-gl.css');
24
24
  var react = require('swiper/react');
25
+ var ReactMarkdown = require('react-markdown');
26
+ var remarkGfm = require('remark-gfm');
25
27
 
26
28
  const AddFeatureButton = ({ title, icon = "feature_add" /* , layerName, geometryType*/ }) => {
27
29
  // const [, handleAddFeature] = useFeatureCreator(layerName, geometryType);
@@ -4448,24 +4450,48 @@ const formatDataSourceCondition = ({ condition, configFilters, filters, attribut
4448
4450
  const DashboardChipsContainer = styled(uilibGl.Flex) `
4449
4451
  flex-wrap: wrap;
4450
4452
  `;
4453
+ const DefaultChipColorMixin = styled.css `
4454
+ && {
4455
+ color: ${({ theme: { palette } }) => palette.textPrimary};
4456
+ }
4457
+
4458
+ && > * {
4459
+ color: ${({ theme: { palette } }) => palette.textPrimary};
4460
+ }
4461
+
4462
+ && span[kind]:after {
4463
+ color: ${({ theme: { palette } }) => palette.icon};
4464
+ }
4465
+ `;
4466
+ const CustomChipColorMixin = styled.css `
4467
+ && {
4468
+ color: ${({ $fontColor }) => $fontColor};
4469
+ }
4470
+
4471
+ && > * {
4472
+ color: ${({ $fontColor }) => $fontColor};
4473
+ }
4474
+
4475
+ && span[kind]:after {
4476
+ color: ${({ $fontColor }) => $fontColor};
4477
+ }
4478
+ `;
4451
4479
  const DashboardChip$1 = styled(uilibGl.Chip) `
4452
4480
  margin: 0 0.25rem 0.25rem 0;
4453
4481
  background: ${({ $isDefault, $bgColor, theme: { palette } }) => $isDefault ? palette.element : $bgColor || palette.primary};
4454
4482
  border-radius: ${({ $radius, theme: { borderRadius } }) => $radius || borderRadius.medium};
4455
4483
  white-space: nowrap;
4456
4484
  font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
4457
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => $isDefault ? palette.textPrimary : $fontColor || "#fff"};
4485
+ color: ${({ theme: { palette } }) => palette.iconContrast};
4458
4486
 
4459
4487
  > * {
4460
4488
  font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
4461
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => $isDefault ? palette.textPrimary : $fontColor || "#fff"};
4462
4489
  }
4463
4490
 
4464
4491
  span[kind] {
4465
4492
  height: 0.875rem;
4466
4493
 
4467
4494
  :after {
4468
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => ($isDefault ? palette.icon : $fontColor || "#fff")};
4469
4495
  font-size: 0.875rem;
4470
4496
  }
4471
4497
  }
@@ -4474,6 +4500,9 @@ const DashboardChip$1 = styled(uilibGl.Chip) `
4474
4500
  width: auto;
4475
4501
  padding: 0 0.5rem;
4476
4502
  }
4503
+
4504
+ ${({ $isDefault }) => $isDefault && DefaultChipColorMixin}
4505
+ ${({ $fontColor, $isDefault }) => !!$fontColor && !$isDefault && CustomChipColorMixin}
4477
4506
  `;
4478
4507
 
4479
4508
  const ChartLegendContainer = styled(uilibGl.Flex) `
@@ -5040,7 +5069,7 @@ const LayerGroup = ({ group, onlyMainTools }) => {
5040
5069
  if (!group) {
5041
5070
  return null;
5042
5071
  }
5043
- return (jsxRuntime.jsx(LayerGroupContainer, { visible: group.isVisible, children: jsxRuntime.jsxs(LayerGroupMain, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: group.isExpanded ? "tree_folder_open" : "tree_folder_closed", style: { color: group.clientData.color } }), jsxRuntime.jsxs(uilibGl.Description, { children: [jsxRuntime.jsx("div", { style: { wordBreak: "break-word" }, children: group?.alias || group?.name }), jsxRuntime.jsx(uilibGl.IconButton, { kind: group.isExpanded ? "reduce" : "expand", onClick: () => onToggleExpand(group.name, !group.isExpanded) })] }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(uilibGl.Flex, { flexWrap: "nowrap", p: "0 0.5rem", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: group.isVisible ? "password_show" : "password_hide", className: "feature-visible", isSelected: group.isVisible, onClick: () => onToggleVisibility(group.name, !group.isVisible) }) }), !onlyMainTools && (jsxRuntime.jsx(uilibGl.Popup, { distance: -14, isVisible: isMenuOpen, onRequestClose: toggleMenu, anchor: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconButton, { innerRef: ref, kind: "menu_vertical", onClick: toggleMenu }) })), children: jsxRuntime.jsx(uilibGl.Menu, { options: options, selectOption: selectOption }) }))] }) })] }) }));
5072
+ return (jsxRuntime.jsx(LayerGroupContainer, { visible: group.isVisible, children: jsxRuntime.jsxs(LayerGroupMain, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: group.isExpanded ? "tree_folder_opened" : "tree_folder_closed", style: { color: group.clientData.color } }), jsxRuntime.jsxs(uilibGl.Description, { children: [jsxRuntime.jsx("div", { style: { wordBreak: "break-word" }, children: group?.alias || group?.name }), jsxRuntime.jsx(uilibGl.IconButton, { kind: group.isExpanded ? "reduce" : "expand", onClick: () => onToggleExpand(group.name, !group.isExpanded) })] }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(uilibGl.Flex, { flexWrap: "nowrap", p: "0 0.5rem", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: group.isVisible ? "password_show" : "password_hide", className: "feature-visible", isSelected: group.isVisible, onClick: () => onToggleVisibility(group.name, !group.isVisible) }) }), !onlyMainTools && (jsxRuntime.jsx(uilibGl.Popup, { distance: -14, isVisible: isMenuOpen, onRequestClose: toggleMenu, anchor: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconButton, { innerRef: ref, kind: "menu_vertical", onClick: toggleMenu }) })), children: jsxRuntime.jsx(uilibGl.Menu, { options: options, selectOption: selectOption }) }))] }) })] }) }));
5044
5073
  };
5045
5074
 
5046
5075
  const createTreeNode = (layer, Component, onlyMainTools) => {
@@ -5103,9 +5132,6 @@ const LayerListContainer = styled(uilibGl.Flex) `
5103
5132
  const ElementValueWrapper = styled.div `
5104
5133
  transition: background-color ${uilibGl.transition.toggle};
5105
5134
  `;
5106
- const InnerContainerWrapper$1 = styled.div `
5107
- width: 100%;
5108
- `;
5109
5135
  const ContainerWrapper = styled(uilibGl.Flex) `
5110
5136
  position: relative;
5111
5137
  min-height: 1rem;
@@ -5448,24 +5474,24 @@ const ContainersGroupContainer = React.memo(({ elementConfig, type, renderElemen
5448
5474
  const { column, expandable, expanded } = options || {};
5449
5475
  const isColumn = column === undefined || column;
5450
5476
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
5451
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { style: style, isColumn: isColumn, children: jsxRuntime.jsx(ContainerChildren, { items: children, elementConfig: elementConfig, isColumn: isColumn, isMain: id?.startsWith(CONFIG_PAGE_ID), renderElement: renderElement }) }))] }));
5477
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { id: id, style: style, isColumn: isColumn, children: jsxRuntime.jsx(ContainerChildren, { items: children, elementConfig: elementConfig, isColumn: isColumn, isMain: id?.startsWith(CONFIG_PAGE_ID), renderElement: renderElement }) }))] }));
5452
5478
  });
5453
5479
 
5454
5480
  const OneColumnContainer = React.memo(({ elementConfig, renderElement }) => {
5455
- const { options, style } = elementConfig || {};
5481
+ const { id, options, style } = elementConfig || {};
5456
5482
  const { innerTemplateStyle, hideEmpty } = options || {};
5457
5483
  const value = renderElement({ id: "value" });
5458
5484
  const hasUnits = elementConfig?.children?.some(({ id }) => id === "units");
5459
5485
  if (!value && hideEmpty)
5460
5486
  return null;
5461
- return (jsxRuntime.jsxs(Container, { style: innerTemplateStyle || style, children: [jsxRuntime.jsxs(ContainerAlias, { hasBottomMargin: true, children: [renderElement({ id: "alias" }), renderElement({ id: "tooltip" })] }), jsxRuntime.jsxs(ContainerValue, { children: [value, hasUnits && jsxRuntime.jsx(ContainerUnits, { children: renderElement({ id: "units" }) })] })] }));
5487
+ return (jsxRuntime.jsxs(Container, { id: id, style: innerTemplateStyle || style, children: [jsxRuntime.jsxs(ContainerAlias, { hasBottomMargin: true, children: [renderElement({ id: "alias" }), renderElement({ id: "tooltip" })] }), jsxRuntime.jsxs(ContainerValue, { children: [value, hasUnits && jsxRuntime.jsx(ContainerUnits, { children: renderElement({ id: "units" }) })] })] }));
5462
5488
  });
5463
5489
 
5464
5490
  const TwoColumnContainer = React.memo(({ config, elementConfig, type, renderElement }) => {
5465
5491
  const { selectedTabId, layerInfo, attributes } = useWidgetContext(type);
5466
5492
  const { attributes: renderAttributes } = elementConfig?.options || {};
5467
5493
  const renderContainer = React.useCallback((element, attribute) => {
5468
- const { options, style, children } = element || {};
5494
+ const { id, options, style, children } = element || {};
5469
5495
  const { hideEmpty, innerTemplateStyle } = options || {};
5470
5496
  const hasUnits = children?.some(({ id }) => id === "units");
5471
5497
  const iconIndex = children?.findIndex(({ id }) => id === "icon");
@@ -5503,7 +5529,7 @@ const TwoColumnContainer = React.memo(({ config, elementConfig, type, renderElem
5503
5529
  const value = render({ id: "value" });
5504
5530
  if (!value && hideEmpty)
5505
5531
  return null;
5506
- return (jsxRuntime.jsxs(TwoColumnContainerWrapper, { style: innerTemplateStyle || style, children: [jsxRuntime.jsxs(ContainerAlias, { children: [hasIcon && jsxRuntime.jsx(ContainerAliasIcon, { children: render({ id: "icon" }) }), render({ id: "alias" }), render({ id: "tooltip" })] }), jsxRuntime.jsxs(ContainerValue, { big: true, children: [value, hasUnits && jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) })] })] }, attribute));
5532
+ return (jsxRuntime.jsxs(TwoColumnContainerWrapper, { id: id, style: innerTemplateStyle || style, children: [jsxRuntime.jsxs(ContainerAlias, { children: [hasIcon && jsxRuntime.jsx(ContainerAliasIcon, { children: render({ id: "icon" }) }), render({ id: "alias" }), render({ id: "tooltip" })] }), jsxRuntime.jsxs(ContainerValue, { big: true, children: [value, hasUnits && jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) })] })] }, attribute));
5507
5533
  }, [attributes, config, getRenderElement, layerInfo, renderElement, selectedTabId, type]);
5508
5534
  return renderAttributes?.length ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderAttributes.map(attribute => renderContainer(elementConfig, attribute)) })) : (renderContainer(elementConfig));
5509
5535
  });
@@ -5694,7 +5720,7 @@ const DataSourceProgressContainer = React.memo(({ config, elementConfig, type, i
5694
5720
  dataSources
5695
5721
  });
5696
5722
  const { attributes } = layerInfo?.configuration?.attributesConfiguration || {};
5697
- const { id, options, children } = elementConfig || {};
5723
+ const { id, options, children, style } = elementConfig || {};
5698
5724
  const { maxValue, showTotal, relatedDataSource, expandable, expanded } = options || {};
5699
5725
  const valueElement = children?.find(item => item.id === "value");
5700
5726
  const unitsElement = children?.find(item => item.id === "units");
@@ -5722,7 +5748,7 @@ const DataSourceProgressContainer = React.memo(({ config, elementConfig, type, i
5722
5748
  return jsxRuntime.jsx(DataSourceError, { name: elementConfig.templateName });
5723
5749
  }
5724
5750
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
5725
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(DataSourceProgressContainerWrapper, { 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", { ns: "dashboard", defaultValue: "Показать все" }) })), 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 })] }));
5751
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(DataSourceProgressContainerWrapper, { id: id, style: style, 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", { ns: "dashboard", defaultValue: "Показать все" }) })), 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 })] }));
5726
5752
  });
5727
5753
 
5728
5754
  const ProgressContainer = React.memo(({ type, elementConfig, feature, maxValue, index, renderElement }) => {
@@ -5734,7 +5760,7 @@ const ProgressContainer = React.memo(({ type, elementConfig, feature, maxValue,
5734
5760
  dataSources,
5735
5761
  feature
5736
5762
  });
5737
- const { children, options, style } = elementConfig || {};
5763
+ const { id, children, options, style } = elementConfig || {};
5738
5764
  const { bgColor, innerTemplateStyle, maxValue: optionMaxValue, hideTitle, innerValue, colors, colorAttribute } = options;
5739
5765
  const valueElement = children?.find(({ id }) => id === "value");
5740
5766
  const unitsElement = children?.find(({ id }) => id === "units");
@@ -5761,7 +5787,7 @@ const ProgressContainer = React.memo(({ type, elementConfig, feature, maxValue,
5761
5787
  const color = React.useMemo(() => colorAttribute
5762
5788
  ? attributes?.find(({ name }) => name === colorAttribute)?.value
5763
5789
  : colors?.[index] || bgColor, [attributes, bgColor, colorAttribute, colors, index]);
5764
- return (jsxRuntime.jsx(uilibGl.Tooltip, { content: renderTooltip, placement: "top", arrow: true, children: ref => (jsxRuntime.jsxs(ProgressContainerWrapper, { ref: ref, style: innerTemplateStyle || style, children: [renderIcon && jsxRuntime.jsx(ProgressIcon, { children: renderIcon }), jsxRuntime.jsxs(ProgressContent, { children: [!hideTitle && (jsxRuntime.jsxs(ProgressAlias, { children: [jsxRuntime.jsx("div", { children: renderAlias }), jsxRuntime.jsxs(ProgressValue, { children: [renderValue, unitsElement && jsxRuntime.jsx(ProgressUnits, { children: renderElement({ id: "units" }) })] })] })), jsxRuntime.jsxs(ProgressBarContainer, { innerValue: innerValue, children: [jsxRuntime.jsx(ProgressBarWrapper, { children: jsxRuntime.jsx(ProgressBar, { "$width": width, "$color": color }) }), !!(hideTitle || innerValue) && jsxRuntime.jsx(ProgressInnerValue, { children: renderValue })] })] })] })) }));
5790
+ return (jsxRuntime.jsx(uilibGl.Tooltip, { content: renderTooltip, placement: "top", arrow: true, children: ref => (jsxRuntime.jsxs(ProgressContainerWrapper, { ref: ref, id: id, style: innerTemplateStyle || style, children: [renderIcon && jsxRuntime.jsx(ProgressIcon, { children: renderIcon }), jsxRuntime.jsxs(ProgressContent, { children: [!hideTitle && (jsxRuntime.jsxs(ProgressAlias, { children: [jsxRuntime.jsx("div", { children: renderAlias }), jsxRuntime.jsxs(ProgressValue, { children: [renderValue, unitsElement && jsxRuntime.jsx(ProgressUnits, { children: renderElement({ id: "units" }) })] })] })), jsxRuntime.jsxs(ProgressBarContainer, { innerValue: innerValue, children: [jsxRuntime.jsx(ProgressBarWrapper, { children: jsxRuntime.jsx(ProgressBar, { "$width": width, "$color": color }) }), !!(hideTitle || innerValue) && jsxRuntime.jsx(ProgressInnerValue, { children: renderValue })] })] })] })) }));
5765
5791
  });
5766
5792
 
5767
5793
  const RANGE_MIN_VALUE = 0;
@@ -5955,7 +5981,7 @@ const FiltersContainer = React.memo(({ elementConfig, config, type, renderElemen
5955
5981
  }, [config, type]);
5956
5982
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
5957
5983
  const selectedItems = React.useMemo(() => getFilterSelectedItems(filterItems, filters, configFilters), [configFilters, filters, filterItems]);
5958
- 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, { style: style, "$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 })] }));
5984
+ 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, { id: id, style: style, "$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 })] }));
5959
5985
  });
5960
5986
 
5961
5987
  const DefaultAttributesContainer = React.memo(({ type, renderElement }) => {
@@ -5964,7 +5990,7 @@ const DefaultAttributesContainer = React.memo(({ type, renderElement }) => {
5964
5990
  });
5965
5991
 
5966
5992
  const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderElement }) => {
5967
- const { options, children } = elementConfig || {};
5993
+ const { id, style, options, children } = elementConfig || {};
5968
5994
  const { twoColumns, hideEmpty } = options || {};
5969
5995
  const aliasElement = children.find(({ id }) => id === "alias");
5970
5996
  const chartElement = children.find(({ id }) => id === "chart");
@@ -5979,7 +6005,7 @@ const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderEleme
5979
6005
  const hasItems = !!data[0]?.items?.length;
5980
6006
  if (!loading && !hasItems && hideEmpty)
5981
6007
  return null;
5982
- return (jsxRuntime.jsxs(uilibGl.FlexSpan, { flexDirection: "column", 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: "center", children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { children: renderElement({ id: "chart" }) }), jsxRuntime.jsx(ContainerLegend, { justifyContent: legendElement?.options?.center ? "center" : "flex-start", children: renderElement({ id: "legend" }) })] })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: "\u2014" })) })] }))] }));
6008
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { id: id, style: style, isColumn: true, children: [aliasElement && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { column: !twoColumns, alignItems: "center", children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { children: renderElement({ id: "chart" }) }), jsxRuntime.jsx(ContainerLegend, { justifyContent: legendElement?.options?.center ? "center" : "flex-start", children: renderElement({ id: "legend" }) })] })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: "\u2014" })) })] }))] }));
5983
6009
  });
5984
6010
 
5985
6011
  const PagesContainer = React.memo(({ type = exports.WidgetType.Dashboard, noBorders }) => {
@@ -6015,10 +6041,6 @@ const PagesContainer = React.memo(({ type = exports.WidgetType.Dashboard, noBord
6015
6041
  return (jsxRuntime.jsx(Container, { id: getRootElementId(type), style: { width }, isMain: true, isColumn: isColumn, noBorders: noBorders, children: jsxRuntime.jsx(ContainerChildren, { items: filteredChildren, isMain: true, renderElement: renderElement }) }));
6016
6042
  });
6017
6043
 
6018
- const TwoColumnsInnerContainer = React.memo(({ renderElement }) => {
6019
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(TwoColumnContainerWrapper, { children: [jsxRuntime.jsxs(Container, { children: [jsxRuntime.jsx(ContainerAlias, { children: renderElement({ id: "firstAlias" }) }), jsxRuntime.jsx(ContainerValue, { big: true, children: renderElement({ id: "firstValue" }) })] }), jsxRuntime.jsxs(Container, { children: [jsxRuntime.jsx(ContainerAlias, { children: renderElement({ id: "secondAlias" }) }), jsxRuntime.jsx(ContainerValue, { big: true, children: renderElement({ id: "secondValue" }) })] })] }), renderElement({ id: "thirdContainer" })] }));
6020
- });
6021
-
6022
6044
  const ImageContainerBg$1 = styled.div `
6023
6045
  position: absolute;
6024
6046
  top: 0;
@@ -6080,8 +6102,8 @@ const ImageContainerWrapper = styled(uilibGl.Flex) `
6080
6102
  `;
6081
6103
 
6082
6104
  const ImageContainer = React.memo(({ elementConfig, renderElement }) => {
6083
- const { style } = elementConfig || {};
6084
- return (jsxRuntime.jsxs(ImageContainerWrapper, { style: style, children: [jsxRuntime.jsx(ImageContainerTitle, { children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ImageContainerText, { children: renderElement({ id: "text" }) }), renderElement({ id: "button" }), jsxRuntime.jsx(ImageContainerBg$1, { children: renderElement({ id: "image" }) })] }));
6105
+ const { id, style } = elementConfig || {};
6106
+ return (jsxRuntime.jsxs(ImageContainerWrapper, { id: id, style: style, children: [jsxRuntime.jsx(ImageContainerTitle, { children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ImageContainerText, { children: renderElement({ id: "text" }) }), renderElement({ id: "button" }), jsxRuntime.jsx(ImageContainerBg$1, { children: renderElement({ id: "image" }) })] }));
6085
6107
  });
6086
6108
 
6087
6109
  const IconContainerWrapper = styled(uilibGl.Flex) `
@@ -6133,7 +6155,8 @@ const IconContainerText = styled.div `
6133
6155
  `;
6134
6156
 
6135
6157
  const IconContainer = React.memo(({ elementConfig, renderElement }) => {
6136
- return (jsxRuntime.jsxs(IconContainerWrapper, { style: elementConfig?.style, children: [jsxRuntime.jsxs(IconContainerHeaderWrapper, { children: [jsxRuntime.jsxs(IconContainerHeader, { children: [renderElement({ id: "icon" }), jsxRuntime.jsx(IconContainerTitle, { children: renderElement({ id: "alias" }) })] }), renderElement({ id: "link" })] }), jsxRuntime.jsx(IconContainerText, { children: renderElement({ id: "text" }) })] }));
6158
+ const { id, style } = elementConfig || {};
6159
+ return (jsxRuntime.jsxs(IconContainerWrapper, { id: id, style: style, children: [jsxRuntime.jsxs(IconContainerHeaderWrapper, { children: [jsxRuntime.jsxs(IconContainerHeader, { children: [renderElement({ id: "icon" }), jsxRuntime.jsx(IconContainerTitle, { children: renderElement({ id: "alias" }) })] }), renderElement({ id: "link" })] }), jsxRuntime.jsx(IconContainerText, { children: renderElement({ id: "text" }) })] }));
6137
6160
  });
6138
6161
 
6139
6162
  const DataSourceContainer = React.memo(({ config, elementConfig, type, innerComponent, renderElement }) => {
@@ -6148,7 +6171,7 @@ const DataSourceContainer = React.memo(({ config, elementConfig, type, innerComp
6148
6171
  return jsxRuntime.jsx(DataSourceError, { name: elementConfig.templateName });
6149
6172
  }
6150
6173
  const isLoading = !dataSource?.features;
6151
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsx(Container, { isColumn: column, style: { height: isLoading ? "3rem" : "auto", ...style }, children: dataSource.features?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { index: index, type: type, config: config, feature: feature, elementConfig: elementConfig, innerComponent: innerComponent }, index))) })) : (jsxRuntime.jsx(ContainerLoading, {}))] }));
6174
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsx(Container, { id: id, isColumn: column, style: { height: isLoading ? "3rem" : "auto", ...style }, children: dataSource.features?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { index: index, type: type, config: config, feature: feature, elementConfig: elementConfig, innerComponent: innerComponent }, index))) })) : (jsxRuntime.jsx(ContainerLoading, {}))] }));
6152
6175
  });
6153
6176
 
6154
6177
  const SvgContainerColorMixin = styled.css `
@@ -6174,12 +6197,25 @@ const SvgContainer = styled.div `
6174
6197
  const ContainerIconTitle = styled(uilibGl.Flex) `
6175
6198
  align-items: center;
6176
6199
  flex-wrap: nowrap;
6200
+ flex-shrink: 1;
6201
+ flex-grow: 0;
6177
6202
  color: ${({ fontColor, theme: { palette } }) => fontColor || palette.textSecondary};
6178
6203
 
6204
+ > div {
6205
+ flex-shrink: 1;
6206
+ flex-grow: 0;
6207
+ width: auto;
6208
+ }
6209
+
6210
+ ${SvgContainer} {
6211
+ flex-shrink: 0;
6212
+ flex-grow: 0;
6213
+ margin-right: 0.5rem;
6214
+ }
6215
+
6179
6216
  svg,
6180
6217
  img,
6181
- span[kind],
6182
- ${SvgContainer} {
6218
+ span[kind] {
6183
6219
  margin-right: 0.5rem;
6184
6220
  }
6185
6221
 
@@ -6245,7 +6281,7 @@ const TitleContainer = React.memo(({ containerId, templateName, layerNames, font
6245
6281
  const { expandContainer, expandedContainers, setDashboardLayer } = useWidgetContext(type);
6246
6282
  const [layersVisibility, toggleVisibility] = useToggle(true);
6247
6283
  const { palette } = styled.useTheme();
6248
- const { style, options } = elementConfig || {};
6284
+ const { id, style, options } = elementConfig || {};
6249
6285
  const { simple, downloadById } = options || {};
6250
6286
  const isLayers = templateName === exports.ContainerTemplate.Layers;
6251
6287
  const { onExport } = useExportPdf(downloadById);
@@ -6263,7 +6299,7 @@ const TitleContainer = React.memo(({ containerId, templateName, layerNames, font
6263
6299
  const renderVisibility = React.useMemo(() => isLayers && (jsxRuntime.jsx(uilibGl.FlexSpan, { mr: "-1rem", children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: layersVisibility ? "password_show" : "password_hide", className: "feature-visible", isSelected: layersVisibility, onClick: onToggleVisibility }) })), [isLayers, layersVisibility, onToggleVisibility]);
6264
6300
  const renderToggler = React.useMemo(() => !!containerId &&
6265
6301
  expandable && (jsxRuntime.jsx("div", { children: jsxRuntime.jsx(uilibGl.LegendToggler, { color: palette.icon, toggled: expandedContainers?.[containerId] !== undefined ? expandedContainers[containerId] : expanded, onClick: onClick }) })), [containerId, expandable, expanded, expandedContainers, onClick, palette.icon]);
6266
- return (jsxRuntime.jsx(Container, { isTitle: isVisible, style: style, children: jsxRuntime.jsxs(ContainerTitle, { simple: simple, children: [jsxRuntime.jsxs(ContainerIconTitle, { fontColor: fontColor, children: [renderElement({ id: "titleIcon", wrap: false }), renderElement({ id: "title" }), !!downloadById && (jsxRuntime.jsx(uilibGl.IconButton, { kind: "download", onClick: onExport })), isLayers && renderToggler] }), !isLayers && renderToggler, renderVisibility] }) }));
6302
+ return (jsxRuntime.jsx(Container, { id: id, style: style, isTitle: isVisible, children: jsxRuntime.jsxs(ContainerTitle, { simple: simple, children: [jsxRuntime.jsxs(ContainerIconTitle, { fontColor: fontColor, children: [renderElement({ id: "titleIcon", wrap: false }), renderElement({ id: "title" }), !!downloadById && (jsxRuntime.jsx(uilibGl.IconButton, { kind: "download", onClick: onExport })), isLayers && renderToggler] }), !isLayers && renderToggler, renderVisibility] }) }));
6267
6303
  });
6268
6304
 
6269
6305
  const ContainerDivider = styled(uilibGl.Divider) `
@@ -6272,7 +6308,8 @@ const ContainerDivider = styled(uilibGl.Divider) `
6272
6308
  `;
6273
6309
 
6274
6310
  const DividerContainer = React.memo(({ elementConfig, config }) => {
6275
- return (jsxRuntime.jsx(Container, { style: elementConfig?.style, children: jsxRuntime.jsx(ContainerDivider, { "$bgColor": config?.options?.bgColor }) }));
6311
+ const { id, style } = elementConfig || {};
6312
+ return (jsxRuntime.jsx(Container, { id: id, style: style, children: jsxRuntime.jsx(ContainerDivider, { "$bgColor": config?.options?.bgColor }) }));
6276
6313
  });
6277
6314
 
6278
6315
  const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
@@ -6282,7 +6319,7 @@ const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
6282
6319
  elementConfig,
6283
6320
  dataSources,
6284
6321
  });
6285
- const { id, options } = elementConfig || {};
6322
+ const { id, style, options } = elementConfig || {};
6286
6323
  const { expandable, expanded } = options || {};
6287
6324
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
6288
6325
  const render = React.useMemo(() => getRenderElement({
@@ -6307,7 +6344,7 @@ const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
6307
6344
  pageIndex,
6308
6345
  type,
6309
6346
  ]);
6310
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: render }), isVisible && (jsxRuntime.jsxs(Container, { style: elementConfig?.style, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: render({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: render({
6347
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: render }), isVisible && (jsxRuntime.jsxs(Container, { style: style, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: render({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: render({
6311
6348
  id: "slideshow",
6312
6349
  wrap: false,
6313
6350
  }) })] }))] }));
@@ -6318,7 +6355,7 @@ const CameraContainer = React.memo(({ elementConfig, type, renderElement }) => {
6318
6355
  const { id, options, style } = elementConfig || {};
6319
6356
  const { expandable, expanded } = options || {};
6320
6357
  const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
6321
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { style: style, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value", wrap: false }) })] }))] }));
6358
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { id: id, style: style, children: [jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { children: renderElement({ id: "value", wrap: false }) })] }))] }));
6322
6359
  });
6323
6360
 
6324
6361
  const TabAnchor = styled.div `
@@ -6402,7 +6439,7 @@ const SwiperContainer = styled.div `
6402
6439
  const TabsContainer = React.memo(({ elementConfig, type }) => {
6403
6440
  const { palette } = styled.useTheme();
6404
6441
  const { selectedTabId, setSelectedTabId } = useWidgetContext(type);
6405
- const { options, style, children: tabs } = elementConfig || {};
6442
+ const { id, options, style, children: tabs } = elementConfig || {};
6406
6443
  const { radius, column, bgColor, noBg, onlyIcon, shownItems, maxLength = 12 } = options || {};
6407
6444
  const renderIcon = React.useCallback((icon, active) => {
6408
6445
  if (!icon)
@@ -6420,7 +6457,7 @@ const TabsContainer = React.memo(({ elementConfig, type }) => {
6420
6457
  setSelectedTabId(tabs[0].id);
6421
6458
  }
6422
6459
  }, []);
6423
- return (jsxRuntime.jsx(SwiperContainer, { style: style, children: jsxRuntime.jsx(react.Swiper, { spaceBetween: 0, slidesPerView: shownItems || 2, children: tabs.map(({ id, value, options: tabOptions }) => (jsxRuntime.jsxs(react.SwiperSlide, { children: [jsxRuntime.jsxs(TabContainer, { href: `#${id}`, active: selectedTabId === id, column: column, bgColor: bgColor, noBg: noBg, radius: radius, onlyIcon: onlyIcon, hasIcon: !!tabOptions?.icon, onClick: () => onClick(id), children: [renderIcon(tabOptions?.icon, selectedTabId === id), !onlyIcon && (jsxRuntime.jsx(TabValue, { children: jsxRuntime.jsx(TextTrim, { maxLength: maxLength, children: value }) }))] }), jsxRuntime.jsx(TabAnchor, { id: id })] }, id))) }) }));
6460
+ return (jsxRuntime.jsx(SwiperContainer, { id: id, style: style, children: jsxRuntime.jsx(react.Swiper, { spaceBetween: 0, slidesPerView: shownItems || 2, children: tabs.map(({ id, value, options: tabOptions }) => (jsxRuntime.jsxs(react.SwiperSlide, { children: [jsxRuntime.jsxs(TabContainer, { href: `#${id}`, active: selectedTabId === id, column: column, bgColor: bgColor, noBg: noBg, radius: radius, onlyIcon: onlyIcon, hasIcon: !!tabOptions?.icon, onClick: () => onClick(id), children: [renderIcon(tabOptions?.icon, selectedTabId === id), !onlyIcon && (jsxRuntime.jsx(TabValue, { children: jsxRuntime.jsx(TextTrim, { maxLength: maxLength, children: value }) }))] }), jsxRuntime.jsx(TabAnchor, { id: id })] }, id))) }) }));
6424
6461
  });
6425
6462
 
6426
6463
  const ContainerIconValue = styled(uilibGl.Flex) ``;
@@ -6526,7 +6563,7 @@ const RoundedBackgroundContainer = React.memo(({ type, elementConfig, feature, r
6526
6563
  dataSources,
6527
6564
  feature
6528
6565
  });
6529
- const { options, style, children } = elementConfig || {};
6566
+ const { id, options, style, children } = elementConfig || {};
6530
6567
  const { maxLength, center, fontColor, innerTemplateStyle, inlineUnits, big, bigIcon, hideEmpty, colorAttribute } = options || {};
6531
6568
  const iconElement = children?.find(({ id }) => id === "icon");
6532
6569
  const aliasElement = children?.find(({ id }) => id === "alias");
@@ -6550,12 +6587,12 @@ const RoundedBackgroundContainer = React.memo(({ type, elementConfig, feature, r
6550
6587
  const renderValue = React.useMemo(() => lodash.isNil(value) ? null : (jsxRuntime.jsxs(ContainerValue, { style: valueElement?.style, big: true, children: [value, !!unitsElement && (jsxRuntime.jsx(ContainerUnits, { style: unitsElement?.style, children: renderElement({ id: "units" }) }))] })), [valueElement?.style, value, unitsElement, renderElement]);
6551
6588
  if (lodash.isNil(value) && hideEmpty)
6552
6589
  return null;
6553
- return (jsxRuntime.jsxs(RoundedBackgroundContainerWrapper, { style: innerTemplateStyle || style, "$center": center, "$color": color, "$inlineUnits": inlineUnits, "$big": big, "$bigIcon": bigIcon, children: [jsxRuntime.jsxs(ContainerIconValue, { children: [renderIcon, big ? renderAlias : renderValue] }), big ? renderValue : renderAlias] }));
6590
+ return (jsxRuntime.jsxs(RoundedBackgroundContainerWrapper, { id: id, style: innerTemplateStyle || style, "$center": center, "$color": color, "$inlineUnits": inlineUnits, "$big": big, "$bigIcon": bigIcon, children: [jsxRuntime.jsxs(ContainerIconValue, { children: [renderIcon, big ? renderAlias : renderValue] }), big ? renderValue : renderAlias] }));
6554
6591
  });
6555
6592
 
6556
6593
  const AddFeatureContainer = React.memo(({ elementConfig }) => {
6557
- const { children, style } = elementConfig || {};
6558
- return (jsxRuntime.jsx(Container, { style: style, children: children
6594
+ const { id, children, style } = elementConfig || {};
6595
+ return (jsxRuntime.jsx(Container, { id: id, style: style, children: children
6559
6596
  .filter(({ type }) => type === "button")
6560
6597
  .map(({ options }, index) => (jsxRuntime.jsx(AddFeatureButton, { icon: options?.icon, title: options?.title, layerName: options?.layerName, geometryType: options?.geometryType }, index))) }));
6561
6598
  });
@@ -6589,15 +6626,15 @@ const LayersContainer = React.memo(({ type, elementConfig, renderElement }) => {
6589
6626
  return currentPage.layers;
6590
6627
  return currentPage.layers.filter(({ name }) => layerNames.includes(name));
6591
6628
  }, [currentPage?.layers, layerNames]);
6592
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { style: style, children: jsxRuntime.jsx(LayerTree, { layers: layers, onlyMainTools: true }) }))] }));
6629
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { id: id, style: style, children: jsxRuntime.jsx(LayerTree, { layers: layers, onlyMainTools: true }) }))] }));
6593
6630
  });
6594
6631
 
6595
6632
  const ExportPdfContainer = React.memo(({ type, elementConfig }) => {
6596
6633
  const { t } = useGlobalContext();
6597
6634
  const { loading, onExport } = useExportPdf(getRootElementId(type));
6598
- const { style, options } = elementConfig || {};
6635
+ const { id, style, options } = elementConfig || {};
6599
6636
  const { icon, title } = options || {};
6600
- return (jsxRuntime.jsx(Container, { children: jsxRuntime.jsx(uilibGl.IconButton, { kind: icon || "download", primary: true, disabled: loading, style: style, onClick: onExport, children: title ?? t("downloadPdf", { ns: "dashboard", defaultValue: "Скачать PDF" }) }) }));
6637
+ return (jsxRuntime.jsx(Container, { id: id, style: style, children: jsxRuntime.jsx(uilibGl.IconButton, { kind: icon || "download", primary: true, disabled: loading, onClick: onExport, children: title ?? t("downloadPdf", { ns: "dashboard", defaultValue: "Скачать PDF" }) }) }));
6601
6638
  });
6602
6639
 
6603
6640
  const containerComponents = {
@@ -6608,7 +6645,6 @@ const containerComponents = {
6608
6645
  [exports.ContainerTemplate.RoundedBackground]: RoundedBackgroundContainer,
6609
6646
  [exports.ContainerTemplate.OneColumn]: OneColumnContainer,
6610
6647
  [exports.ContainerTemplate.TwoColumn]: TwoColumnContainer,
6611
- [exports.ContainerTemplate.TwoColumnsInner]: TwoColumnsInnerContainer,
6612
6648
  [exports.ContainerTemplate.DataSource]: DataSourceContainer,
6613
6649
  [exports.ContainerTemplate.DataSourceProgress]: DataSourceProgressContainer,
6614
6650
  [exports.ContainerTemplate.Progress]: ProgressContainer,
@@ -7550,6 +7586,169 @@ const ElementLink = React.memo(({ type, elementConfig }) => {
7550
7586
  return link.startsWith("http") ? jsxRuntime.jsx(ExternalLink, { onClick: () => window.open(link) }) : jsxRuntime.jsx(LocalLink, { link: link });
7551
7587
  });
7552
7588
 
7589
+ const MarkdownWrapper = styled.div `
7590
+ padding: 0;
7591
+ background: transparent;
7592
+ border-radius: 0.5rem;
7593
+ font-family: 'Nunito Sans', sans-serif;
7594
+ color: ${({ theme: { palette } }) => palette.textPrimary};
7595
+
7596
+ /* Paragraphs */
7597
+ p {
7598
+ font-size: 0.875rem;
7599
+ line-height: 1rem;
7600
+ letter-spacing: 0.0052rem;
7601
+ margin: 0 0 1rem 0;
7602
+ font-weight: 400;
7603
+
7604
+ &:last-child {
7605
+ margin-bottom: 0;
7606
+ }
7607
+ }
7608
+
7609
+ /* Headings */
7610
+ h1, h2, h3, h4, h5, h6 {
7611
+ margin: 0 0 0.75rem 0;
7612
+ font-weight: 300;
7613
+ }
7614
+
7615
+ h1 {
7616
+ font-size: 1.5rem;
7617
+ line-height: 1.75rem;
7618
+ }
7619
+
7620
+ h2 {
7621
+ font-size: 1.25rem;
7622
+ line-height: 1.5rem;
7623
+ }
7624
+
7625
+ h3 {
7626
+ font-size: 1rem;
7627
+ line-height: 1.25rem;
7628
+ }
7629
+
7630
+ /* Images */
7631
+ img {
7632
+ max-width: 100%;
7633
+ height: auto;
7634
+ border-radius: 0.5rem;
7635
+ object-fit: cover;
7636
+ margin: 0.75rem 0;
7637
+ }
7638
+
7639
+ /* Links */
7640
+ a {
7641
+ color: ${({ theme: { palette } }) => palette.primary};
7642
+ text-decoration: none;
7643
+
7644
+ &:hover {
7645
+ text-decoration: underline;
7646
+ }
7647
+ }
7648
+
7649
+ /* Lists */
7650
+ ul, ol {
7651
+ margin: 0 0 1rem 0;
7652
+ padding-left: 1.25rem;
7653
+
7654
+ li {
7655
+ font-size: 0.875rem;
7656
+ line-height: 1rem;
7657
+ margin-bottom: 0.5rem;
7658
+ }
7659
+ }
7660
+
7661
+ /* Code */
7662
+ code {
7663
+ background: ${({ theme: { palette } }) => palette.element};
7664
+ padding: 0.125rem 0.375rem;
7665
+ border-radius: 0.25rem;
7666
+ font-family: monospace;
7667
+ font-size: 0.8125rem;
7668
+ }
7669
+
7670
+ pre {
7671
+ background: ${({ theme: { palette } }) => palette.element};
7672
+ padding: 0.75rem;
7673
+ border-radius: 0.25rem;
7674
+ overflow-x: auto;
7675
+ margin: 0.75rem 0;
7676
+
7677
+ code {
7678
+ background: transparent;
7679
+ padding: 0;
7680
+ }
7681
+ }
7682
+
7683
+ /* Hide horizontal rules */
7684
+ hr {
7685
+ display: none;
7686
+ }
7687
+ `;
7688
+ styled(uilibGl.Flex) `
7689
+ align-items: center;
7690
+ gap: 1rem;
7691
+ margin-top: 1rem;
7692
+ `;
7693
+ styled.span `
7694
+ display: block;
7695
+ font-size: 0.75rem;
7696
+ line-height: 0.875rem;
7697
+ opacity: 0.36;
7698
+ margin: 0 0 0.5rem 0;
7699
+ `;
7700
+ styled.div `
7701
+ width: 1.25rem;
7702
+ height: 1.25rem;
7703
+ cursor: pointer;
7704
+ transition: opacity 0.2s;
7705
+
7706
+ &:hover {
7707
+ opacity: 0.7;
7708
+ }
7709
+
7710
+ img, svg {
7711
+ width: 100%;
7712
+ height: 100%;
7713
+ display: block;
7714
+ }
7715
+ `;
7716
+ const ExpandButton = styled(uilibGl.IconButton) `
7717
+ margin-bottom: 1rem;
7718
+ `;
7719
+
7720
+ const ElementMarkdown = React.memo(({ elementConfig, type }) => {
7721
+ const { attributes } = useWidgetContext(type);
7722
+ const { t } = useGlobalContext();
7723
+ const [expanded, setExpanded] = React.useState(false);
7724
+ const { attributeName, value, options } = elementConfig || {};
7725
+ const expandLength = options?.expandLength || 0;
7726
+ // Get markdown content from:
7727
+ // 1. value (static content)
7728
+ // 2. attribute by attributeName (dynamic content from data)
7729
+ let content = value;
7730
+ if (!content && attributeName && attributes) {
7731
+ const attribute = attributes.find(attr => attr.name === attributeName);
7732
+ content = attribute?.value;
7733
+ }
7734
+ if (!content)
7735
+ return null;
7736
+ const markdownString = String(content);
7737
+ const shouldShowExpand = expandLength > 0 && markdownString.length > expandLength;
7738
+ // If expand is not needed, show full content
7739
+ if (!shouldShowExpand) {
7740
+ return (jsxRuntime.jsx(MarkdownWrapper, { children: jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: markdownString }) }));
7741
+ }
7742
+ // Truncated content for collapsed state
7743
+ const truncatedContent = markdownString.substring(0, expandLength);
7744
+ // Collapsed state
7745
+ if (!expanded) {
7746
+ return (jsxRuntime.jsxs(MarkdownWrapper, { children: [jsxRuntime.jsx(ExpandButton, { primary: true, icon: jsxRuntime.jsx(uilibGl.Expander, { isSelected: false }), onClick: () => setExpanded(true), children: t("more", { ns: "dashboard", defaultValue: "Подробнее" }) }), jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: truncatedContent })] }));
7747
+ }
7748
+ // Expanded state
7749
+ return (jsxRuntime.jsxs(MarkdownWrapper, { children: [jsxRuntime.jsx(ExpandButton, { primary: true, icon: jsxRuntime.jsx(uilibGl.Expander, { isSelected: true }), onClick: () => setExpanded(false), children: t("hide", { ns: "dashboard", defaultValue: "Свернуть" }) }), jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: markdownString })] }));
7750
+ });
7751
+
7553
7752
  const SmallPreviewContainer = styled.div `
7554
7753
  width: 100%;
7555
7754
  height: 100%;
@@ -7829,6 +8028,7 @@ const elementComponents = {
7829
8028
  camera: ElementCamera,
7830
8029
  chart: ElementChart,
7831
8030
  legend: ElementLegend,
8031
+ markdown: ElementMarkdown,
7832
8032
  };
7833
8033
 
7834
8034
  const getElementValue = ({ getDefaultContainer, ...props }) => {
@@ -8420,6 +8620,268 @@ const RangeDateFilter = ({ type, filter }) => {
8420
8620
  return (jsxRuntime.jsx(uilibGl.RangeNumberInput, { label: label || t("interval", { ns: "dashboard", defaultValue: "Интервал" }), selectedOption: { range: true }, minDate: getDate(minDate), maxDate: getDate(maxDate), value: [getDate(value[0]), getDate(value[1])], zIndex: 100, prefix: jsxRuntime.jsx(uilibGl.Icon, { kind: "date", disabled: true }), suffix: !isEmpty && !isDefault && jsxRuntime.jsx(StyledIconButton, { kind: "error", onClick: reset }), withTime: withTime, isDate: true, onChange: onChange }));
8421
8621
  };
8422
8622
 
8623
+ const getJustifyContent = (align) => {
8624
+ switch (align) {
8625
+ case "center":
8626
+ return "center";
8627
+ case "right":
8628
+ return "flex-end";
8629
+ case "left":
8630
+ default:
8631
+ return "flex-start";
8632
+ }
8633
+ };
8634
+ const ChipsContainer = styled(uilibGl.Flex) `
8635
+ flex-wrap: wrap;
8636
+ gap: 0.25rem;
8637
+ background: transparent;
8638
+ justify-content: ${({ $align }) => getJustifyContent($align)};
8639
+ `;
8640
+
8641
+ const FilterChip = styled.div `
8642
+ display: inline-flex;
8643
+ align-items: center;
8644
+ gap: 0.25rem;
8645
+ padding: 0.3125rem 0.5rem;
8646
+ height: 1.5rem;
8647
+ border-radius: 0.25rem;
8648
+ background-color: ${({ $isActive, $bgColor, theme }) => $bgColor
8649
+ ? $bgColor
8650
+ : $isActive
8651
+ ? theme.palette?.primary
8652
+ : theme.palette?.elementLight};
8653
+ color: ${({ $isActive, $textColor, theme }) => $textColor
8654
+ ? $textColor
8655
+ : $isActive
8656
+ ? theme.palette?.textContrast
8657
+ : theme.palette?.textSecondary};
8658
+ cursor: pointer;
8659
+ font-size: 0.75rem;
8660
+ line-height: 0.875rem;
8661
+ white-space: nowrap;
8662
+ flex-shrink: 0;
8663
+ transition: all 0.2s ease-in-out;
8664
+ margin: 0 0.25rem 0 0;
8665
+ box-sizing: border-box;
8666
+
8667
+ &:hover {
8668
+ background-color: ${({ $isActive, $bgColor, theme }) => $isActive
8669
+ ? $bgColor || 'inherit'
8670
+ : $bgColor || theme.palette?.elementDark};
8671
+ }
8672
+ `;
8673
+ const ChipIconWrapper = styled.span `
8674
+ display: inline-flex;
8675
+ align-items: center;
8676
+ justify-content: center;
8677
+ width: 0.875rem;
8678
+ height: 0.875rem;
8679
+ flex-shrink: 0;
8680
+
8681
+ svg, img {
8682
+ width: 100%;
8683
+ height: 100%;
8684
+ display: block;
8685
+ }
8686
+ `;
8687
+ const ChipText = styled.span `
8688
+ overflow: hidden;
8689
+ text-overflow: ellipsis;
8690
+ white-space: nowrap;
8691
+ ${({ $maxTextWidth }) => $maxTextWidth && `max-width: ${$maxTextWidth / 16}rem;`}
8692
+ `;
8693
+
8694
+ const CustomChip = ({ text, icon, color, primary, secondary, error, disabled, isActive, maxTextWidth, fontColor: customFontColor, backgroundColor: customBackgroundColor, ...props }) => {
8695
+ const theme = styled.useTheme();
8696
+ const { palette } = theme;
8697
+ // Helper to add transparency to hex color
8698
+ const addTransparency = (hex, transparency = '1f') => {
8699
+ // Ensure hex starts with #
8700
+ const cleanHex = hex.startsWith('#') ? hex : `#${hex}`;
8701
+ return `${cleanHex}${transparency}`;
8702
+ };
8703
+ // Calculate colors based on priority:
8704
+ // 1. customFontColor / customBackgroundColor (highest, from options)
8705
+ // 2. color (from attribute)
8706
+ // 3. primary/secondary/error
8707
+ // 4. default theme colors
8708
+ let bgColor;
8709
+ let textColor;
8710
+ if (isActive) {
8711
+ // Priority 1: Custom colors from options
8712
+ if (customFontColor) {
8713
+ textColor = customFontColor;
8714
+ bgColor = customBackgroundColor || addTransparency(customFontColor); // 12% opacity
8715
+ }
8716
+ // Priority 2: Color from attribute
8717
+ else if (color) {
8718
+ textColor = palette.textPrimary; // White text for active chip
8719
+ bgColor = color; // Full color without transparency
8720
+ }
8721
+ // Priority 3: Variant colors
8722
+ else if (primary) {
8723
+ bgColor = theme.message.color.success; // Green
8724
+ textColor = palette.textContrast;
8725
+ }
8726
+ else if (secondary) {
8727
+ bgColor = palette.primary;
8728
+ textColor = palette.textContrast;
8729
+ }
8730
+ else if (error) {
8731
+ bgColor = theme.message.color.warning; // Yellow
8732
+ textColor = palette.textPrimary;
8733
+ }
8734
+ // Priority 4: Default - no colors specified
8735
+ else {
8736
+ textColor = palette.primary;
8737
+ bgColor = addTransparency(palette.primary); // palette.primary + 12%
8738
+ }
8739
+ }
8740
+ else {
8741
+ // Inactive state
8742
+ if (color) {
8743
+ textColor = color; // Use color for text
8744
+ bgColor = addTransparency(color); // Uses default 1f (12%) transparency
8745
+ }
8746
+ // else: No color attribute - leave bgColor and textColor undefined
8747
+ // Styled component will use fallback for inactive: bg = rgba(0,0,0,0.06), text = palette.textSecondary
8748
+ }
8749
+ const renderIcon = React.useCallback((iconValue) => {
8750
+ if (!iconValue) {
8751
+ return null;
8752
+ }
8753
+ // If icon doesn't contain a dot and doesn't start with /sp/, it's a built-in icon from uilib-gl
8754
+ if (!iconValue.includes(".") && !iconValue.startsWith("/sp/")) {
8755
+ return jsxRuntime.jsx(uilibGl.Icon, { kind: iconValue });
8756
+ }
8757
+ // If it's an SVG file or resourceId path, use SvgImage component
8758
+ const isSvg = iconValue.endsWith(".svg") || iconValue.startsWith("/sp/resources/file/");
8759
+ if (isSvg) {
8760
+ const iconColor = textColor
8761
+ ? textColor
8762
+ : isActive
8763
+ ? palette.textContrast
8764
+ : palette.textSecondary;
8765
+ return (jsxRuntime.jsx(SvgImage, { url: iconValue, width: 14, height: 14, fontColor: iconColor }));
8766
+ }
8767
+ // Otherwise, it's a regular image
8768
+ return jsxRuntime.jsx("img", { src: iconValue, alt: "" });
8769
+ }, [isActive, textColor, palette.textContrast, palette.textSecondary]);
8770
+ return (jsxRuntime.jsxs(FilterChip, { "$isActive": isActive, "$bgColor": bgColor, "$textColor": textColor, ...props, children: [icon && jsxRuntime.jsx(ChipIconWrapper, { children: renderIcon(icon) }), jsxRuntime.jsx(ChipText, { "$maxTextWidth": maxTextWidth, children: text })] }));
8771
+ };
8772
+
8773
+ const ChipsFilter = ({ type, filter, elementConfig, }) => {
8774
+ const { filters, dataSources, changeFilters } = useWidgetContext(type);
8775
+ const { currentPage } = useWidgetPage(type);
8776
+ const theme = styled.useTheme();
8777
+ const { filters: configFilters } = currentPage;
8778
+ const { options } = elementConfig || {};
8779
+ const { align } = options || {};
8780
+ const { filterName, colorAttribute, iconAttribute, maxTextWidth, icon, fontColor, backgroundColor, } = filter.options;
8781
+ const configFilter = getConfigFilter(filterName, configFilters);
8782
+ const multiSelect = configFilter?.valueType === "array";
8783
+ // Process icon URL (resourceId or direct URL)
8784
+ const processedIcon = icon ? getResourceUrl(icon) : undefined;
8785
+ const chipOptions = React.useMemo(() => {
8786
+ if (!configFilter)
8787
+ return [];
8788
+ const dataSource = getDataSource(configFilter.relatedDataSource, dataSources);
8789
+ if (!dataSource?.features)
8790
+ return [];
8791
+ const features = dataSource.features;
8792
+ return features.map(feature => {
8793
+ const attrs = feature.attributes;
8794
+ const text = attrs[configFilter.attributeAlias || DEFAULT_ATTRIBUTE_NAME];
8795
+ const value = attrs[configFilter.attributeValue || DEFAULT_ATTRIBUTE_NAME];
8796
+ const chipIcon = iconAttribute
8797
+ ? getIconFromAttribute(attrs, iconAttribute)
8798
+ : undefined;
8799
+ const chipColor = colorAttribute
8800
+ ? getColorFromAttribute(attrs, colorAttribute, theme)
8801
+ : undefined;
8802
+ return {
8803
+ text,
8804
+ value,
8805
+ color: chipColor,
8806
+ icon: chipIcon,
8807
+ };
8808
+ });
8809
+ }, [configFilter, dataSources, colorAttribute, iconAttribute, theme]);
8810
+ const isChipActive = React.useCallback((chipValue) => {
8811
+ const currentValue = filters?.[filterName]?.value;
8812
+ if (currentValue === undefined) {
8813
+ return checkEqualOrIncludes(configFilter?.defaultValue, chipValue);
8814
+ }
8815
+ return checkEqualOrIncludes(currentValue, chipValue);
8816
+ }, [filters, filterName, configFilter]);
8817
+ const handleChipClick = React.useCallback((chipValue) => {
8818
+ const currentValue = filters?.[filterName]?.value;
8819
+ let newValue;
8820
+ if (multiSelect) {
8821
+ const currentArray = Array.isArray(currentValue)
8822
+ ? currentValue
8823
+ : currentValue
8824
+ ? [currentValue]
8825
+ : [];
8826
+ const valueIndex = currentArray.indexOf(chipValue);
8827
+ if (valueIndex >= 0) {
8828
+ const filtered = currentArray.filter(v => v !== chipValue);
8829
+ if (filtered.length === 0) {
8830
+ newValue = configFilter?.defaultValue || null;
8831
+ }
8832
+ else {
8833
+ newValue = filtered;
8834
+ }
8835
+ }
8836
+ else {
8837
+ newValue = [...currentArray, chipValue];
8838
+ }
8839
+ }
8840
+ else {
8841
+ if (currentValue === chipValue) {
8842
+ newValue = configFilter?.defaultValue || null;
8843
+ }
8844
+ else {
8845
+ newValue = chipValue;
8846
+ }
8847
+ }
8848
+ changeFilters({
8849
+ [filterName]: { value: newValue },
8850
+ });
8851
+ }, [filters, filterName, multiSelect, changeFilters, configFilter]);
8852
+ if (!configFilter)
8853
+ return null;
8854
+ return (jsxRuntime.jsx(ChipsContainer, { "$align": align, children: chipOptions.map((chip, index) => {
8855
+ const isActive = isChipActive(chip.value);
8856
+ // Use chip.icon from attribute or fallback to static icon
8857
+ const chipIcon = chip.icon || processedIcon;
8858
+ return (jsxRuntime.jsx(CustomChip, { text: chip.text, icon: chipIcon, color: chip.color, isActive: isActive, maxTextWidth: maxTextWidth, fontColor: fontColor, backgroundColor: backgroundColor, onClick: () => handleChipClick(chip.value), title: chip.text }, index));
8859
+ }) }));
8860
+ };
8861
+ function getColorFromAttribute(option, colorAttribute, theme) {
8862
+ const value = option[colorAttribute];
8863
+ // If value is already a hex color (starts with #), return it directly
8864
+ if (value && typeof value === 'string' && value.startsWith('#')) {
8865
+ return value;
8866
+ }
8867
+ // Otherwise, map string values to theme colors
8868
+ const colorMap = {
8869
+ active: theme?.message?.color?.success,
8870
+ warning: theme?.message?.color?.warning,
8871
+ info: theme?.message?.color?.info,
8872
+ inactive: theme?.palette?.textDisabled,
8873
+ };
8874
+ return value && typeof value === 'string' ? colorMap[value.toLowerCase()] : undefined;
8875
+ }
8876
+ function getIconFromAttribute(option, iconAttribute) {
8877
+ const iconValue = option[iconAttribute];
8878
+ if (!iconValue || typeof iconValue !== 'string') {
8879
+ return undefined;
8880
+ }
8881
+ // Process through getResourceUrl to handle both URLs and resourceIds
8882
+ return getResourceUrl(iconValue);
8883
+ }
8884
+
8423
8885
  const getFilterComponent = (filterType) => {
8424
8886
  switch (filterType) {
8425
8887
  case "checkbox":
@@ -8432,6 +8894,8 @@ const getFilterComponent = (filterType) => {
8432
8894
  return RangeDateFilter;
8433
8895
  case "text":
8434
8896
  return TextFilter;
8897
+ case "chips":
8898
+ return ChipsFilter;
8435
8899
  case "dropdown":
8436
8900
  default:
8437
8901
  return DropdownFilter;
@@ -8617,7 +9081,9 @@ const getRenderElement = ({ t, config, elementConfig, attributes = [], layerInfo
8617
9081
  return formatElementValue({ t, value, elementConfig: element, attributes, wrap });
8618
9082
  };
8619
9083
 
8620
- const getResourceUrl = (url) => url ? (url.startsWith("http") ? url : `/sp/resources/file/${url}`) : "";
9084
+ const getResourceUrl = (url) => {
9085
+ return url ? (url.startsWith("http") ? url : `/sp/resources/file/${url}`) : "";
9086
+ };
8621
9087
 
8622
9088
  const getSlideshowImages = ({ element, attribute, }) => {
8623
9089
  const { defaultValue, options } = element;
@@ -9618,7 +10084,7 @@ const ContainerChildren = React.memo(({ items, isColumn, isMain, renderElement }
9618
10084
  index,
9619
10085
  wrap: isColumn || isMain,
9620
10086
  });
9621
- return isMain ? (jsxRuntime.jsx(ContainerWrapper, { id: item.id, "data-templatename": item.templateName, children: jsxRuntime.jsx(DashboardWrapper, { children: render }) }, index)) : (jsxRuntime.jsx(InnerContainerWrapper$1, { id: item.id, children: render }, index));
10087
+ return isMain ? (jsxRuntime.jsx(ContainerWrapper, { id: item.id, "data-templatename": item.templateName, children: jsxRuntime.jsx(DashboardWrapper, { children: render }) }, index)) : (jsxRuntime.jsx(React.Fragment, { children: render }, index));
9622
10088
  }) }));
9623
10089
  });
9624
10090
 
@@ -10169,6 +10635,7 @@ exports.ElementIcon = ElementIcon;
10169
10635
  exports.ElementImage = ElementImage;
10170
10636
  exports.ElementLegend = ElementLegend;
10171
10637
  exports.ElementLink = ElementLink;
10638
+ exports.ElementMarkdown = ElementMarkdown;
10172
10639
  exports.ElementSlideshow = ElementSlideshow;
10173
10640
  exports.ElementSvg = ElementSvg;
10174
10641
  exports.ElementTooltip = ElementTooltip;
@@ -10200,7 +10667,6 @@ exports.HeaderTitleContainer = HeaderTitleContainer;
10200
10667
  exports.HiddenTitleItems = HiddenTitleItems;
10201
10668
  exports.IconContainer = IconContainer;
10202
10669
  exports.ImageContainer = ImageContainer;
10203
- exports.InnerContainerWrapper = InnerContainerWrapper$1;
10204
10670
  exports.LEFT_PANEL_HEADER_HEIGHT = LEFT_PANEL_HEADER_HEIGHT;
10205
10671
  exports.Layer = Layer;
10206
10672
  exports.LayerDescription = LayerDescription;
@@ -10251,7 +10717,6 @@ exports.TitleContainer = TitleContainer;
10251
10717
  exports.TopContainer = TopContainer;
10252
10718
  exports.TopContainerButtons = TopContainerButtons;
10253
10719
  exports.TwoColumnContainer = TwoColumnContainer;
10254
- exports.TwoColumnsInnerContainer = TwoColumnsInnerContainer;
10255
10720
  exports.addDataSource = addDataSource;
10256
10721
  exports.addDataSources = addDataSources;
10257
10722
  exports.applyFiltersToCondition = applyFiltersToCondition;