@evergis/react 4.0.153 → 4.0.155
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 +3 -3
- package/dist/components/Dashboard/components/Chart/ChartPlotContext.d.ts +24 -0
- package/dist/components/Dashboard/components/Chart/components/AxisTitles.d.ts +23 -0
- package/dist/components/Dashboard/components/Chart/styled.d.ts +33 -0
- package/dist/components/Dashboard/components/ChartLegend/index.d.ts +1 -0
- package/dist/components/Dashboard/components/ChartLegend/styled.d.ts +1 -0
- package/dist/components/Dashboard/constants.d.ts +37 -1
- package/dist/components/Dashboard/containers/AttachmentContainer/constants.d.ts +1 -0
- package/dist/components/Dashboard/containers/ChartContainer/types.d.ts +3 -1
- package/dist/components/Dashboard/containers/FiltersContainer/constants.d.ts +1 -0
- package/dist/components/Dashboard/containers/styled.d.ts +38 -0
- package/dist/components/Dashboard/elements/ElementIcon/components/AttachmentIcon/index.d.ts +7 -0
- package/dist/components/Dashboard/elements/ElementIcon/components/AttachmentIcon/styled.d.ts +3 -0
- package/dist/components/Dashboard/elements/ElementIcon/components/AttachmentIcon/types.d.ts +15 -0
- package/dist/components/Dashboard/elements/ElementIcon/constants.d.ts +2 -0
- package/dist/components/Dashboard/elements/ElementIcon/utils/getAttachmentIcon.d.ts +7 -0
- package/dist/components/Dashboard/hooks/index.d.ts +3 -0
- package/dist/components/Dashboard/hooks/useChartAxisAttributes.d.ts +19 -0
- package/dist/components/Dashboard/hooks/useChartAxisTickFormat.d.ts +18 -0
- package/dist/components/Dashboard/hooks/useChartAxisTitles.d.ts +32 -0
- package/dist/components/Dashboard/types.d.ts +59 -1
- package/dist/components/Dashboard/utils/chartAxis.d.ts +29 -0
- package/dist/components/Dashboard/utils/index.d.ts +1 -0
- package/dist/index.js +679 -89
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +662 -90
- package/dist/react.esm.js.map +1 -1
- package/package.json +3 -3
package/dist/react.esm.js
CHANGED
|
@@ -3356,6 +3356,46 @@ const MAX_CHART_WIDTH = 300;
|
|
|
3356
3356
|
const DEFAULT_CHART_ANGLE = 4;
|
|
3357
3357
|
const DEFAULT_CHART_HEIGHT = 90;
|
|
3358
3358
|
const STACK_BAR_TOTAL_HEIGHT = 20;
|
|
3359
|
+
/** Высота строки текста подписи оси (шрифт 10px) — по макету. */
|
|
3360
|
+
const AXIS_TITLE_LINE_HEIGHT = 12;
|
|
3361
|
+
/** Зазор между подписью оси и значениями шкалы — по макету. */
|
|
3362
|
+
const AXIS_TITLE_GAP = 4;
|
|
3363
|
+
/**
|
|
3364
|
+
* Поле SVG графика под выступ крайних делений шкалы значений.
|
|
3365
|
+
*
|
|
3366
|
+
* d3 центрирует подпись деления на его линии (`dy: 0.32em`), поэтому у крайнего деления половина подписи
|
|
3367
|
+
* выходит за поле графика. Если поле вплотную к краю SVG, половина оказывается за SVG, и её срезает
|
|
3368
|
+
* обёртка: у линейного графика в fill — `ChartFillMeasure` (`overflow: hidden`), у барчарта всегда —
|
|
3369
|
+
* `BarChartContainer` (`overflow-x: hidden`, отчего и по вертикали содержимое не `visible`).
|
|
3370
|
+
*/
|
|
3371
|
+
const Y_AXIS_LABEL_OVERHANG = 6;
|
|
3372
|
+
/** Зазор от строки горизонтальных подписей осей до верхней линии сетки — по макету. */
|
|
3373
|
+
const AXIS_TITLE_TOP_GRID_GAP = 9;
|
|
3374
|
+
/** Число делений шкал линейного графика; у левой и правой шкал оно общее, чтобы совпадала сетка. */
|
|
3375
|
+
const LINE_CHART_Y_TICKS = 4;
|
|
3376
|
+
/**
|
|
3377
|
+
* Высота строки горизонтальных подписей осей (`axis.titlePosition: "top"`). Вместе с верхним полем SVG
|
|
3378
|
+
* (Y_AXIS_LABEL_OVERHANG) даёт строку текста и 9px до верхней линии сетки: деление центрировано на
|
|
3379
|
+
* линии и выступает над ней на ~5px, так что между подписью и значением шкалы остаются те же 4px,
|
|
3380
|
+
* что и у вертикальной подписи.
|
|
3381
|
+
*/
|
|
3382
|
+
const AXIS_TITLE_TOP_HEIGHT = AXIS_TITLE_LINE_HEIGHT + AXIS_TITLE_TOP_GRID_GAP - Y_AXIS_LABEL_OVERHANG;
|
|
3383
|
+
/**
|
|
3384
|
+
* Пустая полоса под подписями оси X внутри SVG линейного графика: под ось зарезервировано
|
|
3385
|
+
* LINE_CHART_LABEL_MARGIN (20px), а подписи сдвинуты вниз на +16px, поэтому строка подписи
|
|
3386
|
+
* (шрифт d3 10px) кончается примерно в 14px от низа SVG.
|
|
3387
|
+
*/
|
|
3388
|
+
const LINE_CHART_X_LABELS_BLANK = 14;
|
|
3389
|
+
/** Зазор между подписями оси X и подписью самой оси — по макету. */
|
|
3390
|
+
const X_AXIS_TITLE_GAP = 4;
|
|
3391
|
+
/** Зазор между подписью оси X и легендой, идущей отдельной строкой, — по макету. */
|
|
3392
|
+
const X_AXIS_TITLE_LEGEND_GAP = 8;
|
|
3393
|
+
/** Выравнивание подписи оси X → `justify-content` строки-подвала графика. */
|
|
3394
|
+
const CHART_AXIS_ALIGN_JUSTIFY = {
|
|
3395
|
+
left: "flex-start",
|
|
3396
|
+
center: "center",
|
|
3397
|
+
right: "flex-end",
|
|
3398
|
+
};
|
|
3359
3399
|
const FILTER_PREFIX = "%";
|
|
3360
3400
|
/** Имя системного геометрического фильтра — выделение, нарисованное пользователем на карте. */
|
|
3361
3401
|
const GEOMETRY_FILTER_NAME = "geometry";
|
|
@@ -3465,7 +3505,76 @@ const CONTAINER_BODY_FILL_STYLE = {
|
|
|
3465
3505
|
*/
|
|
3466
3506
|
const CONTAINERS_GROUP_DEFAULTS = { boxSizing: "border-box" };
|
|
3467
3507
|
|
|
3468
|
-
|
|
3508
|
+
/** Обёртка линейного графика: строка горизонтальных подписей над телом, вертикальные — по бокам. */
|
|
3509
|
+
const LineChartLayout = styled.div.withConfig({ displayName: "LineChartLayout", componentId: "sc-gmzloe" }) `
|
|
3510
|
+
display: flex;
|
|
3511
|
+
flex-direction: column;
|
|
3512
|
+
width: 100%;
|
|
3513
|
+
height: 100%;
|
|
3514
|
+
min-width: 0;
|
|
3515
|
+
min-height: 0;
|
|
3516
|
+
`;
|
|
3517
|
+
const LineChartRow = styled.div.withConfig({ displayName: "LineChartRow", componentId: "sc-dxzi1m" }) `
|
|
3518
|
+
display: flex;
|
|
3519
|
+
flex: 1 1 auto;
|
|
3520
|
+
align-items: stretch;
|
|
3521
|
+
min-width: 0;
|
|
3522
|
+
min-height: 0;
|
|
3523
|
+
`;
|
|
3524
|
+
/**
|
|
3525
|
+
* Тело линейного графика между вертикальными подписями осей. Забирает всю оставшуюся ширину строки —
|
|
3526
|
+
* её и измеряем, чтобы отдать d3 пиксельную ширину: подписи бывают в одну и в две строки.
|
|
3527
|
+
*/
|
|
3528
|
+
const LineChartBody = styled.div.withConfig({ displayName: "LineChartBody", componentId: "sc-1sbsc7u" }) `
|
|
3529
|
+
flex: 1 1 auto;
|
|
3530
|
+
min-width: 0;
|
|
3531
|
+
`;
|
|
3532
|
+
const AxisTitlesRow = styled.div.withConfig({ displayName: "AxisTitlesRow", componentId: "sc-1hskx6f" }) `
|
|
3533
|
+
display: flex;
|
|
3534
|
+
flex: 0 0 ${AXIS_TITLE_TOP_HEIGHT}px;
|
|
3535
|
+
justify-content: space-between;
|
|
3536
|
+
align-items: flex-start;
|
|
3537
|
+
gap: 0.5rem;
|
|
3538
|
+
height: ${AXIS_TITLE_TOP_HEIGHT}px;
|
|
3539
|
+
min-width: 0;
|
|
3540
|
+
`;
|
|
3541
|
+
const AxisTitleText = styled.div.withConfig({ displayName: "AxisTitleText", componentId: "sc-9shs4l" }) `
|
|
3542
|
+
font-size: 0.625rem;
|
|
3543
|
+
line-height: ${AXIS_TITLE_LINE_HEIGHT}px;
|
|
3544
|
+
color: ${({ $color, theme: { palette } }) => $color || palette.iconDisabled};
|
|
3545
|
+
`;
|
|
3546
|
+
const AxisTitleTop = styled(AxisTitleText).withConfig({ displayName: "AxisTitleTop", componentId: "sc-pv3dgm" }) `
|
|
3547
|
+
overflow: hidden;
|
|
3548
|
+
white-space: nowrap;
|
|
3549
|
+
text-overflow: ellipsis;
|
|
3550
|
+
`;
|
|
3551
|
+
/**
|
|
3552
|
+
* Колонка вертикальной подписи оси: ширина — по тексту (одна или две строки) плюс зазор до значений
|
|
3553
|
+
* шкалы. Вертикальные отступы колонки повторяют поля SVG, поэтому подпись центрируется по полю
|
|
3554
|
+
* графика, а не по всей высоте вместе с подписями оси X.
|
|
3555
|
+
*/
|
|
3556
|
+
const AxisTitleSideColumn = styled.div.withConfig({ displayName: "AxisTitleSideColumn", componentId: "sc-11nmkfu" }) `
|
|
3557
|
+
display: flex;
|
|
3558
|
+
flex: 0 0 auto;
|
|
3559
|
+
align-items: center;
|
|
3560
|
+
justify-content: center;
|
|
3561
|
+
box-sizing: border-box;
|
|
3562
|
+
padding: ${({ $plotTop }) => $plotTop}px 0 ${({ $plotBottom }) => $plotBottom}px;
|
|
3563
|
+
${({ $side }) => ($side === "left" ? "padding-right" : "padding-left")}: ${AXIS_TITLE_GAP}px;
|
|
3564
|
+
`;
|
|
3565
|
+
/**
|
|
3566
|
+
* Сам текст вертикальной подписи. Поворот вынесен на внутренний элемент: повёрнутая целиком колонка
|
|
3567
|
+
* перенесла бы зазор до шкалы на внешнюю сторону. Левая подпись читается снизу вверх, правая — сверху
|
|
3568
|
+
* вниз, как на макете.
|
|
3569
|
+
*/
|
|
3570
|
+
const AxisTitleSide = styled(AxisTitleText).withConfig({ displayName: "AxisTitleSide", componentId: "sc-lretfl" }) `
|
|
3571
|
+
max-height: 100%;
|
|
3572
|
+
overflow: hidden;
|
|
3573
|
+
text-align: center;
|
|
3574
|
+
writing-mode: vertical-rl;
|
|
3575
|
+
transform: ${({ $side }) => ($side === "left" ? "rotate(180deg)" : "none")};
|
|
3576
|
+
`;
|
|
3577
|
+
const ChartTooltipTable = styled.table.withConfig({ displayName: "ChartTooltipTable", componentId: "sc-1j0a1z" }) `
|
|
3469
3578
|
td {
|
|
3470
3579
|
padding: 0;
|
|
3471
3580
|
}
|
|
@@ -3474,7 +3583,7 @@ const ChartTooltipTable = styled.table.withConfig({ displayName: "ChartTooltipTa
|
|
|
3474
3583
|
padding-bottom: 0.375rem;
|
|
3475
3584
|
}
|
|
3476
3585
|
`;
|
|
3477
|
-
const ChartTooltip = styled(Flex).withConfig({ displayName: "ChartTooltip", componentId: "sc-
|
|
3586
|
+
const ChartTooltip = styled(Flex).withConfig({ displayName: "ChartTooltip", componentId: "sc-1ps09qa" }) `
|
|
3478
3587
|
flex-wrap: nowrap;
|
|
3479
3588
|
background: rgb(48, 69, 79);
|
|
3480
3589
|
border-radius: 0.25rem;
|
|
@@ -3484,26 +3593,26 @@ const ChartTooltip = styled(Flex).withConfig({ displayName: "ChartTooltip", comp
|
|
|
3484
3593
|
margin-bottom: 0.25rem;
|
|
3485
3594
|
}
|
|
3486
3595
|
`;
|
|
3487
|
-
const ChartTooltipLabel = styled.div.withConfig({ displayName: "ChartTooltipLabel", componentId: "sc-
|
|
3596
|
+
const ChartTooltipLabel = styled.div.withConfig({ displayName: "ChartTooltipLabel", componentId: "sc-1chgokj" }) `
|
|
3488
3597
|
margin-right: 0.25rem;
|
|
3489
3598
|
`;
|
|
3490
|
-
const ChartTooltipColor = styled.div.withConfig({ displayName: "ChartTooltipColor", componentId: "sc-
|
|
3599
|
+
const ChartTooltipColor = styled.div.withConfig({ displayName: "ChartTooltipColor", componentId: "sc-1un94mw" }) `
|
|
3491
3600
|
width: 0.625rem;
|
|
3492
3601
|
height: 0.625rem;
|
|
3493
3602
|
background-color: ${({ $color }) => $color};
|
|
3494
3603
|
border-radius: ${({ theme: { borderRadius } }) => borderRadius.smallest};
|
|
3495
3604
|
margin-right: 0.25rem;
|
|
3496
3605
|
`;
|
|
3497
|
-
const ChartLegendColor$1 = styled.div.withConfig({ displayName: "ChartLegendColor", componentId: "sc-
|
|
3606
|
+
const ChartLegendColor$1 = styled.div.withConfig({ displayName: "ChartLegendColor", componentId: "sc-sw1cfw" }) `
|
|
3498
3607
|
width: 0.5rem;
|
|
3499
3608
|
height: 0.5rem;
|
|
3500
3609
|
background-color: ${({ $color }) => $color};
|
|
3501
3610
|
border-radius: 0.125rem;
|
|
3502
3611
|
`;
|
|
3503
|
-
const ChartLegendValue = styled.div.withConfig({ displayName: "ChartLegendValue", componentId: "sc-
|
|
3612
|
+
const ChartLegendValue = styled.div.withConfig({ displayName: "ChartLegendValue", componentId: "sc-1s1kjum" }) `
|
|
3504
3613
|
opacity: 0.65;
|
|
3505
3614
|
`;
|
|
3506
|
-
const ChartTooltipRow = styled(Flex).withConfig({ displayName: "ChartTooltipRow", componentId: "sc-
|
|
3615
|
+
const ChartTooltipRow = styled(Flex).withConfig({ displayName: "ChartTooltipRow", componentId: "sc-ftllia" }) `
|
|
3507
3616
|
display: flex;
|
|
3508
3617
|
flex-direction: row;
|
|
3509
3618
|
flex-wrap: nowrap;
|
|
@@ -3515,11 +3624,11 @@ const ChartTooltipRow = styled(Flex).withConfig({ displayName: "ChartTooltipRow"
|
|
|
3515
3624
|
margin-right: 0.25rem;
|
|
3516
3625
|
}
|
|
3517
3626
|
`;
|
|
3518
|
-
const ChartTooltipName = styled.div.withConfig({ displayName: "ChartTooltipName", componentId: "sc-
|
|
3627
|
+
const ChartTooltipName = styled.div.withConfig({ displayName: "ChartTooltipName", componentId: "sc-16ov53z" }) `
|
|
3519
3628
|
margin-right: 1rem;
|
|
3520
3629
|
opacity: 0.65;
|
|
3521
3630
|
`;
|
|
3522
|
-
const PieChartCenter = styled.div.withConfig({ displayName: "PieChartCenter", componentId: "sc-
|
|
3631
|
+
const PieChartCenter = styled.div.withConfig({ displayName: "PieChartCenter", componentId: "sc-5m536c" }) `
|
|
3523
3632
|
position: absolute;
|
|
3524
3633
|
top: 50%;
|
|
3525
3634
|
left: 50%;
|
|
@@ -3528,7 +3637,7 @@ const PieChartCenter = styled.div.withConfig({ displayName: "PieChartCenter", co
|
|
|
3528
3637
|
font-weight: bold;
|
|
3529
3638
|
font-size: 1.5rem;
|
|
3530
3639
|
`;
|
|
3531
|
-
const ChartWrapperContainer = styled.div.withConfig({ displayName: "ChartWrapperContainer", componentId: "sc-
|
|
3640
|
+
const ChartWrapperContainer = styled.div.withConfig({ displayName: "ChartWrapperContainer", componentId: "sc-1ixngl" }) `
|
|
3532
3641
|
position: relative;
|
|
3533
3642
|
width: 100%;
|
|
3534
3643
|
`;
|
|
@@ -3537,7 +3646,7 @@ const ChartWrapperContainer = styled.div.withConfig({ displayName: "ChartWrapper
|
|
|
3537
3646
|
* на неё вешается ref для ResizeObserver — меряем обе оси без цикла. Плоский div (не Flex uilib), как соседний
|
|
3538
3647
|
* ChartWrapperContainer, чтобы ref гарантированно дошёл до DOM-узла. Тело графика центрируется внутри.
|
|
3539
3648
|
*/
|
|
3540
|
-
const ChartFillMeasure = styled.div.withConfig({ displayName: "ChartFillMeasure", componentId: "sc-
|
|
3649
|
+
const ChartFillMeasure = styled.div.withConfig({ displayName: "ChartFillMeasure", componentId: "sc-3rqqmt" }) `
|
|
3541
3650
|
position: relative;
|
|
3542
3651
|
display: flex;
|
|
3543
3652
|
align-items: center;
|
|
@@ -3555,7 +3664,7 @@ const ChartFillMeasure = styled.div.withConfig({ displayName: "ChartFillMeasure"
|
|
|
3555
3664
|
display: block;
|
|
3556
3665
|
}
|
|
3557
3666
|
`;
|
|
3558
|
-
const Tooltip = styled.div.withConfig({ displayName: "Tooltip", componentId: "sc-
|
|
3667
|
+
const Tooltip = styled.div.withConfig({ displayName: "Tooltip", componentId: "sc-k91v0" }) `
|
|
3559
3668
|
position: relative;
|
|
3560
3669
|
border-radius: 0.25rem;
|
|
3561
3670
|
background-color: rgba(28, 33, 48);
|
|
@@ -3660,7 +3769,7 @@ const LineChartStyles = createGlobalStyle `
|
|
|
3660
3769
|
fill: ${({ theme: { palette } }) => palette.textDisabled};
|
|
3661
3770
|
}
|
|
3662
3771
|
`;
|
|
3663
|
-
const StyledBarChart = styled(BarChart$1).withConfig({ displayName: "StyledBarChart", componentId: "sc-
|
|
3772
|
+
const StyledBarChart = styled(BarChart$1).withConfig({ displayName: "StyledBarChart", componentId: "sc-16gz38d" }) `
|
|
3664
3773
|
.domain {
|
|
3665
3774
|
display: none;
|
|
3666
3775
|
}
|
|
@@ -4548,6 +4657,79 @@ const getAttributeConfigurationByName = (attributes, name) => {
|
|
|
4548
4657
|
return attributes[name];
|
|
4549
4658
|
};
|
|
4550
4659
|
|
|
4660
|
+
const EMPTY_AXIS = {};
|
|
4661
|
+
const warnedLegacySources = new Set();
|
|
4662
|
+
// Сборщик консьюмера подставляет `process.env.NODE_ENV` строкой, поэтому выражение должно быть
|
|
4663
|
+
// ровно таким — без `typeof process` и без `?.`. Сам `process` webpack 5 в браузер не завозит:
|
|
4664
|
+
// проверка `typeof process` отключила бы предупреждения и в dev. Консьюмер без сборщика получит
|
|
4665
|
+
// ReferenceError — он гасится, и предупреждений просто нет.
|
|
4666
|
+
const isDevEnvironment = (() => {
|
|
4667
|
+
try {
|
|
4668
|
+
return process.env.NODE_ENV !== "production";
|
|
4669
|
+
}
|
|
4670
|
+
catch {
|
|
4671
|
+
return false;
|
|
4672
|
+
}
|
|
4673
|
+
})();
|
|
4674
|
+
/**
|
|
4675
|
+
* Один раз на источник сообщает, что конфиг остался на устаревшей плоской форме.
|
|
4676
|
+
*
|
|
4677
|
+
* Без такого маркера момент «легаси закончилось» не наступает никогда, и временный слой
|
|
4678
|
+
* совместимости становится постоянным.
|
|
4679
|
+
*/
|
|
4680
|
+
const warnLegacyAxis = ({ dataSourceName, attributeName }) => {
|
|
4681
|
+
if (!isDevEnvironment)
|
|
4682
|
+
return;
|
|
4683
|
+
const key = `${dataSourceName ?? "?"}:${attributeName ?? "?"}`;
|
|
4684
|
+
if (warnedLegacySources.has(key))
|
|
4685
|
+
return;
|
|
4686
|
+
warnedLegacySources.add(key);
|
|
4687
|
+
// eslint-disable-next-line no-console
|
|
4688
|
+
console.warn(`[Dashboard] Источник "${key}" использует устаревшие поля оси (chartAxis/axisColor/hideAxis). ` +
|
|
4689
|
+
"Перепишите их в объект axis: { type, side, color, title, hide }. " +
|
|
4690
|
+
"Слой совместимости временный.");
|
|
4691
|
+
};
|
|
4692
|
+
/**
|
|
4693
|
+
* Настройки оси источника.
|
|
4694
|
+
*
|
|
4695
|
+
* Читает `axis`, а при его отсутствии собирает объект из устаревших плоских полей
|
|
4696
|
+
* `chartAxis` / `axisColor` / `hideAxis`. Заданный `axis` имеет приоритет: узел, который уже
|
|
4697
|
+
* правили в редакторе, не должен откатываться к старым значениям.
|
|
4698
|
+
*/
|
|
4699
|
+
const resolveAxis = (source) => {
|
|
4700
|
+
if (!source)
|
|
4701
|
+
return EMPTY_AXIS;
|
|
4702
|
+
const { axis, chartAxis, axisColor, hideAxis } = source;
|
|
4703
|
+
if (axis)
|
|
4704
|
+
return axis;
|
|
4705
|
+
if (chartAxis === undefined && axisColor === undefined && hideAxis === undefined)
|
|
4706
|
+
return EMPTY_AXIS;
|
|
4707
|
+
warnLegacyAxis(source);
|
|
4708
|
+
return {
|
|
4709
|
+
type: chartAxis === "x" ? "x" : "y",
|
|
4710
|
+
color: axisColor,
|
|
4711
|
+
hide: hideAxis,
|
|
4712
|
+
};
|
|
4713
|
+
};
|
|
4714
|
+
/**
|
|
4715
|
+
* Источник питает ось значений.
|
|
4716
|
+
*
|
|
4717
|
+
* Отсутствие `axis.type` означает `"y"`: конфиг без явного типа — самый частый случай,
|
|
4718
|
+
* и раньше такой источник молча выпадал из графика.
|
|
4719
|
+
*/
|
|
4720
|
+
const isValueAxis = (source) => (resolveAxis(source).type ?? "y") === "y";
|
|
4721
|
+
/** Сторона оси; отсутствие `axis.side` означает `"left"`. */
|
|
4722
|
+
const getAxisSide = (source) => resolveAxis(source).side ?? "left";
|
|
4723
|
+
/** Источник выводится на правой оси. */
|
|
4724
|
+
const isRightAxis = (source) => getAxisSide(source) === "right";
|
|
4725
|
+
/**
|
|
4726
|
+
* Запись описывает ось чарта, а не источник фильтра.
|
|
4727
|
+
*
|
|
4728
|
+
* `BarChartFilter` собирает `relatedConfig` вручную и осей не задаёт — ему нужна исходная палитра,
|
|
4729
|
+
* а не растянутая под число элементов.
|
|
4730
|
+
*/
|
|
4731
|
+
const hasAxisConfig = ({ axis, chartAxis }) => axis !== undefined || chartAxis !== undefined;
|
|
4732
|
+
|
|
4551
4733
|
const getAttributesConfiguration = (layer) => {
|
|
4552
4734
|
const layerAttributeConfiguration = layer?.configuration?.attributesConfiguration ?? {};
|
|
4553
4735
|
const { geometryAttribute, idAttribute } = layerAttributeConfiguration;
|
|
@@ -4572,7 +4754,7 @@ const getAttributesConfiguration = (layer) => {
|
|
|
4572
4754
|
|
|
4573
4755
|
const formatChartRelatedValue = (t, value, layerInfo, relatedAttributes) => {
|
|
4574
4756
|
const layerDefinition = getAttributesConfiguration(layerInfo);
|
|
4575
|
-
const relatedAxis = relatedAttributes.find(
|
|
4757
|
+
const relatedAxis = relatedAttributes.find(isValueAxis);
|
|
4576
4758
|
const attribute = getAttributeConfigurationByName(layerDefinition.attributes, relatedAxis?.attributeName);
|
|
4577
4759
|
return attribute
|
|
4578
4760
|
? formatAttributeValue({ t, type: attribute.type, value, stringFormat: attribute.stringFormat })
|
|
@@ -5417,11 +5599,11 @@ const getAttributeValue = (element, attributes) => {
|
|
|
5417
5599
|
return typeof value === "string" && maxLength && maxLength < value.length ? (jsx(TextTrim, { maxLength: maxLength, wordBreak: wordBreak, expandable: expandable, lineBreak: lineBreak, children: value })) : (value);
|
|
5418
5600
|
};
|
|
5419
5601
|
|
|
5420
|
-
const getChartAxes = (chartElement) => chartElement?.options?.relatedDataSources?.filter(
|
|
5602
|
+
const getChartAxes = (chartElement) => chartElement?.options?.relatedDataSources?.filter(isValueAxis);
|
|
5421
5603
|
|
|
5422
5604
|
const getChartFilterName = (relatedDataSources) => {
|
|
5423
5605
|
const relatedAttributes = relatedDataSources || [];
|
|
5424
|
-
const axes = relatedAttributes.filter(
|
|
5606
|
+
const axes = relatedAttributes.filter(isValueAxis);
|
|
5425
5607
|
return axes?.[0]?.filterName;
|
|
5426
5608
|
};
|
|
5427
5609
|
|
|
@@ -5640,13 +5822,14 @@ const GRID_TILE_SIZE = "4.5rem";
|
|
|
5640
5822
|
const LIST_ICON_SIZE = "1.5rem";
|
|
5641
5823
|
const JPG_MIME_TYPE = "image/jpeg";
|
|
5642
5824
|
const PNG_MIME_TYPE = "image/png";
|
|
5825
|
+
const SVG_MIME_TYPE = "image/svg+xml";
|
|
5643
5826
|
const IMAGE_MIME_TYPES = [
|
|
5644
5827
|
"image/apng",
|
|
5645
5828
|
"image/avif",
|
|
5646
5829
|
"image/gif",
|
|
5647
5830
|
"image/jpeg",
|
|
5648
5831
|
"image/png",
|
|
5649
|
-
|
|
5832
|
+
SVG_MIME_TYPE,
|
|
5650
5833
|
"image/webp",
|
|
5651
5834
|
];
|
|
5652
5835
|
const XLSX_MIME_TYPES = [
|
|
@@ -7051,6 +7234,96 @@ const useFetchImageWithAuth = (url) => {
|
|
|
7051
7234
|
return isExternal ? url : blobUrl;
|
|
7052
7235
|
};
|
|
7053
7236
|
|
|
7237
|
+
/**
|
|
7238
|
+
* Оси значений линейного графика и атрибуты, по `stringFormat` которых форматируются деления.
|
|
7239
|
+
*
|
|
7240
|
+
* У левой и правой осей это разные атрибуты, поэтому они резолвятся по отдельности: иначе на
|
|
7241
|
+
* правой оси окажутся единицы измерения левой.
|
|
7242
|
+
*/
|
|
7243
|
+
const useChartAxisAttributes = ({ dataSources, relatedAttributes }) => {
|
|
7244
|
+
const { layerInfos, dataSources: fetchedDataSources } = useWidgetContext();
|
|
7245
|
+
const axes = useMemo(() => (relatedAttributes || []).filter(isValueAxis), [relatedAttributes]);
|
|
7246
|
+
const strokeColors = useMemo(() => axes.map(related => resolveAxis(related).color), [axes]);
|
|
7247
|
+
const leftAxis = useMemo(() => axes.find(related => !isRightAxis(related)) ?? axes[0] ?? relatedAttributes?.[0], [axes, relatedAttributes]);
|
|
7248
|
+
const rightAxis = useMemo(() => axes.find(isRightAxis), [axes]);
|
|
7249
|
+
const resolveAxisAttribute = useCallback((related) => {
|
|
7250
|
+
if (!related)
|
|
7251
|
+
return undefined;
|
|
7252
|
+
const layerInfo = getDataSourceLayerInfo({
|
|
7253
|
+
layerInfos,
|
|
7254
|
+
configDataSource: dataSources?.find(({ name }) => name === related.dataSourceName),
|
|
7255
|
+
fetchedDataSource: getDataSource(related.dataSourceName, fetchedDataSources),
|
|
7256
|
+
});
|
|
7257
|
+
return getLayerInfoAttribute(layerInfo, related.attributeName);
|
|
7258
|
+
}, [dataSources, fetchedDataSources, layerInfos]);
|
|
7259
|
+
const leftAxisAttribute = useMemo(() => resolveAxisAttribute(leftAxis), [resolveAxisAttribute, leftAxis]);
|
|
7260
|
+
const rightAxisAttribute = useMemo(() => resolveAxisAttribute(rightAxis), [resolveAxisAttribute, rightAxis]);
|
|
7261
|
+
return { axes, strokeColors, leftAxisAttribute, rightAxisAttribute };
|
|
7262
|
+
};
|
|
7263
|
+
|
|
7264
|
+
/**
|
|
7265
|
+
* Форматтеры делений левой и правой шкал линейного графика — по `stringFormat` своего атрибута.
|
|
7266
|
+
*
|
|
7267
|
+
* Отдаются в `tickFormat` генератора оси, а не подменяют текст после отрисовки: d3 измеряет ширину
|
|
7268
|
+
* шкалы по уже нарисованным подписям и по ней сдвигает поле графика. Подмена текста задним числом
|
|
7269
|
+
* (`30` → `30,0`) делала подпись шире замера, и она заезжала на подпись оси слева.
|
|
7270
|
+
*/
|
|
7271
|
+
const useChartAxisTickFormat = ({ dataSources, relatedAttributes }) => {
|
|
7272
|
+
const { t } = useGlobalContext();
|
|
7273
|
+
const { leftAxisAttribute, rightAxisAttribute } = useChartAxisAttributes({ dataSources, relatedAttributes });
|
|
7274
|
+
const createTickFormat = useCallback((attribute) => (value) => {
|
|
7275
|
+
if (!value)
|
|
7276
|
+
return "0";
|
|
7277
|
+
return attribute
|
|
7278
|
+
? String(formatAttributeValue({
|
|
7279
|
+
t,
|
|
7280
|
+
type: attribute.type,
|
|
7281
|
+
value: Number(value),
|
|
7282
|
+
stringFormat: attribute.stringFormat,
|
|
7283
|
+
noUnits: true,
|
|
7284
|
+
}))
|
|
7285
|
+
: String(value);
|
|
7286
|
+
}, [t]);
|
|
7287
|
+
const formatLeftTick = useMemo(() => createTickFormat(leftAxisAttribute), [createTickFormat, leftAxisAttribute]);
|
|
7288
|
+
const formatRightTick = useMemo(() => createTickFormat(rightAxisAttribute), [createTickFormat, rightAxisAttribute]);
|
|
7289
|
+
return { formatLeftTick, formatRightTick };
|
|
7290
|
+
};
|
|
7291
|
+
|
|
7292
|
+
/**
|
|
7293
|
+
* Подписи осей линейного графика и место, которое они занимают над телом графика.
|
|
7294
|
+
*
|
|
7295
|
+
* Режим размещения общий для всех осей (`options.axis.titlePosition`), текст — у каждой оси свой.
|
|
7296
|
+
* Цвет подписи отдельной опцией не задаётся: одна серия на стороне — подпись в её цвет, несколько —
|
|
7297
|
+
* нейтральная, потому что тогда подпись описывает всю ось, а не одну из линий. Ширину вертикальных
|
|
7298
|
+
* подписей здесь не считаем — она зависит от числа строк текста и измеряется по факту.
|
|
7299
|
+
*/
|
|
7300
|
+
const useChartAxisTitles = ({ options, axes, isLineChart }) => {
|
|
7301
|
+
const axisTitlePosition = options?.axis?.titlePosition ?? "side";
|
|
7302
|
+
const axisTitles = useMemo(() => {
|
|
7303
|
+
const pick = (side) => {
|
|
7304
|
+
const sideAxes = axes.filter(related => getAxisSide(related) === side);
|
|
7305
|
+
const title = sideAxes.map(resolveAxis).find(axis => axis.title)?.title;
|
|
7306
|
+
if (!title)
|
|
7307
|
+
return undefined;
|
|
7308
|
+
return { title, color: sideAxes.length === 1 ? resolveAxis(sideAxes[0]).color : undefined };
|
|
7309
|
+
};
|
|
7310
|
+
return { left: pick("left"), right: pick("right") };
|
|
7311
|
+
}, [axes]);
|
|
7312
|
+
const hasAxisTitles = !!(isLineChart && (axisTitles.left || axisTitles.right));
|
|
7313
|
+
const hasTopTitles = hasAxisTitles && axisTitlePosition === "top";
|
|
7314
|
+
const hasSideTitles = hasAxisTitles && axisTitlePosition === "side";
|
|
7315
|
+
const hideLeftAxis = useMemo(() => axes.filter(related => !isRightAxis(related)).every(related => resolveAxis(related).hide), [axes]);
|
|
7316
|
+
const hideRightAxis = useMemo(() => axes.filter(isRightAxis).every(related => resolveAxis(related).hide), [axes]);
|
|
7317
|
+
return {
|
|
7318
|
+
axisTitles,
|
|
7319
|
+
hasTopTitles,
|
|
7320
|
+
hasSideTitles,
|
|
7321
|
+
axisTitlesHeight: hasTopTitles ? AXIS_TITLE_TOP_HEIGHT : 0,
|
|
7322
|
+
hideLeftAxis,
|
|
7323
|
+
hideRightAxis,
|
|
7324
|
+
};
|
|
7325
|
+
};
|
|
7326
|
+
|
|
7054
7327
|
const HEIGHT_OFFSET = 20;
|
|
7055
7328
|
const FILL_OPACITY = 0.28;
|
|
7056
7329
|
const lineGenerator = line()
|
|
@@ -7096,20 +7369,10 @@ function wrap() {
|
|
|
7096
7369
|
}
|
|
7097
7370
|
}
|
|
7098
7371
|
const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes, defaultColor, fontColor, markers, showMarkers, }) => {
|
|
7099
|
-
const {
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
.map(({ axisColor }) => axisColor);
|
|
7104
|
-
const yAxis = useMemo(() => relatedAttributes?.find(({ chartAxis }) => chartAxis === "y") ?? relatedAttributes?.[0], [relatedAttributes]);
|
|
7105
|
-
const yAxisAttribute = useMemo(() => {
|
|
7106
|
-
const layerInfo = getDataSourceLayerInfo({
|
|
7107
|
-
layerInfos,
|
|
7108
|
-
configDataSource: dataSources?.find(({ name }) => name === yAxis?.dataSourceName),
|
|
7109
|
-
fetchedDataSource: getDataSource(yAxis?.dataSourceName, fetchedDataSources),
|
|
7110
|
-
});
|
|
7111
|
-
return getLayerInfoAttribute(layerInfo, yAxis?.attributeName);
|
|
7112
|
-
}, [dataSources, fetchedDataSources, layerInfos, yAxis]);
|
|
7372
|
+
const { strokeColors } = useChartAxisAttributes({
|
|
7373
|
+
dataSources,
|
|
7374
|
+
relatedAttributes,
|
|
7375
|
+
});
|
|
7113
7376
|
const ref = useRef({
|
|
7114
7377
|
path: null,
|
|
7115
7378
|
area: null,
|
|
@@ -7162,22 +7425,9 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
|
|
|
7162
7425
|
svg
|
|
7163
7426
|
.selectAll(`.${lineChartClassNames.lineChartXScaleGlobal} .tick text`)
|
|
7164
7427
|
.attr("y", 16);
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
if (!item)
|
|
7169
|
-
return 0;
|
|
7170
|
-
return yAxisAttribute
|
|
7171
|
-
? formatAttributeValue({
|
|
7172
|
-
t,
|
|
7173
|
-
type: yAxisAttribute.type,
|
|
7174
|
-
value: item,
|
|
7175
|
-
stringFormat: yAxisAttribute.stringFormat,
|
|
7176
|
-
noUnits: true,
|
|
7177
|
-
})
|
|
7178
|
-
: item;
|
|
7179
|
-
})
|
|
7180
|
-
.each(wrap);
|
|
7428
|
+
// Текст делений форматируется ещё в генераторе оси (useChartAxisTickFormat), до замера ширины
|
|
7429
|
+
// шкалы; здесь его только укорачиваем.
|
|
7430
|
+
svg.selectAll(`.${lineChartClassNames.lineChartYScaleGlobal} .tick text`).each(wrap);
|
|
7181
7431
|
svg.selectAll(".tick text").attr("style", `color: ${fontColor}`);
|
|
7182
7432
|
const global = svg.select(`.${lineChartClassNames.lineChartLinesGlobal}`);
|
|
7183
7433
|
const lineChartLines = svg.selectAll(`.${lineChartClassNames.lineChartLine}`);
|
|
@@ -7213,7 +7463,6 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
|
|
|
7213
7463
|
svg.append("defs").html(() => defs.join(""));
|
|
7214
7464
|
}, [
|
|
7215
7465
|
fontColor,
|
|
7216
|
-
yAxisAttribute,
|
|
7217
7466
|
chartId,
|
|
7218
7467
|
strokeColors,
|
|
7219
7468
|
defaultColor,
|
|
@@ -7221,7 +7470,6 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
|
|
|
7221
7470
|
onChange,
|
|
7222
7471
|
showMarkers,
|
|
7223
7472
|
markers,
|
|
7224
|
-
t,
|
|
7225
7473
|
]);
|
|
7226
7474
|
return [customize, onChange];
|
|
7227
7475
|
};
|
|
@@ -7378,10 +7626,10 @@ const useChartData = ({ element, type }) => {
|
|
|
7378
7626
|
const configDataSources = useConfigDataSources(type);
|
|
7379
7627
|
const relatedAttributes = useMemo(() => element?.options?.relatedDataSources || [], [element?.options?.relatedDataSources]);
|
|
7380
7628
|
const loading = useMemo(() => !!relatedAttributes?.length &&
|
|
7381
|
-
!dataSources?.some(({ name }) => relatedAttributes.some(
|
|
7629
|
+
!dataSources?.some(({ name }) => relatedAttributes.some(related => isValueAxis(related) && related.dataSourceName === name)), [dataSources, relatedAttributes]);
|
|
7382
7630
|
const fetchedData = useMemo(() => {
|
|
7383
7631
|
const isRelated = !!relatedAttributes?.length;
|
|
7384
|
-
const filteredAttributes = relatedAttributes.filter(
|
|
7632
|
+
const filteredAttributes = relatedAttributes.filter(isValueAxis);
|
|
7385
7633
|
if (!element)
|
|
7386
7634
|
return [];
|
|
7387
7635
|
if (isRelated) {
|
|
@@ -7389,7 +7637,7 @@ const useChartData = ({ element, type }) => {
|
|
|
7389
7637
|
return [];
|
|
7390
7638
|
return filteredAttributes
|
|
7391
7639
|
.map(relatedAxis => {
|
|
7392
|
-
const { dataSourceName,
|
|
7640
|
+
const { dataSourceName, attributeName, attributeUnits } = relatedAxis;
|
|
7393
7641
|
const dataSource = configDataSources.find(({ name }) => name === dataSourceName);
|
|
7394
7642
|
const featureDataSource = getDataSource(dataSourceName, dataSources);
|
|
7395
7643
|
const layerInfo = getDataSourceLayerInfo({
|
|
@@ -7409,7 +7657,10 @@ const useChartData = ({ element, type }) => {
|
|
|
7409
7657
|
layerInfo,
|
|
7410
7658
|
})
|
|
7411
7659
|
: null,
|
|
7412
|
-
color:
|
|
7660
|
+
color: resolveAxis(relatedAxis).color,
|
|
7661
|
+
// Сторона едет вместе с данными: серии без значений отсеиваются ниже, и сопоставлять
|
|
7662
|
+
// их с осями по индексу уже нельзя.
|
|
7663
|
+
axisSide: getAxisSide(relatedAxis),
|
|
7413
7664
|
attributeName,
|
|
7414
7665
|
attributeUnits,
|
|
7415
7666
|
dataSourceName,
|
|
@@ -7422,6 +7673,7 @@ const useChartData = ({ element, type }) => {
|
|
|
7422
7673
|
return [
|
|
7423
7674
|
{
|
|
7424
7675
|
items: getDataFromAttributes(t, element, attributes),
|
|
7676
|
+
axisSide: "left",
|
|
7425
7677
|
layerInfo: null,
|
|
7426
7678
|
attributeName: null,
|
|
7427
7679
|
attributeUnits: null,
|
|
@@ -7441,7 +7693,7 @@ const useChartData = ({ element, type }) => {
|
|
|
7441
7693
|
]);
|
|
7442
7694
|
const isResolved = useMemo(() => !relatedAttributes?.length ||
|
|
7443
7695
|
relatedAttributes
|
|
7444
|
-
.filter(
|
|
7696
|
+
.filter(isValueAxis)
|
|
7445
7697
|
.every(({ dataSourceName }) => Array.isArray(getDataSource(dataSourceName, dataSources)?.features)), [relatedAttributes, dataSources]);
|
|
7446
7698
|
const [data, setData] = useState(fetchedData);
|
|
7447
7699
|
useEffect(() => {
|
|
@@ -8973,6 +9225,15 @@ const ChartLegendContainer = styled(Flex).withConfig({ displayName: "ChartLegend
|
|
|
8973
9225
|
flex-direction: column;
|
|
8974
9226
|
flex-wrap: wrap;
|
|
8975
9227
|
justify-content: ${({ twoColumns }) => (twoColumns ? "flex-start" : "center")};
|
|
9228
|
+
|
|
9229
|
+
/* Явная опция column перебивает раскладку, которую легенде навязывает ChartContainer
|
|
9230
|
+
(под графиком — в ряд, сбоку — столбиком). Без опции поведение прежнее. */
|
|
9231
|
+
${({ $column }) => $column !== undefined &&
|
|
9232
|
+
css `
|
|
9233
|
+
&&& {
|
|
9234
|
+
flex-direction: ${$column ? "column" : "row"};
|
|
9235
|
+
}
|
|
9236
|
+
`}
|
|
8976
9237
|
`;
|
|
8977
9238
|
const ChartLegendItem = styled(Flex).withConfig({ displayName: "ChartLegendItem", componentId: "sc-16m9piw" }) `
|
|
8978
9239
|
cursor: ${({ onClick }) => (onClick ? "pointer" : "default")};
|
|
@@ -9041,12 +9302,129 @@ const ContainerChart = styled(Flex).withConfig({ displayName: "ContainerChart",
|
|
|
9041
9302
|
`}
|
|
9042
9303
|
`;
|
|
9043
9304
|
const ContainerLegend = styled(Flex).withConfig({ displayName: "ContainerLegend", componentId: "sc-z1n1s8" }) ``;
|
|
9044
|
-
|
|
9305
|
+
/**
|
|
9306
|
+
* Выравнивание строки по полю графика: ширина тела графика, а внутренние отступы — до краёв поля
|
|
9307
|
+
* (колонка подписи оси и значения шкалы). Тело графика центрируется в слоте, поэтому и строка
|
|
9308
|
+
* центрируется. Правило поднято `&&&` над шириной, которую строкам задаёт `ContainerValue`.
|
|
9309
|
+
*/
|
|
9310
|
+
const plotInsetsMixin = css `
|
|
9311
|
+
${({ $insets }) => $insets &&
|
|
9312
|
+
css `
|
|
9313
|
+
&&& {
|
|
9314
|
+
box-sizing: border-box;
|
|
9315
|
+
align-self: center;
|
|
9316
|
+
width: ${$insets.width}px;
|
|
9317
|
+
max-width: 100%;
|
|
9318
|
+
padding-left: ${$insets.left}px;
|
|
9319
|
+
padding-right: ${$insets.right}px;
|
|
9320
|
+
}
|
|
9321
|
+
`}
|
|
9322
|
+
`;
|
|
9323
|
+
/**
|
|
9324
|
+
* Строка ждёт, пока график сообщит положение поля: место занимает, но не видна. Иначе до первой
|
|
9325
|
+
* отрисовки d3 она стояла бы по краю контейнера и потом прыгала на место.
|
|
9326
|
+
*/
|
|
9327
|
+
const awaitingPlotMixin = css `
|
|
9328
|
+
${({ $awaitingPlot }) => $awaitingPlot &&
|
|
9329
|
+
css `
|
|
9330
|
+
visibility: hidden;
|
|
9331
|
+
`}
|
|
9332
|
+
`;
|
|
9333
|
+
/**
|
|
9334
|
+
* Строка под телом графика: подпись оси X и, при `legendInline`, легенда справа от неё.
|
|
9335
|
+
*
|
|
9336
|
+
* `$offsetTop` подтягивает строку к подписям оси X: под ними внутри SVG остаётся пустая полоса,
|
|
9337
|
+
* и без поправки зазор получился бы втрое больше макетного.
|
|
9338
|
+
*/
|
|
9339
|
+
const ChartFooter = styled(Flex).withConfig({ displayName: "ChartFooter", componentId: "sc-nii28w" }) `
|
|
9340
|
+
align-items: center;
|
|
9341
|
+
flex-wrap: nowrap;
|
|
9342
|
+
gap: 0.5rem;
|
|
9343
|
+
width: 100%;
|
|
9344
|
+
margin-top: ${({ $offsetTop }) => $offsetTop ?? 0}px;
|
|
9345
|
+
justify-content: ${({ $align }) => $align};
|
|
9346
|
+
|
|
9347
|
+
${ContainerLegend} {
|
|
9348
|
+
justify-content: flex-end;
|
|
9349
|
+
margin-left: auto;
|
|
9350
|
+
}
|
|
9351
|
+
|
|
9352
|
+
/* Легенда в строке с подписью: записи прижаты вправо, без отступа сверху, который ей задаёт
|
|
9353
|
+
ContainerValue, и без нижнего отступа записей — иначе она съедет вниз относительно подписи.
|
|
9354
|
+
Прижимать нужно сами записи: обёртки легенды — Flex из uilib-gl с width: 100%, и выравнивание
|
|
9355
|
+
внешнего контейнера до записей не доходит, а своё у легенды — по центру. */
|
|
9356
|
+
&&& ${ChartLegendContainer} {
|
|
9357
|
+
justify-content: flex-end;
|
|
9358
|
+
margin-top: 0;
|
|
9359
|
+
}
|
|
9360
|
+
|
|
9361
|
+
&&& ${ChartLegendItem} {
|
|
9362
|
+
margin-bottom: 0;
|
|
9363
|
+
}
|
|
9364
|
+
|
|
9365
|
+
${plotInsetsMixin};
|
|
9366
|
+
${awaitingPlotMixin};
|
|
9367
|
+
`;
|
|
9368
|
+
const ChartXAxisTitle = styled.div.withConfig({ displayName: "ChartXAxisTitle", componentId: "sc-1vsgzi9" }) `
|
|
9369
|
+
font-size: 0.625rem;
|
|
9370
|
+
line-height: 0.75rem;
|
|
9371
|
+
white-space: nowrap;
|
|
9372
|
+
color: ${({ $color, theme: { palette } }) => $color || palette.textDisabled};
|
|
9373
|
+
`;
|
|
9374
|
+
/**
|
|
9375
|
+
* Строка легенды под графиком. `$gapTop` заменяет отступ сверху, который легенде задаёт `ContainerValue`;
|
|
9376
|
+
* `$offsetTop` сдвигает саму строку — подтягивает её к подписям оси X, как строку с подписью оси.
|
|
9377
|
+
*
|
|
9378
|
+
* `$justify` выравнивает сами записи. Выравнивание строки (`justifyContent`) до них не доходит: обёртки
|
|
9379
|
+
* легенды — Flex из uilib-gl с `width: 100%`, а записи внутри легенда всегда центрирует.
|
|
9380
|
+
*/
|
|
9381
|
+
const ChartLegendRow = styled(ContainerLegend).withConfig({ displayName: "ChartLegendRow", componentId: "sc-1a12wrz" }) `
|
|
9382
|
+
${({ $offsetTop }) => $offsetTop !== undefined &&
|
|
9383
|
+
css `
|
|
9384
|
+
margin-top: ${$offsetTop}px;
|
|
9385
|
+
`}
|
|
9386
|
+
|
|
9387
|
+
${({ $gapTop }) => $gapTop !== undefined &&
|
|
9388
|
+
css `
|
|
9389
|
+
&&& ${ChartLegendContainer} {
|
|
9390
|
+
margin-top: ${$gapTop}px;
|
|
9391
|
+
}
|
|
9392
|
+
`}
|
|
9393
|
+
|
|
9394
|
+
${({ $justify }) => $justify &&
|
|
9395
|
+
css `
|
|
9396
|
+
&&& ${ChartLegendContainer} {
|
|
9397
|
+
justify-content: ${$justify};
|
|
9398
|
+
}
|
|
9399
|
+
`}
|
|
9400
|
+
|
|
9401
|
+
${plotInsetsMixin};
|
|
9402
|
+
${awaitingPlotMixin};
|
|
9403
|
+
`;
|
|
9404
|
+
/**
|
|
9405
|
+
* Колонка «график + подпись оси X» для легенды сбоку (`twoColumns`). Без неё подпись встала бы третьим
|
|
9406
|
+
* элементом ряда рядом с легендой, а не под графиком.
|
|
9407
|
+
*/
|
|
9408
|
+
const ChartWithFooter = styled(Flex).withConfig({ displayName: "ChartWithFooter", componentId: "sc-140gv2s" }) `
|
|
9409
|
+
flex-direction: column;
|
|
9410
|
+
flex-wrap: nowrap;
|
|
9411
|
+
min-width: 0;
|
|
9412
|
+
|
|
9413
|
+
${({ $fill }) => $fill &&
|
|
9414
|
+
css `
|
|
9415
|
+
min-height: 0;
|
|
9416
|
+
`}
|
|
9417
|
+
|
|
9418
|
+
&&& ${ContainerChart} {
|
|
9419
|
+
width: 100%;
|
|
9420
|
+
}
|
|
9421
|
+
`;
|
|
9422
|
+
const ContainerUnits = styled.div.withConfig({ displayName: "ContainerUnits", componentId: "sc-vj15z6" }) `
|
|
9045
9423
|
margin-left: 0.5rem;
|
|
9046
9424
|
white-space: nowrap;
|
|
9047
9425
|
font-size: 0.75rem;
|
|
9048
9426
|
`;
|
|
9049
|
-
const ContainerValue = styled(Flex).withConfig({ displayName: "ContainerValue", componentId: "sc-
|
|
9427
|
+
const ContainerValue = styled(Flex).withConfig({ displayName: "ContainerValue", componentId: "sc-1bnfj5v" }) `
|
|
9050
9428
|
justify-content: flex-end;
|
|
9051
9429
|
align-items: center;
|
|
9052
9430
|
flex-wrap: nowrap;
|
|
@@ -9065,7 +9443,7 @@ const ContainerValue = styled(Flex).withConfig({ displayName: "ContainerValue",
|
|
|
9065
9443
|
width: ${({ column }) => (column ? "100%" : "auto")};
|
|
9066
9444
|
}
|
|
9067
9445
|
|
|
9068
|
-
${ContainerChart}, ${ContainerLegend} {
|
|
9446
|
+
${ContainerChart}, ${ContainerLegend}, ${ChartWithFooter} {
|
|
9069
9447
|
width: ${({ column }) => (column ? "100%" : "50%")};
|
|
9070
9448
|
}
|
|
9071
9449
|
|
|
@@ -9088,7 +9466,7 @@ const SizeIconMixin = css `
|
|
|
9088
9466
|
font-size: ${({ $fontSize }) => $fontSize}px !important;
|
|
9089
9467
|
}
|
|
9090
9468
|
`;
|
|
9091
|
-
styled(Icon).withConfig({ displayName: "ContainerIcon", componentId: "sc-
|
|
9469
|
+
styled(Icon).withConfig({ displayName: "ContainerIcon", componentId: "sc-18399bz" }) `
|
|
9092
9470
|
width: auto;
|
|
9093
9471
|
height: auto;
|
|
9094
9472
|
margin-bottom: 0.5rem;
|
|
@@ -9102,7 +9480,7 @@ const SvgContainerColorMixin$1 = css `
|
|
|
9102
9480
|
fill: ${({ $fontColor }) => $fontColor};
|
|
9103
9481
|
}
|
|
9104
9482
|
`;
|
|
9105
|
-
const SvgContainer$1 = styled.div.withConfig({ displayName: "SvgContainer", componentId: "sc-
|
|
9483
|
+
const SvgContainer$1 = styled.div.withConfig({ displayName: "SvgContainer", componentId: "sc-8l0ajh" }) `
|
|
9106
9484
|
&&& {
|
|
9107
9485
|
min-width: ${({ $width }) => ($width ? `${$width}px` : "1rem")};
|
|
9108
9486
|
max-width: ${({ $width }) => ($width ? `${$width}px` : "1rem")};
|
|
@@ -9114,7 +9492,7 @@ const SvgContainer$1 = styled.div.withConfig({ displayName: "SvgContainer", comp
|
|
|
9114
9492
|
}
|
|
9115
9493
|
}
|
|
9116
9494
|
`;
|
|
9117
|
-
const TwoColumnContainerWrapper = styled(Container).withConfig({ displayName: "TwoColumnContainerWrapper", componentId: "sc-
|
|
9495
|
+
const TwoColumnContainerWrapper = styled(Container).withConfig({ displayName: "TwoColumnContainerWrapper", componentId: "sc-1yxeknf" }) `
|
|
9118
9496
|
flex-direction: row;
|
|
9119
9497
|
flex-wrap: nowrap;
|
|
9120
9498
|
align-items: center;
|
|
@@ -9141,6 +9519,16 @@ const CameraContainer = memo(({ elementConfig, type, renderElement }) => {
|
|
|
9141
9519
|
return (jsxs(ContainerRoot, { ...root, children: [jsx(ContainerBackground, { elementConfig: elementConfig, renderElement: renderElement }), jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxs(Container, { ...body, children: [jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsx(ContainerValue, { children: renderElement({ id: "value", wrap: false }) })] }))] }));
|
|
9142
9520
|
});
|
|
9143
9521
|
|
|
9522
|
+
/**
|
|
9523
|
+
* Контекст, через который элемент `chart` сообщает контейнеру, где лежит поле графика.
|
|
9524
|
+
*
|
|
9525
|
+
* По макету подпись оси X и легенда выравниваются по полю графика, а не по краям контейнера.
|
|
9526
|
+
* Ширину шкал d3 вычисляет только при отрисовке, а подвал с подписью и легендой рисует
|
|
9527
|
+
* `ChartContainer` — снаружи элемента. Без контейнера (элемент сам по себе) провайдера нет,
|
|
9528
|
+
* и отчёт просто не отправляется.
|
|
9529
|
+
*/
|
|
9530
|
+
const ChartPlotContext = createContext({});
|
|
9531
|
+
|
|
9144
9532
|
/**
|
|
9145
9533
|
* Контекст вписывания графика (`options.fill` контейнера Chart).
|
|
9146
9534
|
*
|
|
@@ -9150,14 +9538,43 @@ const CameraContainer = memo(({ elementConfig, type, renderElement }) => {
|
|
|
9150
9538
|
*/
|
|
9151
9539
|
const FillContext = createContext({ fill: false, fitHeight: false });
|
|
9152
9540
|
|
|
9541
|
+
const isSameInsets = (prev, next) => !!prev && prev.left === next.left && prev.right === next.right && prev.width === next.width;
|
|
9153
9542
|
const ChartContainer = memo(({ elementConfig, isVisible, type, renderElement }) => {
|
|
9154
9543
|
const { options, children } = elementConfig || {};
|
|
9155
|
-
const { twoColumns, hideEmpty, height } = options || {};
|
|
9544
|
+
const { twoColumns, hideEmpty, height, legendInline } = options || {};
|
|
9156
9545
|
const fill = options?.fill;
|
|
9157
9546
|
const fillContextValue = useMemo(() => ({ fill: !!fill, fitHeight: !!fill && height != null }), [fill, height]);
|
|
9547
|
+
// Поле графика отчитывается после каждой отрисовки d3; одинаковые значения не пишем в стейт,
|
|
9548
|
+
// иначе отчёт и ре-рендер гоняли бы друг друга.
|
|
9549
|
+
const [plotInsets, setPlotInsets] = useState(null);
|
|
9550
|
+
const reportPlotInsets = useCallback((next) => setPlotInsets(prev => (isSameInsets(prev, next) ? prev : next)), []);
|
|
9551
|
+
const plotContextValue = useMemo(() => ({ reportPlotInsets }), [reportPlotInsets]);
|
|
9158
9552
|
const aliasElement = children.find(child => child.id === "alias");
|
|
9159
9553
|
const chartElement = children.find(child => child.id === "chart");
|
|
9160
9554
|
const legendElement = children.find(child => child.id === "legend");
|
|
9555
|
+
const isLineChart = chartElement?.options?.chartType === "line";
|
|
9556
|
+
// Подпись оси X — часть макета осей линейного графика, как и подписи осей Y в `Chart`. У других типов
|
|
9557
|
+
// её нет, даже если она осталась в конфиге после смены типа: редактор показывает настройки осей только
|
|
9558
|
+
// линейному графику, и убрать там такую подпись было бы нечем.
|
|
9559
|
+
const xAxisTitle = useMemo(() => (isLineChart ? chartElement?.options?.axis?.x?.title : undefined), [isLineChart, chartElement?.options?.axis?.x?.title]);
|
|
9560
|
+
const footerJustify = useMemo(() => CHART_AXIS_ALIGN_JUSTIFY[chartElement?.options?.axis?.x?.align ?? "center"], [chartElement?.options?.axis?.x?.align]);
|
|
9561
|
+
// Легенда встаёт в строку с подписью оси X только когда та есть и легенда не вынесена вбок.
|
|
9562
|
+
const isLegendInline = useMemo(() => !!legendInline && !twoColumns && !!xAxisTitle, [legendInline, twoColumns, xAxisTitle]);
|
|
9563
|
+
// По макету подпись оси X и легенда у линейного графика выравниваются по полю графика, а не по
|
|
9564
|
+
// контейнеру. Легенда сбоку (twoColumns) живёт в своей колонке и в выравнивании не участвует.
|
|
9565
|
+
const footerInsets = useMemo(() => (isLineChart ? plotInsets : null), [isLineChart, plotInsets]);
|
|
9566
|
+
const isPlotLegend = isLineChart && !twoColumns;
|
|
9567
|
+
// Положение поля становится известно только после отрисовки: LineChart рисует d3 в useEffect, уже
|
|
9568
|
+
// после первого кадра. До отчёта подвал встал бы по краю контейнера и затем прыгнул на место, поэтому
|
|
9569
|
+
// прячем его — место под ним сохраняется, а появляется он вместе с линиями графика.
|
|
9570
|
+
const isAwaitingPlot = isLineChart && !plotInsets;
|
|
9571
|
+
// Пока подпись оси X не задана, легенда выравнивается прежней опцией `center` (по умолчанию — к левой
|
|
9572
|
+
// границе поля графика); с подписью — по ней, иначе подпись и легенда разъезжаются по разным краям.
|
|
9573
|
+
const legendJustify = useMemo(() => {
|
|
9574
|
+
if (xAxisTitle)
|
|
9575
|
+
return footerJustify;
|
|
9576
|
+
return legendElement?.options?.center ? "center" : "flex-start";
|
|
9577
|
+
}, [xAxisTitle, footerJustify, legendElement?.options?.center]);
|
|
9161
9578
|
const { root, body } = useContainerRoot({ elementConfig });
|
|
9162
9579
|
const { data, loading } = useChartData({
|
|
9163
9580
|
element: chartElement,
|
|
@@ -9169,7 +9586,12 @@ const ChartContainer = memo(({ elementConfig, isVisible, type, renderElement })
|
|
|
9169
9586
|
const hasItems = !!data[0]?.items?.length;
|
|
9170
9587
|
if (!loading && !hasItems && hideEmpty)
|
|
9171
9588
|
return null;
|
|
9172
|
-
|
|
9589
|
+
const chartSlot = (jsx(ContainerChart, { "$fill": !!fill, children: jsx(FillContext.Provider, { value: fillContextValue, children: jsx(ChartPlotContext.Provider, { value: plotContextValue, children: renderElement({ id: "chart" }) }) }) }));
|
|
9590
|
+
const footer = xAxisTitle ? (jsxs(ChartFooter, { "$align": footerJustify, "$insets": footerInsets, "$offsetTop": X_AXIS_TITLE_GAP - LINE_CHART_X_LABELS_BLANK, "$awaitingPlot": isAwaitingPlot, children: [jsx(ChartXAxisTitle, { children: xAxisTitle }), isLegendInline && jsx(ContainerLegend, { children: renderElement({ id: "legend" }) })] })) : null;
|
|
9591
|
+
// Легенда линейного графика: под подписью оси X — через X_AXIS_TITLE_LEGEND_GAP, без подписи — на её
|
|
9592
|
+
// месте, вплотную под подписями делений оси X. У остальных графиков — прежняя раскладка общей легенды.
|
|
9593
|
+
const legendRow = isLegendInline ? null : (jsx(ChartLegendRow, { justifyContent: legendJustify, "$insets": isPlotLegend ? footerInsets : null, "$gapTop": isPlotLegend ? (xAxisTitle ? X_AXIS_TITLE_LEGEND_GAP : 0) : undefined, "$offsetTop": isPlotLegend && !xAxisTitle ? X_AXIS_TITLE_GAP - LINE_CHART_X_LABELS_BLANK : undefined, "$justify": isPlotLegend ? legendJustify : undefined, "$awaitingPlot": isPlotLegend && isAwaitingPlot, children: renderElement({ id: "legend" }) }));
|
|
9594
|
+
return (jsxs(ContainerRoot, { ...root, children: [jsx(ContainerBackground, { elementConfig: elementConfig, renderElement: renderElement }), jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxs(Container, { ...body, isColumn: true, children: [aliasElement && jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsx(ContainerValue, { column: !twoColumns, alignItems: twoColumns && fill ? "stretch" : "center", "$fill": !!fill, children: hasItems ? (jsxs(Fragment$1, { children: [twoColumns && footer ? (jsxs(ChartWithFooter, { "$fill": !!fill, children: [chartSlot, footer] })) : (jsxs(Fragment$1, { children: [chartSlot, footer] })), legendRow] })) : (jsx(Fragment$1, { children: "\u2014" })) })] }))] }));
|
|
9173
9595
|
});
|
|
9174
9596
|
|
|
9175
9597
|
const InnerContainerWrapper = styled.div.withConfig({ displayName: "InnerContainerWrapper", componentId: "sc-1a1fl7q" }) `
|
|
@@ -9527,6 +9949,7 @@ const DEFAULT_BAR_CHART_HEIGHT = 100;
|
|
|
9527
9949
|
const BAR_CHART_HEADER_HEIGHT = 40;
|
|
9528
9950
|
const BAR_CHART_FOOTER_MARGIN = 16;
|
|
9529
9951
|
const LINE_CHART_LABEL_MARGIN = 20;
|
|
9952
|
+
const LINE_CHART_X_AXIS_PADDING = 15;
|
|
9530
9953
|
const DEFAULT_BAR_CHART_MARGINS = {
|
|
9531
9954
|
top: 0,
|
|
9532
9955
|
left: 0,
|
|
@@ -10925,6 +11348,13 @@ const StyledSvg = styled(Flex).withConfig({ displayName: "StyledSvg", componentI
|
|
|
10925
11348
|
${({ $fontColor }) => !!$fontColor && StyledSvgColorMixin};
|
|
10926
11349
|
`;
|
|
10927
11350
|
|
|
11351
|
+
const AttachmentIconImg = styled.img.withConfig({ displayName: "AttachmentIconImg", componentId: "sc-1qtgzdf" }) `
|
|
11352
|
+
flex-shrink: 0;
|
|
11353
|
+
width: ${({ $size }) => $size}px;
|
|
11354
|
+
height: ${({ $size }) => $size}px;
|
|
11355
|
+
object-fit: contain;
|
|
11356
|
+
`;
|
|
11357
|
+
|
|
10928
11358
|
const ContainerIconValue = styled(Flex).withConfig({ displayName: "ContainerIconValue", componentId: "sc-1adlcb4" }) ``;
|
|
10929
11359
|
/**
|
|
10930
11360
|
* Обёртка иконки плитки. Собственный styled нужен, чтобы до иконки можно было дотянуться стилями:
|
|
@@ -11029,6 +11459,12 @@ const RoundedBackgroundContainerWrapper = styled(Flex).withConfig({ displayName:
|
|
|
11029
11459
|
width: ${BIG_ICON_SIZE} !important;
|
|
11030
11460
|
height: ${BIG_ICON_SIZE} !important;
|
|
11031
11461
|
}
|
|
11462
|
+
|
|
11463
|
+
/* Растровая иконка из атрибута-вложения: её размер тоже задаёт контейнер. */
|
|
11464
|
+
${AttachmentIconImg} {
|
|
11465
|
+
width: ${BIG_ICON_SIZE};
|
|
11466
|
+
height: ${BIG_ICON_SIZE};
|
|
11467
|
+
}
|
|
11032
11468
|
}
|
|
11033
11469
|
`};
|
|
11034
11470
|
|
|
@@ -15126,14 +15562,55 @@ const StyledIcon = styled(Icon).withConfig({ displayName: "StyledIcon", componen
|
|
|
15126
15562
|
${({ fontColor }) => !!fontColor && StyledIconFontColorMixin};
|
|
15127
15563
|
`;
|
|
15128
15564
|
|
|
15565
|
+
/** Размер иконки-вложения, px, когда в конфиге не задан `options.fontSize`. */
|
|
15566
|
+
const ATTACHMENT_ICON_DEFAULT_SIZE = 16;
|
|
15567
|
+
|
|
15568
|
+
/**
|
|
15569
|
+
* Иконка из значения атрибута-вложения: первое изображение списка, остальные файлы пропускаются.
|
|
15570
|
+
* Значение приходит JSON-строкой с сервера или массивом после правки — `parseAttachments` понимает оба.
|
|
15571
|
+
* SVG помечается отдельно: его рисуют инлайном, чтобы перекрасить цветом иконки.
|
|
15572
|
+
*/
|
|
15573
|
+
const getAttachmentIcon = (value) => {
|
|
15574
|
+
const image = parseAttachments(value).find(({ mimeType, name }) => IMAGE_FILE_TYPES.includes(getFileType(mimeType, name)));
|
|
15575
|
+
if (!image)
|
|
15576
|
+
return null;
|
|
15577
|
+
return {
|
|
15578
|
+
url: getResourceUrl(image.link),
|
|
15579
|
+
name: image.name,
|
|
15580
|
+
isSvg: image.mimeType === SVG_MIME_TYPE,
|
|
15581
|
+
};
|
|
15582
|
+
};
|
|
15583
|
+
|
|
15584
|
+
/**
|
|
15585
|
+
* Иконка из атрибута-вложения. SVG рисуется инлайном и перекрашивается `fontColor`, как у ElementSvg;
|
|
15586
|
+
* растровый файл — картинкой как есть. Изображений среди вложений нет — не рендерится ничего.
|
|
15587
|
+
*/
|
|
15588
|
+
const AttachmentIcon = memo(({ value, fontSize, fontColor, style }) => {
|
|
15589
|
+
const icon = useMemo(() => getAttachmentIcon(value), [value]);
|
|
15590
|
+
const size = useMemo(() => Number(fontSize) || ATTACHMENT_ICON_DEFAULT_SIZE, [fontSize]);
|
|
15591
|
+
const rasterUrl = useMemo(() => (icon && !icon.isSvg ? icon.url : null), [icon]);
|
|
15592
|
+
const imageSrc = useFetchImageWithAuth(rasterUrl);
|
|
15593
|
+
if (!icon)
|
|
15594
|
+
return null;
|
|
15595
|
+
if (icon.isSvg) {
|
|
15596
|
+
return jsx(SvgImage, { url: icon.url, width: size, height: size, fontColor: fontColor });
|
|
15597
|
+
}
|
|
15598
|
+
if (!imageSrc)
|
|
15599
|
+
return null;
|
|
15600
|
+
return jsx(AttachmentIconImg, { src: imageSrc, alt: icon.name, style: style, "$size": size });
|
|
15601
|
+
});
|
|
15602
|
+
|
|
15129
15603
|
const ElementIcon = memo(({ type, elementConfig, ...rest }) => {
|
|
15130
15604
|
const ctx = useWidgetContext(type);
|
|
15131
15605
|
const attributes = rest.attributes || ctx.attributes;
|
|
15132
15606
|
const { value, attributeName, options, style } = elementConfig || {};
|
|
15133
15607
|
const { fontSize, fontColor } = options || {};
|
|
15134
|
-
const
|
|
15135
|
-
|
|
15136
|
-
|
|
15608
|
+
const attribute = useMemo(() => (attributeName ? getAttributeByName(attributeName, attributes) : undefined), [attributeName, attributes]);
|
|
15609
|
+
const iconValue = useMemo(() => (attributeName ? attribute?.value : value), [attributeName, attribute, value]);
|
|
15610
|
+
// Во вложениях лежит список файлов, а не имя глифа: иконкой становится первое изображение.
|
|
15611
|
+
if (attribute?.subType === StringSubType.Attachments) {
|
|
15612
|
+
return jsx(AttachmentIcon, { value: attribute.value, fontSize: fontSize, fontColor: fontColor, style: style });
|
|
15613
|
+
}
|
|
15137
15614
|
return (jsx(StyledIcon, { kind: iconValue, fontSize: fontSize, fontColor: fontColor, style: style }));
|
|
15138
15615
|
});
|
|
15139
15616
|
|
|
@@ -15190,9 +15667,9 @@ const ElementImage = memo(({ type, elementConfig }) => {
|
|
|
15190
15667
|
});
|
|
15191
15668
|
|
|
15192
15669
|
const ElementLegend = memo(({ type, element, elementConfig }) => {
|
|
15193
|
-
const { attributes,
|
|
15670
|
+
const { attributes, expandedContainers } = useWidgetContext(type);
|
|
15194
15671
|
const { options } = elementConfig || {};
|
|
15195
|
-
const { twoColumns, chartId, relatedDataSources, fontSize } = options || {};
|
|
15672
|
+
const { twoColumns, column, chartId, relatedDataSources, fontSize } = options || {};
|
|
15196
15673
|
const chartElement = useMemo(() => returnFound(element?.children, { id: chartId }), [chartId, element?.children]);
|
|
15197
15674
|
const { data, loading } = useChartData({
|
|
15198
15675
|
element: chartElement,
|
|
@@ -15203,10 +15680,10 @@ const ElementLegend = memo(({ type, element, elementConfig }) => {
|
|
|
15203
15680
|
if (!data[0]?.items?.length)
|
|
15204
15681
|
return [];
|
|
15205
15682
|
if (chartElement?.options?.chartType === "line") {
|
|
15206
|
-
return axes.map(
|
|
15683
|
+
return axes.map(related => {
|
|
15207
15684
|
return {
|
|
15208
|
-
name: alias,
|
|
15209
|
-
color:
|
|
15685
|
+
name: related.alias,
|
|
15686
|
+
color: resolveAxis(related).color,
|
|
15210
15687
|
};
|
|
15211
15688
|
});
|
|
15212
15689
|
}
|
|
@@ -15220,7 +15697,7 @@ const ElementLegend = memo(({ type, element, elementConfig }) => {
|
|
|
15220
15697
|
});
|
|
15221
15698
|
}, [data, chartElement?.options?.chartType, relatedDataSources, axes, attributes]);
|
|
15222
15699
|
return !chartElement?.options?.expanded ||
|
|
15223
|
-
expandedContainers?.[chartElement.id] ? (jsx(ChartLegend, { data: legendData, loading: loading, chartElement: chartElement, twoColumns: twoColumns, fontSize: fontSize, type: type })) : null;
|
|
15700
|
+
expandedContainers?.[chartElement.id] ? (jsx(ChartLegend, { data: legendData, loading: loading, chartElement: chartElement, twoColumns: twoColumns, column: column, fontSize: fontSize, type: type })) : null;
|
|
15224
15701
|
});
|
|
15225
15702
|
|
|
15226
15703
|
const ExternalLink = styled(IconButton).attrs(() => ({
|
|
@@ -16788,7 +17265,11 @@ const getDataFromRelatedFeatures = ({ t, config, filters, relatedConfig, dataSou
|
|
|
16788
17265
|
if (isOtherSliced) {
|
|
16789
17266
|
data = data.slice(0, config?.options?.otherItems);
|
|
16790
17267
|
}
|
|
16791
|
-
|
|
17268
|
+
// Источник чарта отличается от источника фильтра наличием осей: BarChartFilter собирает
|
|
17269
|
+
// relatedConfig вручную и оси не задаёт, потому что ему нужна исходная палитра, а не растянутая
|
|
17270
|
+
// под число элементов. Гейт смотрит и на устаревший chartAxis — иначе у старых конфигов
|
|
17271
|
+
// молча поехали бы цвета столбцов и долей.
|
|
17272
|
+
const gradientArray = hasAxisConfig(relatedConfig)
|
|
16792
17273
|
? stretchPalette(colors, data.length)
|
|
16793
17274
|
: colors;
|
|
16794
17275
|
const filter = getConfigFilter(relatedConfig?.filterName, filters);
|
|
@@ -18854,6 +19335,15 @@ const StackBar = ({ data, filterName, type, alias, options, fill, renderElement,
|
|
|
18854
19335
|
return (jsxs(Fragment$1, { children: [(alias || showTotal) && (jsxs(StackBarHeader, { children: [jsx(StackBarAlias, { children: renderElement({ id: "alias" }) }), showTotal && (jsxs(StackBarTotal, { children: [jsx(StackBarValue, { children: formatValue(total) }), !!units && jsx(StackBarUnits, { children: units })] }))] })), groupTooltip ? (jsx(Tooltip$1, { placement: "top", arrow: true, content: renderGroupTooltip, children: ref => (jsx(StackBarContainer, { ref: ref, "$fill": fill, children: renderItems })) })) : (jsx(StackBarContainer, { "$fill": fill, children: renderItems }))] }));
|
|
18855
19336
|
};
|
|
18856
19337
|
|
|
19338
|
+
/** Горизонтальные подписи осей над телом графика: левая прижата влево, правая — вправо. */
|
|
19339
|
+
const AxisTitlesTop = ({ left, right, neutralColor }) => (jsxs(AxisTitlesRow, { children: [jsx(AxisTitleTop, { "$color": left?.color || neutralColor, title: left?.title, children: left?.title }), jsx(AxisTitleTop, { "$color": right?.color || neutralColor, title: right?.title, children: right?.title })] }));
|
|
19340
|
+
/** Вертикальная подпись оси сбоку от тела графика. Без подписи ничего не рендерит. */
|
|
19341
|
+
const AxisTitleSideSlot = ({ side, axisTitle, neutralColor, plotTop, plotBottom, }) => {
|
|
19342
|
+
if (!axisTitle)
|
|
19343
|
+
return null;
|
|
19344
|
+
return (jsx(AxisTitleSideColumn, { "$side": side, "$plotTop": plotTop, "$plotBottom": plotBottom, children: jsx(AxisTitleSide, { "$side": side, "$color": axisTitle.color || neutralColor, title: axisTitle.title, children: axisTitle.title }) }));
|
|
19345
|
+
};
|
|
19346
|
+
|
|
18857
19347
|
const Chart = memo(({ config, element, elementConfig, type, renderElement }) => {
|
|
18858
19348
|
const theme = useTheme();
|
|
18859
19349
|
const { palette } = theme;
|
|
@@ -18874,12 +19364,18 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
18874
19364
|
const radius = options?.radius || DEFAULT_BARCHART_RADIUS;
|
|
18875
19365
|
const padding = options?.padding || DEFAULT_BAR_PADDING;
|
|
18876
19366
|
const fontColor = options?.fontColor || palette.iconDisabled;
|
|
19367
|
+
// Нейтральная подпись оси — тем же цветом, что и значения шкалы (на макете у них один стиль).
|
|
19368
|
+
const axisTitleColor = options?.fontColor || palette.textDisabled;
|
|
18877
19369
|
const angle = options?.angle || DEFAULT_CHART_ANGLE;
|
|
18878
19370
|
const barWidth = options?.barWidth || DEFAULT_BAR_WIDTH;
|
|
18879
19371
|
const cornerRadius = options?.cornerRadius || 0;
|
|
18880
19372
|
const relatedAttributes = useMemo(() => relatedDataSources || [], [relatedDataSources]);
|
|
18881
|
-
const axes = useMemo(() => relatedAttributes.filter(
|
|
19373
|
+
const axes = useMemo(() => relatedAttributes.filter(isValueAxis), [relatedAttributes]);
|
|
18882
19374
|
const filterName = getChartFilterName(relatedDataSources);
|
|
19375
|
+
const { axisTitles, hasTopTitles, hasSideTitles, axisTitlesHeight, hideLeftAxis, hideRightAxis, } = useChartAxisTitles({ options, axes, isLineChart });
|
|
19376
|
+
// Ширина вертикальных подписей зависит от числа строк текста, поэтому тело между ними меряем
|
|
19377
|
+
// по факту, а не вычитаем константу.
|
|
19378
|
+
const [lineBodyRef, { width: measuredBodyWidth }] = useResizeBox(hasSideTitles);
|
|
18883
19379
|
const isRelated = !!relatedAttributes?.length;
|
|
18884
19380
|
const { data, loading } = useChartData({ element, type });
|
|
18885
19381
|
const totalWidthFromBarWidth = (data[0]?.items?.length || 0) * (barWidth + padding);
|
|
@@ -18907,17 +19403,54 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
18907
19403
|
const chartHeight = useMemo(() => (fitsHeight && measuredHeight ? measuredHeight : height), [fitsHeight, measuredHeight, height]);
|
|
18908
19404
|
// Круглый график вписываем по короткой стороне (object-fit: contain), центрируя в ячейке.
|
|
18909
19405
|
const pieSide = useMemo(() => (fitsHeight && measuredHeight ? Math.min(chartWidth, measuredHeight) : chartWidth), [fitsHeight, measuredHeight, chartWidth]);
|
|
19406
|
+
// Тело линейного графика — это ячейка за вычетом подписей осей. По высоте вычитаем только в
|
|
19407
|
+
// fill: вне fill chartHeight означает высоту самого тела, и обёртка честно растёт на подписи.
|
|
19408
|
+
const lineBodyWidth = useMemo(() => {
|
|
19409
|
+
if (!hasSideTitles)
|
|
19410
|
+
return chartWidth;
|
|
19411
|
+
if (measuredBodyWidth)
|
|
19412
|
+
return measuredBodyWidth;
|
|
19413
|
+
// До первого замера — оценка: одна строка текста и зазор на каждую подпись.
|
|
19414
|
+
const sideTitlesCount = Number(!!axisTitles.left) + Number(!!axisTitles.right);
|
|
19415
|
+
return Math.max(chartWidth - sideTitlesCount * (AXIS_TITLE_LINE_HEIGHT + AXIS_TITLE_GAP), 0);
|
|
19416
|
+
}, [hasSideTitles, measuredBodyWidth, chartWidth, axisTitles]);
|
|
19417
|
+
const lineBodyHeight = useMemo(() => (fitsHeight ? Math.max(chartHeight - axisTitlesHeight, 0) : chartHeight), [fitsHeight, chartHeight, axisTitlesHeight]);
|
|
19418
|
+
// Обёртка выше тела на строку горизонтальных подписей. В fill вся высота уже отмерена ячейкой,
|
|
19419
|
+
// поэтому прибавлять нечего — иначе тело вылезло бы за нижнюю границу.
|
|
19420
|
+
const lineWrapperHeight = useMemo(() => (fitsHeight ? chartHeight : chartHeight + axisTitlesHeight), [fitsHeight, chartHeight, axisTitlesHeight]);
|
|
18910
19421
|
const [customize] = useChartChange({
|
|
18911
19422
|
dataSources: config.dataSources,
|
|
18912
19423
|
chartId: elementConfig?.id,
|
|
18913
|
-
width:
|
|
18914
|
-
height:
|
|
19424
|
+
width: lineBodyWidth,
|
|
19425
|
+
height: lineBodyHeight,
|
|
18915
19426
|
fontColor,
|
|
18916
19427
|
relatedAttributes,
|
|
18917
19428
|
defaultColor: primaryColor,
|
|
18918
19429
|
markers: configMarkers,
|
|
18919
19430
|
showMarkers,
|
|
18920
19431
|
});
|
|
19432
|
+
const { formatLeftTick, formatRightTick } = useChartAxisTickFormat({
|
|
19433
|
+
dataSources: config.dataSources,
|
|
19434
|
+
relatedAttributes,
|
|
19435
|
+
});
|
|
19436
|
+
const { reportPlotInsets } = useContext(ChartPlotContext);
|
|
19437
|
+
// Положение поля графика известно только после отрисовки: ширину шкал вычисляет d3. Смещение тела
|
|
19438
|
+
// берём из offset-размеров, а не из getBoundingClientRect: они не искажаются масштабом превью и
|
|
19439
|
+
// transform предков, а координаты шкалы всегда в пикселях SVG.
|
|
19440
|
+
const customizeLine = useCallback(args => {
|
|
19441
|
+
customize?.(args);
|
|
19442
|
+
const body = lineBodyRef.current;
|
|
19443
|
+
const layout = body?.parentElement?.parentElement;
|
|
19444
|
+
if (!reportPlotInsets || !body || !layout)
|
|
19445
|
+
return;
|
|
19446
|
+
const bodyLeft = body.offsetLeft - layout.offsetLeft;
|
|
19447
|
+
const [plotLeft, plotRight] = args.xScale.range();
|
|
19448
|
+
reportPlotInsets({
|
|
19449
|
+
left: Math.round(bodyLeft + plotLeft),
|
|
19450
|
+
right: Math.round(layout.offsetWidth - bodyLeft - plotRight),
|
|
19451
|
+
width: layout.offsetWidth,
|
|
19452
|
+
});
|
|
19453
|
+
}, [customize, reportPlotInsets, lineBodyRef]);
|
|
18921
19454
|
const { formatFilterColor, onFilter } = useWidgetFilters(type, filterName, data?.[0]?.items);
|
|
18922
19455
|
const formattedAttributes = useMemo(() => getFormattedAttributes(t, (data[0]?.items || []), attributes, element), [attributes, data, element, t]);
|
|
18923
19456
|
const totalSum = useMemo(() => isRelated
|
|
@@ -18976,6 +19509,17 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
18976
19509
|
left: markersMargin,
|
|
18977
19510
|
};
|
|
18978
19511
|
}, [showMarkers, markers?.length]);
|
|
19512
|
+
// Значения шкалы барчарта d3 центрирует на делении, и крайние деления наполовину выступают за поле.
|
|
19513
|
+
// При нулевом поле SVG выступ уходит за SVG, где его срезает BarChartContainer (overflow-x: hidden,
|
|
19514
|
+
// отчего и по вертикали содержимое не visible). Место под выступ резервируем внутри SVG — внешние
|
|
19515
|
+
// размеры обёрток не меняются. Без значений шкалы (showLabels) выступать нечему.
|
|
19516
|
+
const barMargin = useMemo(() => showLabels
|
|
19517
|
+
? {
|
|
19518
|
+
...margin,
|
|
19519
|
+
top: Math.max(margin.top, Y_AXIS_LABEL_OVERHANG),
|
|
19520
|
+
bottom: Math.max(margin.bottom, Y_AXIS_LABEL_OVERHANG),
|
|
19521
|
+
}
|
|
19522
|
+
: margin, [showLabels, margin]);
|
|
18979
19523
|
const formatTooltipName = useCallback((name) => isRelated ? name : tooltipNameFromAttributes(name, formattedAttributes), [formattedAttributes, isRelated]);
|
|
18980
19524
|
const formatTooltipValue = useCallback((value, name) => isRelated
|
|
18981
19525
|
? tooltipValueFromRelatedFeatures(t, value, relatedAttributes, data[0]?.layerInfo)
|
|
@@ -19002,26 +19546,42 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
19002
19546
|
attributeUnits: item.attributeUnits,
|
|
19003
19547
|
dataSourceName: item.dataSourceName,
|
|
19004
19548
|
stroke: item.color || primaryColor,
|
|
19549
|
+
axis: item.axisSide ?? "left",
|
|
19005
19550
|
values: item.items
|
|
19006
19551
|
?.filter(({ value }) => !isEmptyValue(value))
|
|
19007
19552
|
?.map(({ value }) => Number(value)),
|
|
19008
19553
|
}));
|
|
19009
|
-
const isHidedY =
|
|
19010
|
-
const
|
|
19011
|
-
.
|
|
19554
|
+
const isHidedY = hideLeftAxis && hideRightAxis;
|
|
19555
|
+
const valuesOfSide = (side) => lineChartData
|
|
19556
|
+
.filter(({ axis }) => axis === side)
|
|
19012
19557
|
.map(({ values }) => values)
|
|
19013
19558
|
.flat();
|
|
19559
|
+
const leftValues = valuesOfSide("left");
|
|
19560
|
+
const rightValues = valuesOfSide("right");
|
|
19014
19561
|
// Резервируем нижнюю полосу под подписи оси X: без неё ось прижата к нижней границе,
|
|
19015
19562
|
// подписи (сдвинутые на +16px) вылезают за тело и режутся overflow: hidden у ChartFillMeasure.
|
|
19563
|
+
// Сверху резервируем выступ верхнего деления шкалы: оно центрировано на линии сетки и при нулевом
|
|
19564
|
+
// поле наполовину уходит за SVG, где в fill его срезает overflow: hidden у ChartFillMeasure.
|
|
19565
|
+
const topOverhang = Math.max(Y_AXIS_LABEL_OVERHANG - margin.top, 0);
|
|
19016
19566
|
const lineMargin = {
|
|
19017
19567
|
...margin,
|
|
19568
|
+
top: margin.top + topOverhang,
|
|
19018
19569
|
bottom: Math.max(margin.bottom, LINE_CHART_LABEL_MARGIN),
|
|
19019
19570
|
};
|
|
19020
|
-
|
|
19021
|
-
|
|
19022
|
-
|
|
19023
|
-
|
|
19024
|
-
|
|
19571
|
+
// draw.ts вычитает верхнее поле и из нижней границы поля графика — компенсируем добавленное,
|
|
19572
|
+
// чтобы низ поля и зазор до подписей оси X остались на месте.
|
|
19573
|
+
const lineXAxisPadding = LINE_CHART_X_AXIS_PADDING - topOverhang;
|
|
19574
|
+
// Колонки вертикальных подписей повторяют поля SVG, чтобы подпись центрировалась по полю
|
|
19575
|
+
// графика, а не по всей высоте вместе с подписями оси X.
|
|
19576
|
+
const plotTop = lineMargin.top;
|
|
19577
|
+
const plotBottom = lineMargin.top + lineMargin.bottom + lineXAxisPadding;
|
|
19578
|
+
return (jsxs(AnyChartWrapper, { height: lineWrapperHeight, children: [jsx(LineChartStyles, {}), jsxs(LineChartLayout, { children: [hasTopTitles && (jsx(AxisTitlesTop, { left: axisTitles.left, right: axisTitles.right, neutralColor: axisTitleColor })), jsxs(LineChartRow, { children: [hasSideTitles && (jsx(AxisTitleSideSlot, { side: "left", axisTitle: axisTitles.left, neutralColor: axisTitleColor, plotTop: plotTop, plotBottom: plotBottom })), jsx(LineChartBody, { ref: lineBodyRef, children: jsx(LineChart, { data: lineChartData, labels: labels, markers: markers, width: lineBodyWidth, height: lineBodyHeight, xAxisPadding: lineXAxisPadding, yAxisPadding: 0, min: leftValues.length ? Math.min(...leftValues) : undefined, rightMin: rightValues.length ? Math.min(...rightValues) : undefined, customYAxisSelection: yAxis => {
|
|
19579
|
+
// Обе оси приходят в один колбэк, поэтому сторону определяем по классу.
|
|
19580
|
+
const isRight = yAxis.classed(lineChartClassNames.lineChartYScaleRight);
|
|
19581
|
+
if (isRight ? hideRightAxis : hideLeftAxis) {
|
|
19582
|
+
yAxis.remove();
|
|
19583
|
+
}
|
|
19584
|
+
}, customYAxis: yAxis => yAxis.ticks(LINE_CHART_Y_TICKS).tickFormat(formatLeftTick), customYAxisRight: yAxis => yAxis.ticks(LINE_CHART_Y_TICKS).tickFormat(formatRightTick), renderTooltip: renderLineChartTooltip, customize: customizeLine, dotSnapping: dotSnapping, dynamicTooltipEnable: true, stackedTooltip: true, tooltipClassName: "dashboardLineChartTooltip", drawGridX: !isHidedY, margin: lineMargin }) }), hasSideTitles && (jsx(AxisTitleSideSlot, { side: "right", axisTitle: axisTitles.right, neutralColor: axisTitleColor, plotTop: plotTop, plotBottom: plotBottom }))] })] })] }));
|
|
19025
19585
|
}
|
|
19026
19586
|
if (isStackBar) {
|
|
19027
19587
|
// Вне fill chartHeight — высота самой полосы, и обёртка честно становится выше на строку
|
|
@@ -19051,7 +19611,7 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
19051
19611
|
const barRadius = options?.cornerRadius ?? DEFAULT_BARCHART_RADIUS;
|
|
19052
19612
|
bars.attr("rx", barRadius);
|
|
19053
19613
|
bars.attr("ry", barRadius);
|
|
19054
|
-
}, margin:
|
|
19614
|
+
}, margin: barMargin, xAxisPadding: 0, yAxisPadding: 0, formatTooltipValue: formatTooltipValue, formatTooltipName: formatTooltipName, hideTooltipGroupName: true, dynamicTooltipEnable: true, isBarTooltip: true, onBarClick: filterName ? item => onFilter(item.name) : undefined }) }) }));
|
|
19055
19615
|
}, [
|
|
19056
19616
|
customXAxisBottom,
|
|
19057
19617
|
customYAxisLeft,
|
|
@@ -19067,6 +19627,15 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
19067
19627
|
formatFilterColor,
|
|
19068
19628
|
chartWidth,
|
|
19069
19629
|
chartHeight,
|
|
19630
|
+
lineBodyWidth,
|
|
19631
|
+
lineBodyHeight,
|
|
19632
|
+
lineWrapperHeight,
|
|
19633
|
+
axisTitles,
|
|
19634
|
+
hasTopTitles,
|
|
19635
|
+
hasSideTitles,
|
|
19636
|
+
axisTitleColor,
|
|
19637
|
+
hideLeftAxis,
|
|
19638
|
+
hideRightAxis,
|
|
19070
19639
|
fitsHeight,
|
|
19071
19640
|
pieSide,
|
|
19072
19641
|
fill,
|
|
@@ -19076,11 +19645,14 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
19076
19645
|
formatTooltipValue,
|
|
19077
19646
|
formatTooltipName,
|
|
19078
19647
|
filterName,
|
|
19079
|
-
axes,
|
|
19080
19648
|
labels,
|
|
19081
19649
|
margin,
|
|
19650
|
+
barMargin,
|
|
19082
19651
|
renderLineChartTooltip,
|
|
19083
|
-
|
|
19652
|
+
customizeLine,
|
|
19653
|
+
lineBodyRef,
|
|
19654
|
+
formatLeftTick,
|
|
19655
|
+
formatRightTick,
|
|
19084
19656
|
primaryColor,
|
|
19085
19657
|
type,
|
|
19086
19658
|
elementConfig?.children,
|
|
@@ -19097,14 +19669,14 @@ const Chart = memo(({ config, element, elementConfig, type, renderElement }) =>
|
|
|
19097
19669
|
]);
|
|
19098
19670
|
if (!isVisibleContainer(id, expandable, expanded, expandedContainers))
|
|
19099
19671
|
return null;
|
|
19100
|
-
const chartBody = (jsxs(ChartWrapper, { width: isPieChart && fill ? pieSide : width, height: isStackBar ? "auto" : isPieChart ? (fill ? pieSide : width) : chartHeight, column: column, loading: loading, children: [jsx(ChartTooltipStyles, {}), renderChart] }));
|
|
19672
|
+
const chartBody = (jsxs(ChartWrapper, { width: isPieChart && fill ? pieSide : width, height: isStackBar ? "auto" : isPieChart ? (fill ? pieSide : width) : isLineChart ? lineWrapperHeight : chartHeight, column: column, loading: loading, children: [jsx(ChartTooltipStyles, {}), renderChart] }));
|
|
19101
19673
|
if (!fill)
|
|
19102
19674
|
return chartBody;
|
|
19103
19675
|
// fill: тело центрируется в измеряемой обёртке, ref которой питает ResizeObserver обеими осями.
|
|
19104
19676
|
return jsx(ChartFillMeasure, { ref: chartRef, children: chartBody });
|
|
19105
19677
|
});
|
|
19106
19678
|
|
|
19107
|
-
const ChartLegend = ({ data, chartElement, fontSize, type, twoColumns, loading }) => {
|
|
19679
|
+
const ChartLegend = ({ data, chartElement, fontSize, type, twoColumns, column, loading }) => {
|
|
19108
19680
|
const { t } = useGlobalContext();
|
|
19109
19681
|
const { sliceItems, showMore, onShowMore } = useShownOtherItems(chartElement?.options);
|
|
19110
19682
|
const axes = useMemo(() => getChartAxes(chartElement), [chartElement]);
|
|
@@ -19113,7 +19685,7 @@ const ChartLegend = ({ data, chartElement, fontSize, type, twoColumns, loading }
|
|
|
19113
19685
|
const showMoreBtn = !!shownItems && data.length > shownItems;
|
|
19114
19686
|
if (!loading && !data?.length && !!hideEmpty)
|
|
19115
19687
|
return null;
|
|
19116
|
-
return (jsxs(Flex, { flexDirection: "column", opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: [jsx(ChartLegendContainer, { twoColumns: twoColumns, children: sliceItems(data)?.map(({ name, color }, index) => (jsxs(ChartLegendItem, { hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: axes?.[0]?.filterName ? () => onFilter(name) : undefined, children: [jsx(ChartLegendColor, { color: color }), jsx(ChartLegendName, { "$fontSize": fontSize, "$fontColor": fontColor, children: name })] }, index))) }), showMoreBtn && (jsx(LegendToggler, { onClick: onShowMore, toggled: showMore, children: t("other", { ns: "dashboard", defaultValue: "Другое" }) }))] }));
|
|
19688
|
+
return (jsxs(Flex, { flexDirection: "column", opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: [jsx(ChartLegendContainer, { twoColumns: twoColumns, "$column": column, children: sliceItems(data)?.map(({ name, color }, index) => (jsxs(ChartLegendItem, { hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: axes?.[0]?.filterName ? () => onFilter(name) : undefined, children: [jsx(ChartLegendColor, { color: color }), jsx(ChartLegendName, { "$fontSize": fontSize, "$fontColor": fontColor, children: name })] }, index))) }), showMoreBtn && (jsx(LegendToggler, { onClick: onShowMore, toggled: showMore, children: t("other", { ns: "dashboard", defaultValue: "Другое" }) }))] }));
|
|
19117
19689
|
};
|
|
19118
19690
|
|
|
19119
19691
|
const ContainerChildren = memo(({ type, items, isColumn, isMain, renderElement }) => {
|
|
@@ -19968,5 +20540,5 @@ const DEFAULT_HEATMAP_STYLE = {
|
|
|
19968
20540
|
],
|
|
19969
20541
|
};
|
|
19970
20542
|
|
|
19971
|
-
export { ALIGNMENTS, ALIGN_ITEMS, ATTRIBUTE_ICON_ELEMENT_TYPES, AddButtonRow, AddFeatureButton, AddFeatureContainer, AlertIconContainer, AttachmentContainer, AttributeGalleryContainer, AttributeLabel, BASE_CONTAINER_STYLE, BG_IMAGE_SLOT_ID, BaseMapTheme, CHART_TYPES, COMPACT_FRACTION_DIGITS, CONFIG_PAGES_ID, CONFIG_PAGE_ID, CONTAINERS_GROUP_DEFAULTS, CONTAINER_BODY_ATTRIBUTE, CONTAINER_BODY_FILL_STYLE, CameraContainer, Chart, ChartContainer, ChartLegend, ChartLoading, Container, ContainerBackground, ContainerChildren, ContainerLoading, ContainerRoot, ContainerTemplate, ContainerWrapper, ContainersGroupContainer, DASHBOARD_OVERLAY_Z_INDEX, DEFAULT_ATTRIBUTE_NAME, DEFAULT_BARCHART_RADIUS, DEFAULT_BASE_MAP, DEFAULT_BLUR, DEFAULT_CHART_ANGLE, DEFAULT_CHART_HEIGHT, DEFAULT_CHART_WIDTH, DEFAULT_CIRCLE_RADIUS, DEFAULT_CIRCLE_STROKE_WIDTH, DEFAULT_CIRCLE_STYLE, DEFAULT_COLOR, DEFAULT_DASHBOARD_CONFIG, DEFAULT_DATA_SOURCE_LIMIT, DEFAULT_DROPDOWN_WIDTH, DEFAULT_FILL_EXTRUSION_BASE, DEFAULT_FILL_EXTRUSION_HEIGHT, DEFAULT_FILL_EXTRUSION_STYLE, DEFAULT_FILL_EXTRUSION_VERTICAL_GRADIENT, DEFAULT_FILL_STYLE, DEFAULT_FILTER_PADDING, DEFAULT_GRID_GAP, DEFAULT_HEATMAP_COLOR, DEFAULT_HEATMAP_INTENSITY, DEFAULT_HEATMAP_RADIUS, DEFAULT_HEATMAP_STYLE, DEFAULT_HEATMAP_WEIGHT, DEFAULT_ICON_ANCHOR, DEFAULT_ICON_OVERLAP, DEFAULT_ICON_PADDING, DEFAULT_ICON_ROTATE, DEFAULT_ICON_SIZE, DEFAULT_ID_ATTRIBUTE_NAME, DEFAULT_LAT, DEFAULT_LINE_CAP, DEFAULT_LINE_JOIN, DEFAULT_LINE_STYLE, DEFAULT_LINE_WIDTH, DEFAULT_LNG, DEFAULT_OPACITY, DEFAULT_PAGES_CONFIG, DEFAULT_PIECHART_RADIUS, DEFAULT_SYMBOL_COLOR, DEFAULT_SYMBOL_HALO_COLOR, DEFAULT_SYMBOL_PLACEMENT, DEFAULT_SYMBOL_SPACING, DEFAULT_SYMBOL_STYLE, DEFAULT_TEXT_ANCHOR, DEFAULT_TEXT_JUSTIFY, DEFAULT_TEXT_SIZE, DEFAULT_TEXT_TRANSFORM, DEFAULT_TRACK_FR, DEFAULT_TRANSLATE, DEFAULT_ZOOM, DRAG_THRESHOLD_PX, Dashboard, DashboardCheckbox, DashboardChip, DashboardContent, DashboardContext, DashboardDefaultHeader, DashboardHeader, DashboardLoading, DashboardPlaceholder, DashboardPlaceholderWrap, DashboardProvider, DashboardWrapper, DataSourceContainer, DataSourceError, DataSourceErrorContainer, DataSourceInnerContainer, DataSourceProgressContainer, DateFormat, DefaultAttributesContainer, DefaultHeaderContainer, DefaultHeaderWrapper, DividerContainer, EMPTY_DATA_SOURCE_LAYER_INFO, EXTENT_FILTER_NAME, EditGeometryType, ElementButton, ElementCamera, ElementChart, ElementChips, ElementControl, ElementIcon, ElementImage, ElementLegend, ElementLink, ElementMarkdown, ElementSlideshow, ElementSvg, ElementTable, ElementTooltip, ElementValueWrapper, ExpandableTitle, FEATURE_CARD_DEFAULT_COLORS, FEATURE_CARD_OTHER_COLOR, FILL_SIZE, FILTERED_VALUE_OPACITY, FILTER_PREFIX, FR_PRECISION, FeatureCardBackgroundHeader, FeatureCardButtons, FeatureCardContext, FeatureCardDefaultHeader, FeatureCardHeader, FeatureCardProvider, FeatureCardSlideshowHeader, FeatureCardTitle, FeatureControls, FeatureTitleContainer, FiltersContainer, GEOMETRY_ATTRIBUTE, GEOMETRY_FILTER_NAME, GRID_AUTO_FILL_DEFAULTS, GRID_CELL_ATTR, GRID_CELL_ID_PREFIX, GRID_DRAGGING_ATTR, GRID_DRAG_SOURCE_ATTR, GRID_DROP_TARGET_ATTR, GRID_FILL_DEFAULTS, GRID_ROW_ID_PREFIX, GlobalContext, GlobalProvider, GridRowContainer, HANDLE_BLEED_PX, Header, HeaderContainer, HeaderFontColorMixin, HeaderFrontView, HeaderTemplate, HeaderTitleContainer, HiddenTitleItems, IconContainer, ImageContainer, LEFT_PANEL_HEADER_HEIGHT, Layer, LayerDescription, LayerGroupList, LayerIcon, LayerIconContainer, LayerListContainer, LayerTree, LayersContainer, LayersListWrapper, LinearProgressContainer, LogTerminal, LogoContainer, MAP_VIEW_FILTER_NAMES, MAX_CHART_WIDTH, MAX_TRACKS, MIN_TRACK_PX, MIN_TRACK_RATIO, Map$1 as Map, MapContext, MapProvider, NON_TRACK_SLOT_IDS, NO_CELL_DRAG_SELECTOR, NO_CONTENT_VALUE, NUMERIC_ATTRIBUTE_TYPES, NoLiveSnapshotContainer, OBJECT_FITS, OVERFLOWS, OneColumnContainer, PIE_CHART_TOOLTIP_STYLE, POLL_SUBTASK_INTERVAL_MS, POLL_SUBTASK_TIMEOUT_MS, PROJECT_ALIAS_PROP, PROJECT_FILTER_NAME, PROJECT_NAME_PROP, PROJECT_PROPS, PROVIDER_PREFIX, PageNavigator, PageTitle, PageTitleContainer, PagesContainer, Pagination, PresentationHeader, PresentationHeaderButtons, PresentationHeaderTools, PresentationPanelContainer, PresentationPanelWrapper, PresentationWrapper, ProgressContainer, ProviderPrefix, QUERY_DESCRIPTION_CACHE_TTL, RESIZE_HANDLE_ATTR, ResizeHandle, RoundedBackgroundContainer, SAVE_HOOK_RESULT_DURATION, SERVER_NOTIFICATION_EVENT, STACK_BAR_TOTAL_HEIGHT, ScalingFactor, ServerNotificationsContext, ServerNotificationsProvider, SlideshowContainer, SmallPreviewContainer$1 as SmallPreviewContainer, SmallPreviewControl, SmallPreviewCounter, SmallPreviewImages, SmallPreviewLeft, SmallPreviewRight, StackBar, StructuredDataContainer, SvgImage, TILE_ALIGNMENTS, TIME_ZONE_FORMAT, TITLE_SLOT_IDS, TabsContainer, TextTrim, ThemeName, TitleContainer, TopContainer, TopContainerButtons, TwoColumnContainer, UploadContainer, VIEW_MODES, VoteContainer, WidgetType, ZOOM_FILTER_NAME, addDataSource, addDataSources, adjustColor, applyFiltersToCondition, applyQueryFilters, applyTreeFilterToCondition, applyVarsToCondition, asAttributeName, asChartId, asContainerId, asDataSourceName, asFilterName, asLayerName, asModalId, asResourceId, asTabId, buildGridTemplate, buildTrackTemplate, checkEqualOrIncludes, checkIsLoading, collectConfigIds, colorToHex, containsNodeId, createConfigLayer, createConfigPage, createGridCell, createGridIdFactory, createGridRow, createNewPageId, createSaveNotificationId, dateOptions, debounce, decimalOpacityToHex, enrichStyleItemsWithIds, enrichStyleModelsWithIds, eqlParametersToPayload, fetchQueryDescription, findAttributeInExpression, findCellContext, formatArea, formatAttributeValue, formatChartRelatedValue, formatConditionValue, formatDataSourceCondition, formatDate$1 as formatDate, formatElementValue, formatLength, formatNumber, formatPolygonMeasure, geometryToEwkt, getActualExtrusionHeight, getAttributeByName, getAttributeConfigurationByName, getAttributeIconElement, getAttributeIconUrl, getAttributeValue, getAttributesConfiguration, getAverageTrackSize, getChartAxes, getChartFilterName, getChartMarkers, getConfigFilter, getContainerComponent, getDashboardHeader, getDataFromAttributes, getDataFromRelatedFeatures, getDataSource, getDataSourceFilterValue, getDataSourceLayerInfo, getDate, getDefaultConfig, getDisplayTemplateNameFromAttribute, getElementValue, getFeatureAttributes, getFeatureCardHeader, getFilterComponent, getFilterSelectedItems, getFilterValue, getFormattedAttributes, getGradientColors, getImageUrl, getLayerClientStyle, getLayerInfo, getLayerInfoAttribute, getLayerInfoFromDataSources, getLayoutChildren, getMapViewDataSources, getModalsDataSources, getPagesFromConfig, getPagesFromProjectInfo, getProjectValue, getProxyService, getRelatedAttribute, getRenderElement, getResourceUrl, getRootElementId, getSelectedFilterValue, getShownItemsLimit, getSlideshowImages, getStyleAttributes, getSvgUrl, getTemplateNameFromAttribute, getThemeByName, getTotalFromAttributes, getTotalFromRelatedFeatures, getTrackSize, getTrackSizeKey, getTrackSizes, getWrapperSizeStyle, hasContainerBgImage, hexToRgba, isCrossOriginUrl, isEmptyElementValue, isEmptyValue, isFeaturesFilterValue, isFillSize, isFrSize, isGridNode, isHiddenEmptyValue, isHookActive, isLayerService, isNotValidSelectedTab, isNumeric, isObject, isProxyService, isRootOwningContainer, isTreeFilterValue, isVisibleContainer, mapNodeById, mergeAttributeConfigurations, metersPerPixel, noMarginMixin, numberOptions, parseFrValue, parseIconNames, parseIconNamesFromClientStyle, pieChartTooltipFromAttributes, pieChartTooltipFromRelatedFeatures, pointOptions, removeDataSource, removeTracks, replaceNodesByIds, rgbToHex, roundFr, roundTotalSum, setLayoutChildren, sizeCssMixin, sliceShownOtherItems, stretchPalette, timeOptions, toConditionsArray, toCssSize, toFrSize, toPxNumber, toRenderableValue, tooltipNameFromAttributes, tooltipValueFromAttributes, tooltipValueFromRelatedFeatures, transparentizeColor, updateDataSource, useAfterSave, useAppHeight, useAttachmentDownload, useAttachmentItems, useAttachmentPreviewImages, useAttachmentsView, useAutoCompleteControl, useBeforeSave, useBgImageHost, useChartChange, useChartData, useConfigDataSources, useContainerAttributes, useContainerRoot, useCurrentPageLayers, useCustomFeatureSelect, useDashboardHeader, useDataSourceLoading, useDataSources, useDebouncedCallback, useDiffPage, useEditGroupAttributes, useEqualTileWidth, useExpandableContainers, useExportPdf, useFeatureSaveHooks, useFetchImageWithAuth, useFetchWithAuth, useGetConfigLayer, useGlobalContext, useHeaderRender, useHideIfEmptyDataSource, useLayerHiddenAttributes, useLayerParams, useMapContext, useMapDraw, useMapImages, useMaxZoomTo, useProjectDashboardInit, usePythonSandbox, usePythonTask, useRedrawLayer, useRelatedDataSourceAttributes, useRemoteTask, useRenderElement, useResizeBox, useResizeDrag, useSavePrototypeBuilder, useServerNotificationsContext, useShownOtherItems, useToggle, useUpdateDataSource, useVisibleProjectItems, useWidgetConfig, useWidgetContext, useWidgetFilters, useWidgetPage, useWindowResize, useWrapperSize, useZoomToFeatures, useZoomToPoint, withTrackSize };
|
|
20543
|
+
export { ALIGNMENTS, ALIGN_ITEMS, ATTRIBUTE_ICON_ELEMENT_TYPES, AXIS_TITLE_GAP, AXIS_TITLE_LINE_HEIGHT, AXIS_TITLE_TOP_GRID_GAP, AXIS_TITLE_TOP_HEIGHT, AddButtonRow, AddFeatureButton, AddFeatureContainer, AlertIconContainer, AttachmentContainer, AttributeGalleryContainer, AttributeLabel, BASE_CONTAINER_STYLE, BG_IMAGE_SLOT_ID, BaseMapTheme, CHART_AXIS_ALIGN_JUSTIFY, CHART_TYPES, COMPACT_FRACTION_DIGITS, CONFIG_PAGES_ID, CONFIG_PAGE_ID, CONTAINERS_GROUP_DEFAULTS, CONTAINER_BODY_ATTRIBUTE, CONTAINER_BODY_FILL_STYLE, CameraContainer, Chart, ChartContainer, ChartLegend, ChartLoading, Container, ContainerBackground, ContainerChildren, ContainerLoading, ContainerRoot, ContainerTemplate, ContainerWrapper, ContainersGroupContainer, DASHBOARD_OVERLAY_Z_INDEX, DEFAULT_ATTRIBUTE_NAME, DEFAULT_BARCHART_RADIUS, DEFAULT_BASE_MAP, DEFAULT_BLUR, DEFAULT_CHART_ANGLE, DEFAULT_CHART_HEIGHT, DEFAULT_CHART_WIDTH, DEFAULT_CIRCLE_RADIUS, DEFAULT_CIRCLE_STROKE_WIDTH, DEFAULT_CIRCLE_STYLE, DEFAULT_COLOR, DEFAULT_DASHBOARD_CONFIG, DEFAULT_DATA_SOURCE_LIMIT, DEFAULT_DROPDOWN_WIDTH, DEFAULT_FILL_EXTRUSION_BASE, DEFAULT_FILL_EXTRUSION_HEIGHT, DEFAULT_FILL_EXTRUSION_STYLE, DEFAULT_FILL_EXTRUSION_VERTICAL_GRADIENT, DEFAULT_FILL_STYLE, DEFAULT_FILTER_PADDING, DEFAULT_GRID_GAP, DEFAULT_HEATMAP_COLOR, DEFAULT_HEATMAP_INTENSITY, DEFAULT_HEATMAP_RADIUS, DEFAULT_HEATMAP_STYLE, DEFAULT_HEATMAP_WEIGHT, DEFAULT_ICON_ANCHOR, DEFAULT_ICON_OVERLAP, DEFAULT_ICON_PADDING, DEFAULT_ICON_ROTATE, DEFAULT_ICON_SIZE, DEFAULT_ID_ATTRIBUTE_NAME, DEFAULT_LAT, DEFAULT_LINE_CAP, DEFAULT_LINE_JOIN, DEFAULT_LINE_STYLE, DEFAULT_LINE_WIDTH, DEFAULT_LNG, DEFAULT_OPACITY, DEFAULT_PAGES_CONFIG, DEFAULT_PIECHART_RADIUS, DEFAULT_SYMBOL_COLOR, DEFAULT_SYMBOL_HALO_COLOR, DEFAULT_SYMBOL_PLACEMENT, DEFAULT_SYMBOL_SPACING, DEFAULT_SYMBOL_STYLE, DEFAULT_TEXT_ANCHOR, DEFAULT_TEXT_JUSTIFY, DEFAULT_TEXT_SIZE, DEFAULT_TEXT_TRANSFORM, DEFAULT_TRACK_FR, DEFAULT_TRANSLATE, DEFAULT_ZOOM, DRAG_THRESHOLD_PX, Dashboard, DashboardCheckbox, DashboardChip, DashboardContent, DashboardContext, DashboardDefaultHeader, DashboardHeader, DashboardLoading, DashboardPlaceholder, DashboardPlaceholderWrap, DashboardProvider, DashboardWrapper, DataSourceContainer, DataSourceError, DataSourceErrorContainer, DataSourceInnerContainer, DataSourceProgressContainer, DateFormat, DefaultAttributesContainer, DefaultHeaderContainer, DefaultHeaderWrapper, DividerContainer, EMPTY_DATA_SOURCE_LAYER_INFO, EXTENT_FILTER_NAME, EditGeometryType, ElementButton, ElementCamera, ElementChart, ElementChips, ElementControl, ElementIcon, ElementImage, ElementLegend, ElementLink, ElementMarkdown, ElementSlideshow, ElementSvg, ElementTable, ElementTooltip, ElementValueWrapper, ExpandableTitle, FEATURE_CARD_DEFAULT_COLORS, FEATURE_CARD_OTHER_COLOR, FILL_SIZE, FILTERED_VALUE_OPACITY, FILTER_PREFIX, FR_PRECISION, FeatureCardBackgroundHeader, FeatureCardButtons, FeatureCardContext, FeatureCardDefaultHeader, FeatureCardHeader, FeatureCardProvider, FeatureCardSlideshowHeader, FeatureCardTitle, FeatureControls, FeatureTitleContainer, FiltersContainer, GEOMETRY_ATTRIBUTE, GEOMETRY_FILTER_NAME, GRID_AUTO_FILL_DEFAULTS, GRID_CELL_ATTR, GRID_CELL_ID_PREFIX, GRID_DRAGGING_ATTR, GRID_DRAG_SOURCE_ATTR, GRID_DROP_TARGET_ATTR, GRID_FILL_DEFAULTS, GRID_ROW_ID_PREFIX, GlobalContext, GlobalProvider, GridRowContainer, HANDLE_BLEED_PX, Header, HeaderContainer, HeaderFontColorMixin, HeaderFrontView, HeaderTemplate, HeaderTitleContainer, HiddenTitleItems, IconContainer, ImageContainer, LEFT_PANEL_HEADER_HEIGHT, LINE_CHART_X_LABELS_BLANK, LINE_CHART_Y_TICKS, Layer, LayerDescription, LayerGroupList, LayerIcon, LayerIconContainer, LayerListContainer, LayerTree, LayersContainer, LayersListWrapper, LinearProgressContainer, LogTerminal, LogoContainer, MAP_VIEW_FILTER_NAMES, MAX_CHART_WIDTH, MAX_TRACKS, MIN_TRACK_PX, MIN_TRACK_RATIO, Map$1 as Map, MapContext, MapProvider, NON_TRACK_SLOT_IDS, NO_CELL_DRAG_SELECTOR, NO_CONTENT_VALUE, NUMERIC_ATTRIBUTE_TYPES, NoLiveSnapshotContainer, OBJECT_FITS, OVERFLOWS, OneColumnContainer, PIE_CHART_TOOLTIP_STYLE, POLL_SUBTASK_INTERVAL_MS, POLL_SUBTASK_TIMEOUT_MS, PROJECT_ALIAS_PROP, PROJECT_FILTER_NAME, PROJECT_NAME_PROP, PROJECT_PROPS, PROVIDER_PREFIX, PageNavigator, PageTitle, PageTitleContainer, PagesContainer, Pagination, PresentationHeader, PresentationHeaderButtons, PresentationHeaderTools, PresentationPanelContainer, PresentationPanelWrapper, PresentationWrapper, ProgressContainer, ProviderPrefix, QUERY_DESCRIPTION_CACHE_TTL, RESIZE_HANDLE_ATTR, ResizeHandle, RoundedBackgroundContainer, SAVE_HOOK_RESULT_DURATION, SERVER_NOTIFICATION_EVENT, STACK_BAR_TOTAL_HEIGHT, ScalingFactor, ServerNotificationsContext, ServerNotificationsProvider, SlideshowContainer, SmallPreviewContainer$1 as SmallPreviewContainer, SmallPreviewControl, SmallPreviewCounter, SmallPreviewImages, SmallPreviewLeft, SmallPreviewRight, StackBar, StructuredDataContainer, SvgImage, TILE_ALIGNMENTS, TIME_ZONE_FORMAT, TITLE_SLOT_IDS, TabsContainer, TextTrim, ThemeName, TitleContainer, TopContainer, TopContainerButtons, TwoColumnContainer, UploadContainer, VIEW_MODES, VoteContainer, WidgetType, X_AXIS_TITLE_GAP, X_AXIS_TITLE_LEGEND_GAP, Y_AXIS_LABEL_OVERHANG, ZOOM_FILTER_NAME, addDataSource, addDataSources, adjustColor, applyFiltersToCondition, applyQueryFilters, applyTreeFilterToCondition, applyVarsToCondition, asAttributeName, asChartId, asContainerId, asDataSourceName, asFilterName, asLayerName, asModalId, asResourceId, asTabId, buildGridTemplate, buildTrackTemplate, checkEqualOrIncludes, checkIsLoading, collectConfigIds, colorToHex, containsNodeId, createConfigLayer, createConfigPage, createGridCell, createGridIdFactory, createGridRow, createNewPageId, createSaveNotificationId, dateOptions, debounce, decimalOpacityToHex, enrichStyleItemsWithIds, enrichStyleModelsWithIds, eqlParametersToPayload, fetchQueryDescription, findAttributeInExpression, findCellContext, formatArea, formatAttributeValue, formatChartRelatedValue, formatConditionValue, formatDataSourceCondition, formatDate$1 as formatDate, formatElementValue, formatLength, formatNumber, formatPolygonMeasure, geometryToEwkt, getActualExtrusionHeight, getAttributeByName, getAttributeConfigurationByName, getAttributeIconElement, getAttributeIconUrl, getAttributeValue, getAttributesConfiguration, getAverageTrackSize, getAxisSide, getChartAxes, getChartFilterName, getChartMarkers, getConfigFilter, getContainerComponent, getDashboardHeader, getDataFromAttributes, getDataFromRelatedFeatures, getDataSource, getDataSourceFilterValue, getDataSourceLayerInfo, getDate, getDefaultConfig, getDisplayTemplateNameFromAttribute, getElementValue, getFeatureAttributes, getFeatureCardHeader, getFilterComponent, getFilterSelectedItems, getFilterValue, getFormattedAttributes, getGradientColors, getImageUrl, getLayerClientStyle, getLayerInfo, getLayerInfoAttribute, getLayerInfoFromDataSources, getLayoutChildren, getMapViewDataSources, getModalsDataSources, getPagesFromConfig, getPagesFromProjectInfo, getProjectValue, getProxyService, getRelatedAttribute, getRenderElement, getResourceUrl, getRootElementId, getSelectedFilterValue, getShownItemsLimit, getSlideshowImages, getStyleAttributes, getSvgUrl, getTemplateNameFromAttribute, getThemeByName, getTotalFromAttributes, getTotalFromRelatedFeatures, getTrackSize, getTrackSizeKey, getTrackSizes, getWrapperSizeStyle, hasAxisConfig, hasContainerBgImage, hexToRgba, isCrossOriginUrl, isEmptyElementValue, isEmptyValue, isFeaturesFilterValue, isFillSize, isFrSize, isGridNode, isHiddenEmptyValue, isHookActive, isLayerService, isNotValidSelectedTab, isNumeric, isObject, isProxyService, isRightAxis, isRootOwningContainer, isTreeFilterValue, isValueAxis, isVisibleContainer, mapNodeById, mergeAttributeConfigurations, metersPerPixel, noMarginMixin, numberOptions, parseFrValue, parseIconNames, parseIconNamesFromClientStyle, pieChartTooltipFromAttributes, pieChartTooltipFromRelatedFeatures, pointOptions, removeDataSource, removeTracks, replaceNodesByIds, resolveAxis, rgbToHex, roundFr, roundTotalSum, setLayoutChildren, sizeCssMixin, sliceShownOtherItems, stretchPalette, timeOptions, toConditionsArray, toCssSize, toFrSize, toPxNumber, toRenderableValue, tooltipNameFromAttributes, tooltipValueFromAttributes, tooltipValueFromRelatedFeatures, transparentizeColor, updateDataSource, useAfterSave, useAppHeight, useAttachmentDownload, useAttachmentItems, useAttachmentPreviewImages, useAttachmentsView, useAutoCompleteControl, useBeforeSave, useBgImageHost, useChartAxisAttributes, useChartAxisTickFormat, useChartAxisTitles, useChartChange, useChartData, useConfigDataSources, useContainerAttributes, useContainerRoot, useCurrentPageLayers, useCustomFeatureSelect, useDashboardHeader, useDataSourceLoading, useDataSources, useDebouncedCallback, useDiffPage, useEditGroupAttributes, useEqualTileWidth, useExpandableContainers, useExportPdf, useFeatureSaveHooks, useFetchImageWithAuth, useFetchWithAuth, useGetConfigLayer, useGlobalContext, useHeaderRender, useHideIfEmptyDataSource, useLayerHiddenAttributes, useLayerParams, useMapContext, useMapDraw, useMapImages, useMaxZoomTo, useProjectDashboardInit, usePythonSandbox, usePythonTask, useRedrawLayer, useRelatedDataSourceAttributes, useRemoteTask, useRenderElement, useResizeBox, useResizeDrag, useSavePrototypeBuilder, useServerNotificationsContext, useShownOtherItems, useToggle, useUpdateDataSource, useVisibleProjectItems, useWidgetConfig, useWidgetContext, useWidgetFilters, useWidgetPage, useWindowResize, useWrapperSize, useZoomToFeatures, useZoomToPoint, withTrackSize };
|
|
19972
20544
|
//# sourceMappingURL=react.esm.js.map
|