@evergis/react 4.0.101 → 4.0.103
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/components/Dashboard/componentTypes.d.ts +20 -14
- package/dist/components/Dashboard/components/Chart/FillContext.d.ts +15 -0
- package/dist/components/Dashboard/components/Chart/styled.d.ts +1 -0
- package/dist/components/Dashboard/components/StackBar/index.d.ts +2 -0
- package/dist/components/Dashboard/components/StackBar/styled.d.ts +4 -1
- package/dist/components/Dashboard/containers/EditContainer/styled.d.ts +2 -0
- package/dist/components/Dashboard/containers/FiltersContainer/styled.d.ts +2 -0
- package/dist/components/Dashboard/containers/styled.d.ts +4 -1
- package/dist/components/Dashboard/hooks/index.d.ts +1 -1
- package/dist/components/Dashboard/hooks/useResizeBox.d.ts +17 -0
- package/dist/components/Dashboard/types.d.ts +17 -2
- package/dist/components/Dashboard/utils/getWrapperSizeStyle.d.ts +7 -2
- package/dist/index.js +155 -43
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +154 -43
- package/dist/react.esm.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/Dashboard/components/Chart/ChartFillContext.d.ts +0 -8
- package/dist/components/Dashboard/hooks/useResizeWidth.d.ts +0 -12
package/dist/index.js
CHANGED
|
@@ -102,7 +102,30 @@ const ChartWrapperContainer = styled.div.withConfig({ displayName: "ChartWrapper
|
|
|
102
102
|
position: relative;
|
|
103
103
|
width: 100%;
|
|
104
104
|
`;
|
|
105
|
-
|
|
105
|
+
/*
|
|
106
|
+
* fill-режим: обёртка забирает всю доступную ячейку (её высоту задаёт флекс-цепочка, а не контент графика),
|
|
107
|
+
* на неё вешается ref для ResizeObserver — меряем обе оси без цикла. Плоский div (не Flex uilib), как соседний
|
|
108
|
+
* ChartWrapperContainer, чтобы ref гарантированно дошёл до DOM-узла. Тело графика центрируется внутри.
|
|
109
|
+
*/
|
|
110
|
+
const ChartFillMeasure = styled.div.withConfig({ displayName: "ChartFillMeasure", componentId: "sc-1r4oerb" }) `
|
|
111
|
+
position: relative;
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: center;
|
|
114
|
+
justify-content: center;
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: 100%;
|
|
117
|
+
min-width: 0;
|
|
118
|
+
min-height: 0;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
|
|
121
|
+
/* SVG по умолчанию inline, поэтому под ним остаётся зазор базовой линии (~4px при line-height
|
|
122
|
+
18.4px): вне fill его скрывал запас высоты, а тело, точно заполнившее ячейку, из-за него
|
|
123
|
+
вылезает за нижнюю границу. Блочный SVG зазора не даёт. */
|
|
124
|
+
svg {
|
|
125
|
+
display: block;
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
const Tooltip = styled.div.withConfig({ displayName: "Tooltip", componentId: "sc-1va8cy3" }) `
|
|
106
129
|
position: relative;
|
|
107
130
|
border-radius: 0.25rem;
|
|
108
131
|
background-color: rgba(28, 33, 48);
|
|
@@ -195,7 +218,7 @@ const LineChartStyles = styled.createGlobalStyle `
|
|
|
195
218
|
fill: ${({ theme: { palette } }) => palette.textDisabled};
|
|
196
219
|
}
|
|
197
220
|
`;
|
|
198
|
-
const StyledBarChart = styled(charts.BarChart).withConfig({ displayName: "StyledBarChart", componentId: "sc-
|
|
221
|
+
const StyledBarChart = styled(charts.BarChart).withConfig({ displayName: "StyledBarChart", componentId: "sc-1l1kx80" }) `
|
|
199
222
|
.domain {
|
|
200
223
|
display: none;
|
|
201
224
|
}
|
|
@@ -3383,6 +3406,8 @@ const ALIGNMENTS = ["left", "center", "right"];
|
|
|
3383
3406
|
const ALIGN_ITEMS = ["flex-start", "center", "flex-end", "stretch", "baseline"];
|
|
3384
3407
|
/** Масштабирование изображения внутри своего бокса (CSS `object-fit`). */
|
|
3385
3408
|
const OBJECT_FITS = ["cover", "contain", "fill", "none", "scale-down"];
|
|
3409
|
+
/** Поведение контента, выходящего за бокс контейнера (CSS `overflow`). */
|
|
3410
|
+
const OVERFLOWS = ["visible", "hidden", "scroll", "auto"];
|
|
3386
3411
|
/** Режим отображения коллекций. */
|
|
3387
3412
|
const VIEW_MODES = ["grid", "list"];
|
|
3388
3413
|
exports.ContainerTemplate = void 0;
|
|
@@ -3497,6 +3522,13 @@ const BASE_CONTAINER_STYLE = {
|
|
|
3497
3522
|
const StackBarContainer = styled(uilibGl.Flex).withConfig({ displayName: "StackBarContainer", componentId: "sc-stc97k" }) `
|
|
3498
3523
|
flex-wrap: nowrap;
|
|
3499
3524
|
width: 100%;
|
|
3525
|
+
|
|
3526
|
+
${({ $fill }) => $fill &&
|
|
3527
|
+
styled.css `
|
|
3528
|
+
/* fill: полоса забирает остаток высоты обёртки (вся ячейка минус шапка с итогом). */
|
|
3529
|
+
flex: 1 1 auto;
|
|
3530
|
+
min-height: 0;
|
|
3531
|
+
`}
|
|
3500
3532
|
`;
|
|
3501
3533
|
const StackBarHeader = styled(uilibGl.Flex).withConfig({ displayName: "StackBarHeader", componentId: "sc-8mc354" }) `
|
|
3502
3534
|
justify-content: space-between;
|
|
@@ -3506,7 +3538,8 @@ const StackBarHeader = styled(uilibGl.Flex).withConfig({ displayName: "StackBarH
|
|
|
3506
3538
|
const StackBarSection = styled.div.withConfig({ displayName: "StackBarSection", componentId: "sc-i3gdu" }) `
|
|
3507
3539
|
cursor: ${({ onClick }) => (onClick ? "pointer" : "default")};
|
|
3508
3540
|
width: ${({ $width }) => $width}%;
|
|
3509
|
-
|
|
3541
|
+
/* В fill толщину полосы задаёт растянутый контейнер, а не options.height элемента chart. */
|
|
3542
|
+
height: ${({ $fill, $height }) => ($fill ? "100%" : $height ? `${$height}px` : "0.5rem")};
|
|
3510
3543
|
margin: 0 0.5px;
|
|
3511
3544
|
background-color: ${({ $color }) => $color};
|
|
3512
3545
|
opacity: ${({ hasAnyFilter, isFiltered }) => (isFiltered ? 1 : hasAnyFilter ? FILTERED_VALUE_OPACITY / 100 : 1)};
|
|
@@ -7632,30 +7665,33 @@ const useRenderElement = (type = exports.WidgetType.Dashboard, elementConfig) =>
|
|
|
7632
7665
|
]);
|
|
7633
7666
|
};
|
|
7634
7667
|
|
|
7668
|
+
/** Пустой бокс на отключённом пути — стабильная ссылка, чтобы не плодить ре-рендеры. */
|
|
7669
|
+
const EMPTY_BOX = {};
|
|
7635
7670
|
/**
|
|
7636
|
-
* Измеряет
|
|
7671
|
+
* Измеряет фактические ширину и высоту DOM-элемента и обновляет их на любой ресайз (ResizeObserver).
|
|
7637
7672
|
*
|
|
7638
|
-
* Возвращает `[ref,
|
|
7639
|
-
* не измерен. Используется для «резинового» графика: d3-графикам
|
|
7640
|
-
*
|
|
7673
|
+
* Возвращает `[ref, box]`, где `box` — `{ width, height }` в пикселях (content-box) либо пустой объект,
|
|
7674
|
+
* пока элемент ещё не измерен. Используется для «резинового» графика: d3-графикам нужны конкретные
|
|
7675
|
+
* пиксельные размеры, а не CSS `100%`, а для вписывания (fit) нужны обе оси.
|
|
7641
7676
|
*
|
|
7642
7677
|
* `enabled: false` полностью отключает наблюдение — обычные (не fill) графики не измеряются
|
|
7643
7678
|
* и не вызывают лишних ре-рендеров.
|
|
7644
7679
|
*/
|
|
7645
|
-
const
|
|
7680
|
+
const useResizeBox = (enabled) => {
|
|
7646
7681
|
const ref = React.useRef(null);
|
|
7647
|
-
const [
|
|
7682
|
+
const [box, setBox] = React.useState(EMPTY_BOX);
|
|
7648
7683
|
React.useEffect(() => {
|
|
7649
7684
|
const node = ref.current;
|
|
7650
7685
|
if (!enabled || !node)
|
|
7651
7686
|
return;
|
|
7652
7687
|
const observer = new ResizeObserver(([entry]) => {
|
|
7653
|
-
|
|
7688
|
+
const { width, height } = entry.contentRect;
|
|
7689
|
+
setBox({ width, height });
|
|
7654
7690
|
});
|
|
7655
7691
|
observer.observe(node);
|
|
7656
7692
|
return () => observer.disconnect();
|
|
7657
7693
|
}, [enabled]);
|
|
7658
|
-
return [ref, enabled ?
|
|
7694
|
+
return [ref, enabled ? box : EMPTY_BOX];
|
|
7659
7695
|
};
|
|
7660
7696
|
|
|
7661
7697
|
const useShownOtherItems = (options) => {
|
|
@@ -7701,13 +7737,13 @@ const useUpdateDataSource = ({ dataSource, config, filters, attributes, layerPar
|
|
|
7701
7737
|
*/
|
|
7702
7738
|
const useWrapperSize = ({ elementConfig, defaults }) => {
|
|
7703
7739
|
const { id, style, templateName, options } = elementConfig || {};
|
|
7704
|
-
const { width, height } = options || {};
|
|
7740
|
+
const { width, height, overflow } = options || {};
|
|
7705
7741
|
return React.useMemo(() => ({
|
|
7706
7742
|
id,
|
|
7707
7743
|
"data-templatename": templateName,
|
|
7708
7744
|
style,
|
|
7709
|
-
$sizeCss: getWrapperSizeStyle({ style, width, height, defaults, defaultWidth: FILL_SIZE }),
|
|
7710
|
-
}), [id, templateName, style, width, height, defaults]);
|
|
7745
|
+
$sizeCss: getWrapperSizeStyle({ style, width, height, overflow, defaults, defaultWidth: FILL_SIZE }),
|
|
7746
|
+
}), [id, templateName, style, width, height, overflow, defaults]);
|
|
7711
7747
|
};
|
|
7712
7748
|
|
|
7713
7749
|
const ContainersGroupContainer = React.memo(({ elementConfig, type, renderElement }) => {
|
|
@@ -7777,6 +7813,19 @@ const ContainerChart = styled(uilibGl.Flex).withConfig({ displayName: "Container
|
|
|
7777
7813
|
justify-content: center;
|
|
7778
7814
|
width: 100%;
|
|
7779
7815
|
}
|
|
7816
|
+
|
|
7817
|
+
/* fill: слот забирает остаток высоты ячейки (под слотами title/alias/legend) и центрирует тело графика. */
|
|
7818
|
+
${({ $fill }) => $fill &&
|
|
7819
|
+
styled.css `
|
|
7820
|
+
flex: 1 1 auto;
|
|
7821
|
+
min-height: 0;
|
|
7822
|
+
align-items: center;
|
|
7823
|
+
justify-content: center;
|
|
7824
|
+
|
|
7825
|
+
> * {
|
|
7826
|
+
height: 100%;
|
|
7827
|
+
}
|
|
7828
|
+
`}
|
|
7780
7829
|
`;
|
|
7781
7830
|
const ContainerLegend = styled(uilibGl.Flex).withConfig({ displayName: "ContainerLegend", componentId: "sc-z1n1s8" }) ``;
|
|
7782
7831
|
const ContainerUnits = styled.div.withConfig({ displayName: "ContainerUnits", componentId: "sc-1vurgy9" }) `
|
|
@@ -7792,6 +7841,13 @@ const ContainerValue = styled(uilibGl.Flex).withConfig({ displayName: "Container
|
|
|
7792
7841
|
font-size: ${({ big }) => (big ? 1.5 : 1)}rem;
|
|
7793
7842
|
color: ${({ fontColor, theme: { palette } }) => fontColor || palette.textPrimary};
|
|
7794
7843
|
|
|
7844
|
+
/* fill: строка со слотом chart+legend забирает остаток высоты Container'а (гейт — только у Chart-контейнера). */
|
|
7845
|
+
${({ $fill }) => $fill &&
|
|
7846
|
+
styled.css `
|
|
7847
|
+
flex: 1 1 auto;
|
|
7848
|
+
min-height: 0;
|
|
7849
|
+
`}
|
|
7850
|
+
|
|
7795
7851
|
> * {
|
|
7796
7852
|
width: ${({ column }) => (column ? "100%" : "auto")};
|
|
7797
7853
|
}
|
|
@@ -7898,15 +7954,16 @@ const useRenderContainer = ({ elementConfig, type, renderElement, renderBody, })
|
|
|
7898
7954
|
};
|
|
7899
7955
|
|
|
7900
7956
|
const OneColumnContainer = React.memo(({ type, elementConfig, renderElement }) => {
|
|
7901
|
-
const { width, height } = elementConfig?.options || {};
|
|
7957
|
+
const { width, height, overflow } = elementConfig?.options || {};
|
|
7902
7958
|
const templateName = elementConfig?.templateName;
|
|
7903
7959
|
const renderBody = React.useCallback(({ id, value, style, hasUnits, render }) => (jsxRuntime.jsxs(Container, { id: id, isColumn: true, "data-templatename": templateName, style: style, "$sizeCss": getWrapperSizeStyle({
|
|
7904
7960
|
style,
|
|
7905
7961
|
width,
|
|
7906
7962
|
height,
|
|
7963
|
+
overflow,
|
|
7907
7964
|
defaults: BASE_CONTAINER_STYLE,
|
|
7908
7965
|
defaultWidth: FILL_SIZE,
|
|
7909
|
-
}), children: [jsxRuntime.jsxs(ContainerAlias, { hasBottomMargin: true, children: [render({ id: "alias" }), render({ id: "tooltip" }), render({ id: "modal" })] }), jsxRuntime.jsxs(ContainerValue, { children: [value, hasUnits && (jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) }))] })] })), [width, height, templateName]);
|
|
7966
|
+
}), children: [jsxRuntime.jsxs(ContainerAlias, { hasBottomMargin: true, children: [render({ id: "alias" }), render({ id: "tooltip" }), render({ id: "modal" })] }), jsxRuntime.jsxs(ContainerValue, { children: [value, hasUnits && (jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) }))] })] })), [width, height, overflow, templateName]);
|
|
7910
7967
|
const { renderContainer, attributesToRender } = useRenderContainer({
|
|
7911
7968
|
type,
|
|
7912
7969
|
elementConfig,
|
|
@@ -7917,9 +7974,9 @@ const OneColumnContainer = React.memo(({ type, elementConfig, renderElement }) =
|
|
|
7917
7974
|
});
|
|
7918
7975
|
|
|
7919
7976
|
const TwoColumnContainer = React.memo(({ elementConfig, type, renderElement }) => {
|
|
7920
|
-
const { width, height } = elementConfig?.options || {};
|
|
7977
|
+
const { width, height, overflow } = elementConfig?.options || {};
|
|
7921
7978
|
const templateName = elementConfig?.templateName;
|
|
7922
|
-
const renderBody = React.useCallback(({ id, value, style, hasIcon, hasUnits, render }) => (jsxRuntime.jsxs(TwoColumnContainerWrapper, { id: id, "data-templatename": templateName, style: style, "$sizeCss": getWrapperSizeStyle({ style, width, height, defaultWidth: FILL_SIZE }), children: [jsxRuntime.jsxs(ContainerAlias, { children: [hasIcon && (jsxRuntime.jsx(ContainerAliasIcon, { children: render({ id: "icon" }) })), render({ id: "alias" }), render({ id: "tooltip" }), render({ id: "modal" })] }), jsxRuntime.jsxs(ContainerValue, { big: true, children: [value, hasUnits && (jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) }))] })] })), [width, height, templateName]);
|
|
7979
|
+
const renderBody = React.useCallback(({ id, value, style, hasIcon, hasUnits, render }) => (jsxRuntime.jsxs(TwoColumnContainerWrapper, { id: id, "data-templatename": templateName, style: style, "$sizeCss": getWrapperSizeStyle({ style, width, height, overflow, defaultWidth: FILL_SIZE }), children: [jsxRuntime.jsxs(ContainerAlias, { children: [hasIcon && (jsxRuntime.jsx(ContainerAliasIcon, { children: render({ id: "icon" }) })), render({ id: "alias" }), render({ id: "tooltip" }), render({ id: "modal" })] }), jsxRuntime.jsxs(ContainerValue, { big: true, children: [value, hasUnits && (jsxRuntime.jsx(ContainerUnits, { children: render({ id: "units" }) }))] })] })), [width, height, overflow, templateName]);
|
|
7923
7980
|
const { renderContainer, attributesToRender } = useRenderContainer({
|
|
7924
7981
|
type,
|
|
7925
7982
|
elementConfig,
|
|
@@ -8301,6 +8358,15 @@ const BarChartContainer = styled.div.withConfig({ displayName: "BarChartContaine
|
|
|
8301
8358
|
const AnyChartWrapper = styled.div.withConfig({ displayName: "AnyChartWrapper", componentId: "sc-1txgly0" }) `
|
|
8302
8359
|
width: 100%;
|
|
8303
8360
|
height: ${({ height }) => height}px;
|
|
8361
|
+
|
|
8362
|
+
${({ $fill }) => $fill &&
|
|
8363
|
+
styled.css `
|
|
8364
|
+
/* fill: обёртке задана ВСЯ доступная высота ячейки, поэтому тело внутри забирает её остаток
|
|
8365
|
+
флексом (полоса stack тянется под строкой итога), а не вычисляется арифметикой. */
|
|
8366
|
+
display: flex;
|
|
8367
|
+
flex-direction: column;
|
|
8368
|
+
min-height: 0;
|
|
8369
|
+
`}
|
|
8304
8370
|
`;
|
|
8305
8371
|
const BarChartWrapper = styled(AnyChartWrapper).withConfig({ displayName: "BarChartWrapper", componentId: "sc-98mm1q" }) `
|
|
8306
8372
|
width: 100%;
|
|
@@ -8423,6 +8489,10 @@ const ChartContainerWrapper = styled(uilibGl.FlexSpan).withConfig({ displayName:
|
|
|
8423
8489
|
/* Заданная высота контейнера достаётся телу графика — за вычетом заголовка. */
|
|
8424
8490
|
${({ $sizeCss }) => !!$sizeCss?.height &&
|
|
8425
8491
|
styled.css `
|
|
8492
|
+
/* Раздача высоты требует, чтобы обёртка была flex-колонкой (FlexSpan сам по себе не flex),
|
|
8493
|
+
иначе Container с flex:1 1 auto не растянется на заданную высоту, а fill-график не впишется по высоте. */
|
|
8494
|
+
display: flex;
|
|
8495
|
+
|
|
8426
8496
|
> ${Container} {
|
|
8427
8497
|
flex: 1 1 auto;
|
|
8428
8498
|
min-height: 0;
|
|
@@ -8433,17 +8503,19 @@ const ChartContainerWrapper = styled(uilibGl.FlexSpan).withConfig({ displayName:
|
|
|
8433
8503
|
`;
|
|
8434
8504
|
|
|
8435
8505
|
/**
|
|
8436
|
-
*
|
|
8506
|
+
* Контекст вписывания графика (`options.fill` контейнера Chart).
|
|
8437
8507
|
*
|
|
8438
8508
|
* Компонент `Chart` рендерится через `renderElement({ id: "chart" })` и получает только дочерний
|
|
8439
8509
|
* узел `{ id: "chart" }` — опции контейнера до него не доходят. `ChartContainer` оборачивает
|
|
8440
|
-
* график в провайдер этого контекста, а `Chart` читает
|
|
8510
|
+
* график в провайдер этого контекста, а `Chart` читает значение через `useContext`.
|
|
8441
8511
|
*/
|
|
8442
|
-
const
|
|
8512
|
+
const FillContext = React.createContext({ fill: false, fitHeight: false });
|
|
8443
8513
|
|
|
8444
8514
|
const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderElement }) => {
|
|
8445
8515
|
const { options, children } = elementConfig || {};
|
|
8446
|
-
const { twoColumns, hideEmpty,
|
|
8516
|
+
const { twoColumns, hideEmpty, height } = options || {};
|
|
8517
|
+
const fill = options?.fill;
|
|
8518
|
+
const fillContextValue = React.useMemo(() => ({ fill: !!fill, fitHeight: !!fill && height != null }), [fill, height]);
|
|
8447
8519
|
const aliasElement = children.find(child => child.id === "alias");
|
|
8448
8520
|
const chartElement = children.find(child => child.id === "chart");
|
|
8449
8521
|
const legendElement = children.find(child => child.id === "legend");
|
|
@@ -8458,7 +8530,7 @@ const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderEleme
|
|
|
8458
8530
|
const hasItems = !!data[0]?.items?.length;
|
|
8459
8531
|
if (!loading && !hasItems && hideEmpty)
|
|
8460
8532
|
return null;
|
|
8461
|
-
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: "center", children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { children: jsxRuntime.jsx(
|
|
8533
|
+
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" })) })] }))] }));
|
|
8462
8534
|
});
|
|
8463
8535
|
|
|
8464
8536
|
const PagesContainer = React.memo(({ type = exports.WidgetType.Dashboard, noBorders }) => {
|
|
@@ -11465,6 +11537,8 @@ const tagTypography = (tag) => ({ $typography }) => {
|
|
|
11465
11537
|
${style.fontSize && `font-size: ${style.fontSize};`}
|
|
11466
11538
|
${style.lineHeight && `line-height: ${style.lineHeight};`}
|
|
11467
11539
|
${style.fontWeight != null && `font-weight: ${style.fontWeight};`}
|
|
11540
|
+
${style.marginTop && `margin-top: ${style.marginTop};`}
|
|
11541
|
+
${style.marginBottom && `margin-bottom: ${style.marginBottom};`}
|
|
11468
11542
|
`;
|
|
11469
11543
|
};
|
|
11470
11544
|
const MarkdownWrapper = styled.div.withConfig({ displayName: "MarkdownWrapper", componentId: "sc-1iv8z8a" }) `
|
|
@@ -12697,7 +12771,8 @@ const ChartLoading = ({ column }) => (jsxRuntime.jsx(uilibGl.Flex, { position: "
|
|
|
12697
12771
|
|
|
12698
12772
|
const ContainerLoading = () => (jsxRuntime.jsx(uilibGl.Flex, { alignContent: "center", justifyContent: "center", width: "100%", children: jsxRuntime.jsx(uilibGl.CircularProgress, { diameter: 1.5, mono: true }) }));
|
|
12699
12773
|
|
|
12700
|
-
// forwardRef
|
|
12774
|
+
// forwardRef сохранён для совместимости; в fill-режиме ResizeObserver меряет внешнюю обёртку
|
|
12775
|
+
// ChartFillMeasure (см. Chart/index.tsx), а не сам ChartWrapper.
|
|
12701
12776
|
const ChartWrapper = React.memo(React.forwardRef(({ width, height, column, loading, children }, ref) => {
|
|
12702
12777
|
return (jsxRuntime.jsxs(ChartWrapperContainer, { ref: ref, column: column, style: { width, height }, children: [loading && jsxRuntime.jsx(ChartLoading, { column: column }), jsxRuntime.jsx(uilibGl.Flex, { opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: children })] }));
|
|
12703
12778
|
}));
|
|
@@ -13853,13 +13928,17 @@ const omitKeys = (source, keys = []) => {
|
|
|
13853
13928
|
* конфликтующие внутренние дефолты обёртки, а контент лишается возможности её распирать
|
|
13854
13929
|
* (`min-width`/`min-height: 0`). Для fill-высоты добавляется `flex: 1 1 auto` — в колонке
|
|
13855
13930
|
* контейнер забирает остаток ячейки под заголовком, а не переполняет её на его высоту.
|
|
13931
|
+
*
|
|
13932
|
+
* `overflow` уходит в CSS как есть и ничем не подменяется: не задан — работает браузерный
|
|
13933
|
+
* `visible`, то есть контент крупнее бокса вытекает на соседние слоты.
|
|
13856
13934
|
*/
|
|
13857
|
-
const getWrapperSizeStyle = ({ style, width: widthOption, height, defaults, defaultWidth, }) => {
|
|
13935
|
+
const getWrapperSizeStyle = ({ style, width: widthOption, height, overflow, defaults, defaultWidth, }) => {
|
|
13858
13936
|
// Ширина по умолчанию (контейнеры передают FILL_SIZE): явный `options.width` её перекрывает.
|
|
13859
13937
|
const width = widthOption ?? defaultWidth;
|
|
13860
13938
|
const hasWidth = width != null;
|
|
13861
13939
|
const hasHeight = height != null;
|
|
13862
|
-
|
|
13940
|
+
const hasOverflow = overflow != null;
|
|
13941
|
+
if (!hasWidth && !hasHeight && !hasOverflow) {
|
|
13863
13942
|
return defaults;
|
|
13864
13943
|
}
|
|
13865
13944
|
const fillWidth = isFillSize(width);
|
|
@@ -13868,13 +13947,18 @@ const getWrapperSizeStyle = ({ style, width: widthOption, height, defaults, defa
|
|
|
13868
13947
|
...(fillWidth ? FILL_WIDTH_CONFLICTS : []),
|
|
13869
13948
|
...(fillHeight ? FILL_HEIGHT_CONFLICTS : []),
|
|
13870
13949
|
];
|
|
13871
|
-
const sizeKeys = [
|
|
13950
|
+
const sizeKeys = [
|
|
13951
|
+
...(hasWidth ? ["width"] : []),
|
|
13952
|
+
...(hasHeight ? ["height"] : []),
|
|
13953
|
+
...(hasOverflow ? ["overflow"] : []),
|
|
13954
|
+
];
|
|
13872
13955
|
return {
|
|
13873
13956
|
...omitKeys(defaults, conflicts),
|
|
13874
13957
|
// `options` перекрывают одноимённые поля `style` — приоритет тот же, что был у inline-варианта.
|
|
13875
13958
|
...omitKeys(style, sizeKeys),
|
|
13876
13959
|
...(hasWidth && { width, ...(fillWidth && { minWidth: 0 }) }),
|
|
13877
13960
|
...(hasHeight && { height, ...(fillHeight && { minHeight: 0, flex: "1 1 auto" }) }),
|
|
13961
|
+
...(hasOverflow && { overflow }),
|
|
13878
13962
|
};
|
|
13879
13963
|
};
|
|
13880
13964
|
|
|
@@ -14007,7 +14091,7 @@ const tooltipValueFromRelatedFeatures = (t, value, relatedAttributes, layerInfo)
|
|
|
14007
14091
|
return formatChartRelatedValue(t, value, layerInfo, relatedAttributes);
|
|
14008
14092
|
};
|
|
14009
14093
|
|
|
14010
|
-
const StackBar = ({ data, filterName, type, alias, options, renderElement, renderTooltip }) => {
|
|
14094
|
+
const StackBar = ({ data, filterName, type, alias, options, fill, renderElement, renderTooltip }) => {
|
|
14011
14095
|
const { height, showTotal, cornerRadius, groupTooltip } = options || {};
|
|
14012
14096
|
const { t } = useGlobalContext();
|
|
14013
14097
|
const { hasAnyFilter, isFiltered, onFilter } = useWidgetFilters(type, filterName, data?.[0]?.items);
|
|
@@ -14021,11 +14105,11 @@ const StackBar = ({ data, filterName, type, alias, options, renderElement, rende
|
|
|
14021
14105
|
const visibleItems = React.useMemo(() => items?.filter(({ value }) => Number(value) > 0), [items]);
|
|
14022
14106
|
const getWidth = React.useCallback(value => ((Number(value) / total) * 100).toFixed(2), [total]);
|
|
14023
14107
|
const renderGroupTooltip = React.useMemo(() => (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsx(ChartTooltipTable, { cellPadding: 0, cellSpacing: 0, children: visibleItems?.map(({ name, value, color }, index) => (jsxRuntime.jsxs("tr", { children: [jsxRuntime.jsx("td", { children: jsxRuntime.jsxs(ChartTooltip, { alignItems: "center", children: [jsxRuntime.jsx(ChartTooltipColor, { "$color": color }), jsxRuntime.jsx(ChartTooltipName, { children: name })] }) }), jsxRuntime.jsx("td", { children: formatValue(value) })] }, index))) }) })), [visibleItems, formatValue]);
|
|
14024
|
-
const renderItem = React.useCallback(({ name, value, color }, ref) => (jsxRuntime.jsx(StackBarSection, { ref: ref, "$width": getWidth(value), "$height": height, "$color": color, cornerRadius: cornerRadius, hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: filterName ? () => onFilter(name) : undefined })), [cornerRadius, filterName, getWidth, hasAnyFilter, height, isFiltered, onFilter]);
|
|
14108
|
+
const renderItem = React.useCallback(({ name, value, color }, ref) => (jsxRuntime.jsx(StackBarSection, { ref: ref, "$width": getWidth(value), "$height": height, "$fill": fill, "$color": color, cornerRadius: cornerRadius, hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: filterName ? () => onFilter(name) : undefined })), [cornerRadius, fill, filterName, getWidth, hasAnyFilter, height, isFiltered, onFilter]);
|
|
14025
14109
|
const renderItems = React.useMemo(() => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: visibleItems?.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: groupTooltip ? (renderItem(item)) : (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: renderTooltip([item]), children: ref => renderItem(item, ref) }) })) }, index))) })), [groupTooltip, visibleItems, renderItem, renderTooltip]);
|
|
14026
14110
|
if (!total)
|
|
14027
14111
|
return null;
|
|
14028
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(alias || showTotal) && (jsxRuntime.jsxs(StackBarHeader, { children: [jsxRuntime.jsx(StackBarAlias, { children: renderElement({ id: "alias" }) }), showTotal && (jsxRuntime.jsxs(StackBarTotal, { children: [jsxRuntime.jsx(StackBarValue, { children: formatValue(total) }), !!units && jsxRuntime.jsx(StackBarUnits, { children: units })] }))] })), groupTooltip ? (jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: renderGroupTooltip, children: ref => jsxRuntime.jsx(StackBarContainer, { ref: ref, children: renderItems }) })) : (jsxRuntime.jsx(StackBarContainer, { children: renderItems }))] }));
|
|
14112
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(alias || showTotal) && (jsxRuntime.jsxs(StackBarHeader, { children: [jsxRuntime.jsx(StackBarAlias, { children: renderElement({ id: "alias" }) }), showTotal && (jsxRuntime.jsxs(StackBarTotal, { children: [jsxRuntime.jsx(StackBarValue, { children: formatValue(total) }), !!units && jsxRuntime.jsx(StackBarUnits, { children: units })] }))] })), groupTooltip ? (jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: renderGroupTooltip, children: ref => (jsxRuntime.jsx(StackBarContainer, { ref: ref, "$fill": fill, children: renderItems })) })) : (jsxRuntime.jsx(StackBarContainer, { "$fill": fill, children: renderItems }))] }));
|
|
14029
14113
|
};
|
|
14030
14114
|
|
|
14031
14115
|
const Chart = React.memo(({ config, element, elementConfig, type, renderElement }) => {
|
|
@@ -14034,10 +14118,10 @@ const Chart = React.memo(({ config, element, elementConfig, type, renderElement
|
|
|
14034
14118
|
const primaryColor = palette.primary;
|
|
14035
14119
|
const { t } = useGlobalContext();
|
|
14036
14120
|
const { expandedContainers, attributes, dataSources } = useWidgetContext(type);
|
|
14037
|
-
//
|
|
14038
|
-
// т.к. d3-графики (и useChartChange для line) требуют
|
|
14039
|
-
const fill = React.useContext(
|
|
14040
|
-
const [chartRef, measuredWidth] =
|
|
14121
|
+
// fill контейнера: вписываем тело графика в контейнер. Размеры ячейки измеряем реально (ResizeObserver),
|
|
14122
|
+
// т.к. d3-графики (и useChartChange для line) требуют пиксельные числа, а не CSS "100%".
|
|
14123
|
+
const { fill, fitHeight } = React.useContext(FillContext);
|
|
14124
|
+
const [chartRef, { width: measuredWidth, height: measuredHeight }] = useResizeBox(fill);
|
|
14041
14125
|
const { id, options, children } = element || {};
|
|
14042
14126
|
const { column, markers: configMarkers, showLabels, showMarkers, showTotal, totalWord: configTotalWord, totalAttribute, expandable, expanded, chartType, relatedDataSources, defaultColor, dotSnapping, } = options || {};
|
|
14043
14127
|
const isLineChart = chartType === "line";
|
|
@@ -14073,11 +14157,19 @@ const Chart = React.memo(({ config, element, elementConfig, type, renderElement
|
|
|
14073
14157
|
const chartWidth = fill
|
|
14074
14158
|
? measuredWidth ?? DEFAULT_CHART_WIDTH
|
|
14075
14159
|
: toPxNumber(width) ?? DEFAULT_CHART_WIDTH;
|
|
14160
|
+
// Фит по высоте включается только при заданной высоте контейнера (fitHeight) и уже измеренной
|
|
14161
|
+
// ячейке; иначе — прежняя фикс. высота options.height. Флаг важен и ниже: он различает два
|
|
14162
|
+
// смысла chartHeight — «высота тела» (вне fill) и «вся доступная высота» (в fill).
|
|
14163
|
+
const fitsHeight = React.useMemo(() => !!(fill && fitHeight && measuredHeight), [fill, fitHeight, measuredHeight]);
|
|
14164
|
+
// fill по высоте: тянем тело графика на измеренную доступную высоту ячейки (content-box минус слоты).
|
|
14165
|
+
const chartHeight = React.useMemo(() => (fitsHeight && measuredHeight ? measuredHeight : height), [fitsHeight, measuredHeight, height]);
|
|
14166
|
+
// Круглый график вписываем по короткой стороне (object-fit: contain), центрируя в ячейке.
|
|
14167
|
+
const pieSide = React.useMemo(() => (fitsHeight && measuredHeight ? Math.min(chartWidth, measuredHeight) : chartWidth), [fitsHeight, measuredHeight, chartWidth]);
|
|
14076
14168
|
const [customize] = useChartChange({
|
|
14077
14169
|
dataSources: config.dataSources,
|
|
14078
14170
|
chartId: elementConfig?.id,
|
|
14079
14171
|
width: chartWidth,
|
|
14080
|
-
height,
|
|
14172
|
+
height: chartHeight,
|
|
14081
14173
|
fontColor,
|
|
14082
14174
|
relatedAttributes,
|
|
14083
14175
|
defaultColor: primaryColor,
|
|
@@ -14177,26 +14269,37 @@ const Chart = React.memo(({ config, element, elementConfig, type, renderElement
|
|
|
14177
14269
|
.flat()
|
|
14178
14270
|
.map(({ values }) => values)
|
|
14179
14271
|
.flat();
|
|
14180
|
-
return (jsxRuntime.jsxs(AnyChartWrapper, { height:
|
|
14272
|
+
return (jsxRuntime.jsxs(AnyChartWrapper, { height: chartHeight, children: [jsxRuntime.jsx(LineChartStyles, {}), jsxRuntime.jsx(charts.LineChart, { data: lineChartData, labels: labels, markers: markers, width: chartWidth, height: chartHeight, xAxisPadding: 15, yAxisPadding: 0, min: Math.min(...chartValues), customYAxisSelection: yAxis => {
|
|
14181
14273
|
if (isHidedY) {
|
|
14182
14274
|
yAxis.remove();
|
|
14183
14275
|
}
|
|
14184
14276
|
}, customYAxis: yAxis => yAxis.ticks(4), renderTooltip: renderLineChartTooltip, customize: customize, dotSnapping: dotSnapping, dynamicTooltipEnable: true, stackedTooltip: true, tooltipClassName: "dashboardLineChartTooltip", drawGridX: !isHidedY, margin: margin })] }));
|
|
14185
14277
|
}
|
|
14186
14278
|
if (isStackBar) {
|
|
14187
|
-
|
|
14188
|
-
|
|
14279
|
+
// Вне fill chartHeight — высота самой полосы, и обёртка честно становится выше на строку
|
|
14280
|
+
// итога. В fill chartHeight — уже ВСЯ доступная высота ячейки: обёртка занимает её целиком,
|
|
14281
|
+
// а полоса забирает остаток под шапкой флексом ($fill), поэтому прибавлять/вычитать
|
|
14282
|
+
// STACK_BAR_TOTAL_HEIGHT не нужно — иначе тело вылезло бы за нижнюю границу.
|
|
14283
|
+
const stackBarHeight = showTotal && !fitsHeight ? chartHeight + STACK_BAR_TOTAL_HEIGHT : chartHeight;
|
|
14284
|
+
return (jsxRuntime.jsx(AnyChartWrapper, { height: stackBarHeight, "$fill": fitsHeight, children: jsxRuntime.jsx(StackBar, { data: data, filterName: filterName, type: type, alias: elementConfig?.children?.find(child => child.id === "alias"), options: options, fill: fitsHeight, renderTooltip: renderPieChartTooltip, renderElement: renderElement }) }));
|
|
14189
14285
|
}
|
|
14190
14286
|
if (isPieChart) {
|
|
14191
|
-
return (jsxRuntime.jsx(AnyChartWrapper, { height: height, children: jsxRuntime.jsx(charts.PieChart, { data: (data[0]?.items
|
|
14287
|
+
return (jsxRuntime.jsx(AnyChartWrapper, { height: fill ? pieSide : height, children: jsxRuntime.jsx(charts.PieChart, { data: (data[0]?.items
|
|
14192
14288
|
?.filter(({ value }) => !isEmptyValue(value))
|
|
14193
14289
|
?.map(item => ({
|
|
14194
14290
|
...item,
|
|
14195
14291
|
color: formatFilterColor(item.name, item.color, defaultColor),
|
|
14196
|
-
})) || []), width:
|
|
14292
|
+
})) || []), width: pieSide, height: pieSide, padAngle: angle, outerRadius: radius, cornerRadius: cornerRadius, renderTooltip: renderPieChartTooltip, withTooltip: true, onClick: filterName ? item => onFilter(item.name) : undefined, children: showTotal && (jsxRuntime.jsx(PieChartCenter, { children: totalWord || roundTotalSum(+totalSum) })) }) }));
|
|
14197
14293
|
}
|
|
14198
14294
|
const barChartData = getDataFromFilterItems(data[0]?.items);
|
|
14199
|
-
|
|
14295
|
+
// Тот же случай, что у stack: обёртка выше тела на подписи оси X (margin.bottom). В fill
|
|
14296
|
+
// chartHeight — вся доступная высота, поэтому подписи вычитаем из неё, а не прибавляем.
|
|
14297
|
+
// BAR_CHART_FOOTER_MARGIN — это внешний margin-bottom самой BarChartWrapper: в её height он
|
|
14298
|
+
// не входит, но место в ячейке занимает, поэтому его тоже вычитаем.
|
|
14299
|
+
const barBodyHeight = fitsHeight
|
|
14300
|
+
? chartHeight - margin.bottom - BAR_CHART_FOOTER_MARGIN
|
|
14301
|
+
: chartHeight;
|
|
14302
|
+
return (jsxRuntime.jsx(BarChartWrapper, { height: barBodyHeight + margin.bottom, children: jsxRuntime.jsx(BarChartContainer, { children: jsxRuntime.jsx(StyledBarChart, { data: barChartData, colors: getColorsFromFilterItems(data[0]?.items, defaultColor, formatFilterColor), minValue: getMinValueFromFilterItems(data[0]?.items), markers: markers, width: chartWidth, height: barBodyHeight, barWidth: barWidth, barPadding: padding, customYAxisLeft: customYAxisLeft, customXAxisBottom: xAxisBottom => customXAxisBottom(xAxisBottom, barChartData), customYAxis: axis => !showLabels && axis.remove(), customBars: ({ bars }) => {
|
|
14200
14303
|
bars.attr("rx", radius);
|
|
14201
14304
|
bars.attr("ry", radius);
|
|
14202
14305
|
}, margin: margin, xAxisPadding: 0, yAxisPadding: 0, formatTooltipValue: formatTooltipValue, formatTooltipName: formatTooltipName, hideTooltipGroupName: true, dynamicTooltipEnable: true, isBarTooltip: true, onBarClick: filterName ? item => onFilter(item.name) : undefined }) }) }));
|
|
@@ -14214,6 +14317,10 @@ const Chart = React.memo(({ config, element, elementConfig, type, renderElement
|
|
|
14214
14317
|
defaultColor,
|
|
14215
14318
|
formatFilterColor,
|
|
14216
14319
|
chartWidth,
|
|
14320
|
+
chartHeight,
|
|
14321
|
+
fitsHeight,
|
|
14322
|
+
pieSide,
|
|
14323
|
+
fill,
|
|
14217
14324
|
barWidth,
|
|
14218
14325
|
showLabels,
|
|
14219
14326
|
padding,
|
|
@@ -14241,7 +14348,11 @@ const Chart = React.memo(({ config, element, elementConfig, type, renderElement
|
|
|
14241
14348
|
]);
|
|
14242
14349
|
if (!isVisibleContainer(id, expandable, expanded, expandedContainers))
|
|
14243
14350
|
return null;
|
|
14244
|
-
|
|
14351
|
+
const chartBody = (jsxRuntime.jsx(ChartWrapper, { width: isPieChart && fill ? pieSide : width, height: isStackBar ? "auto" : isPieChart ? (fill ? pieSide : width) : chartHeight, column: column, loading: loading, children: renderChart }));
|
|
14352
|
+
if (!fill)
|
|
14353
|
+
return chartBody;
|
|
14354
|
+
// fill: тело центрируется в измеряемой обёртке, ref которой питает ResizeObserver обеими осями.
|
|
14355
|
+
return jsxRuntime.jsx(ChartFillMeasure, { ref: chartRef, children: chartBody });
|
|
14245
14356
|
});
|
|
14246
14357
|
|
|
14247
14358
|
const ChartLegend = ({ data, chartElement, fontSize, type, twoColumns, loading }) => {
|
|
@@ -15097,6 +15208,7 @@ exports.NO_CONTENT_VALUE = NO_CONTENT_VALUE;
|
|
|
15097
15208
|
exports.NUMERIC_ATTRIBUTE_TYPES = NUMERIC_ATTRIBUTE_TYPES;
|
|
15098
15209
|
exports.NoLiveSnapshotContainer = NoLiveSnapshotContainer;
|
|
15099
15210
|
exports.OBJECT_FITS = OBJECT_FITS;
|
|
15211
|
+
exports.OVERFLOWS = OVERFLOWS;
|
|
15100
15212
|
exports.OneColumnContainer = OneColumnContainer;
|
|
15101
15213
|
exports.POLL_SUBTASK_INTERVAL_MS = POLL_SUBTASK_INTERVAL_MS;
|
|
15102
15214
|
exports.POLL_SUBTASK_TIMEOUT_MS = POLL_SUBTASK_TIMEOUT_MS;
|
|
@@ -15298,7 +15410,7 @@ exports.useRedrawLayer = useRedrawLayer;
|
|
|
15298
15410
|
exports.useRelatedDataSourceAttributes = useRelatedDataSourceAttributes;
|
|
15299
15411
|
exports.useRemoteTask = useRemoteTask;
|
|
15300
15412
|
exports.useRenderElement = useRenderElement;
|
|
15301
|
-
exports.
|
|
15413
|
+
exports.useResizeBox = useResizeBox;
|
|
15302
15414
|
exports.useSavePrototypeBuilder = useSavePrototypeBuilder;
|
|
15303
15415
|
exports.useServerNotificationsContext = useServerNotificationsContext;
|
|
15304
15416
|
exports.useShownOtherItems = useShownOtherItems;
|