@dexteel/mesf-core 7.21.0 → 7.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "7.21.0"
2
+ ".": "7.22.0"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [7.22.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.21.0...@dexteel/mesf-core-v7.22.0) (2026-05-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * **trendings-v2:** simplify chart layout ([114ea8f](https://github.com/dexteel/mesf-core-frontend/commit/114ea8fd2f5495f8ccc2d52bcff0bdb6d5202999))
9
+
3
10
  ## [7.21.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.20.1...@dexteel/mesf-core-v7.21.0) (2026-04-24)
4
11
 
5
12
 
package/dist/index.esm.js CHANGED
@@ -25,7 +25,7 @@ import DeleteIcon from '@mui/icons-material/Delete';
25
25
  import EditIcon from '@mui/icons-material/Edit';
26
26
  import FindInPageIcon from '@mui/icons-material/FindInPage';
27
27
  import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
28
- import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, ExpandLess, ExpandMore, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group as Group$1, Assignment, Chat, ViewList, Build, Settings as Settings$2, Code as Code$1, FastRewind, FastForward, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
28
+ import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, ExpandLess, ExpandMore, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group as Group$1, Assignment, Chat, ViewList, Build, Settings as Settings$2, Code as Code$1, KeyboardDoubleArrowLeft, KeyboardArrowLeft, KeyboardArrowRight, KeyboardDoubleArrowRight, Update, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
29
29
  import ContentCopyIcon from '@mui/icons-material/ContentCopy';
30
30
  import FormatListBulletedSharpIcon from '@mui/icons-material/FormatListBulletedSharp';
31
31
  import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
@@ -11861,9 +11861,9 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
11861
11861
  steppedLines: true,
11862
11862
  showLegend: false,
11863
11863
  showTooltip: true,
11864
- combinedView: false,
11864
+ combinedView: true,
11865
11865
  showToolbox: true,
11866
- showYAxisNames: true,
11866
+ showYAxisNames: false,
11867
11867
  });
11868
11868
  const [aggregationMode, setAggregationModeState] = useState("avg");
11869
11869
  // View management state
@@ -11999,12 +11999,13 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
11999
11999
  width: "100%",
12000
12000
  } },
12001
12001
  React__default.createElement(Grid2, null,
12002
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract"), size: "small" },
12003
- React__default.createElement(ChevronLeft, { fontSize: "medium", sx: { color: "black" } }))),
12002
+ React__default.createElement(Tooltip, { title: "Previous period", arrow: true },
12003
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract"), size: "small" },
12004
+ React__default.createElement(KeyboardDoubleArrowLeft, { fontSize: "medium", sx: { color: "black" } })))),
12004
12005
  React__default.createElement(Grid2, null,
12005
- React__default.createElement(Tooltip, { title: "Navigate backward 20%", arrow: true },
12006
+ React__default.createElement(Tooltip, { title: "Pan backward 20%", arrow: true },
12006
12007
  React__default.createElement(IconButton$1, { onClick: () => handlePartialDateNavigator("subtract"), size: "small" },
12007
- React__default.createElement(FastRewind, { fontSize: "medium", sx: { color: "black" } })))),
12008
+ React__default.createElement(KeyboardArrowLeft, { fontSize: "medium", sx: { color: "black" } })))),
12008
12009
  React__default.createElement(Grid2, { size: { md: 3.5 } },
12009
12010
  React__default.createElement(LocalizationProvider$1, { dateAdapter: AdapterMoment },
12010
12011
  React__default.createElement(DateTimePicker, { label: "Start", format: "MM/DD/YYYY HH:mm:ss", value: moment$g(timeScopeStart), onChange: (newValue) => {
@@ -12042,15 +12043,17 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12042
12043
  },
12043
12044
  }, disabled: autoRefresh }))),
12044
12045
  React__default.createElement(Grid2, null,
12045
- React__default.createElement(Tooltip, { title: "Navigate forward 20%", arrow: true },
12046
+ React__default.createElement(Tooltip, { title: "Pan forward 20%", arrow: true },
12046
12047
  React__default.createElement(IconButton$1, { onClick: () => handlePartialDateNavigator("add"), size: "small" },
12047
- React__default.createElement(FastForward, { fontSize: "medium", sx: { color: "black" } })))),
12048
+ React__default.createElement(KeyboardArrowRight, { fontSize: "medium", sx: { color: "black" } })))),
12048
12049
  React__default.createElement(Grid2, null,
12049
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("add"), size: "small" },
12050
- React__default.createElement(ChevronRight, { fontSize: "medium", sx: { color: "black" } }))),
12050
+ React__default.createElement(Tooltip, { title: "Next period", arrow: true },
12051
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("add"), size: "small" },
12052
+ React__default.createElement(KeyboardDoubleArrowRight, { fontSize: "medium", sx: { color: "black" } })))),
12051
12053
  React__default.createElement(Grid2, null,
12052
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract", true), size: "small" },
12053
- React__default.createElement(SkipNext, { fontSize: "medium", sx: { color: "black" } }))))),
12054
+ React__default.createElement(Tooltip, { title: "Jump to current time", arrow: true },
12055
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract", true), size: "small" },
12056
+ React__default.createElement(Update, { fontSize: "medium", sx: { color: "black" } })))))),
12054
12057
  React__default.createElement(Grid2, { size: { md: 5, sm: 6, xs: 12 } },
12055
12058
  React__default.createElement(Paper, { elevation: 0, sx: {
12056
12059
  p: 1,
@@ -12062,7 +12065,7 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12062
12065
  alignItems: "stretch",
12063
12066
  justifyContent: "space-between",
12064
12067
  } },
12065
- React__default.createElement(Box, { sx: { width: 230 } },
12068
+ React__default.createElement(Box, { sx: { width: 155 } },
12066
12069
  React__default.createElement(FormControl, { fullWidth: true, size: "small" },
12067
12070
  React__default.createElement(Select, { multiple: true, value: [
12068
12071
  ...(customOptions.showGridLines ? ["grid"] : []),
@@ -12076,20 +12079,10 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12076
12079
  const selected = e.target.value;
12077
12080
  setCustomOptions((prevOptions) => (Object.assign(Object.assign({}, prevOptions), { showGridLines: selected.includes("grid"), showSymbols: selected.includes("symbols"), smoothLines: selected.includes("smooth") &&
12078
12081
  !selected.includes("stepped"), steppedLines: selected.includes("stepped"), showTooltip: selected.includes("tooltip"), showToolbox: selected.includes("toolbox"), showYAxisNames: selected.includes("yAxisNames") })));
12079
- }, renderValue: (selected) => {
12080
- const labels = {
12081
- grid: "Grid",
12082
- symbols: "Symbols",
12083
- smooth: "Smooth",
12084
- stepped: "Stepped",
12085
- tooltip: "Tooltip",
12086
- toolbox: "Toolbox",
12087
- yAxisNames: "Y-Axis Names",
12088
- };
12089
- return (React__default.createElement("span", { style: { fontSize: "0.75rem" } }, selected
12090
- .map((val) => labels[val])
12091
- .join(", ")));
12092
- } },
12082
+ }, renderValue: (selected) => (React__default.createElement("span", { style: { fontSize: "0.75rem" } },
12083
+ "Chart: ",
12084
+ selected.length,
12085
+ " options")) },
12093
12086
  React__default.createElement(MenuItem, { value: "grid", style: { padding: 0 } },
12094
12087
  React__default.createElement(Checkbox, { checked: customOptions.showGridLines, size: "small" }),
12095
12088
  React__default.createElement(ListItemText, null, "Grid")),
@@ -12115,16 +12108,14 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12115
12108
  React__default.createElement(FormControl, { fullWidth: true, size: "small" },
12116
12109
  React__default.createElement(Select, { value: aggregationMode, onChange: (e) => {
12117
12110
  setAggregationModeState(e.target.value);
12118
- }, renderValue: (selected) => selected === "last"
12119
- ? "Aggregation: Last value"
12120
- : "Aggregation: Average" },
12111
+ }, renderValue: (selected) => selected === "last" ? "Agg: Last" : "Agg: Avg" },
12121
12112
  React__default.createElement(MenuItem, { value: "avg" }, "Average"),
12122
12113
  React__default.createElement(MenuItem, { value: "last" }, "Last value")))),
12123
12114
  React__default.createElement(Divider, { orientation: "vertical", flexItem: true }),
12124
12115
  React__default.createElement(FormControlLabel, { checked: customOptions.combinedView, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Combined"), style: { margin: "0" }, onChange: (e, checked) => {
12125
12116
  setCustomOptions((prevOptions) => (Object.assign(Object.assign({}, prevOptions), { combinedView: checked })));
12126
12117
  } }),
12127
- React__default.createElement(FormControlLabel, { checked: autoRefresh, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Auto Refresh"), style: { margin: "0" }, onChange: (e, checked) => {
12118
+ React__default.createElement(FormControlLabel, { checked: autoRefresh, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Auto"), style: { margin: "0" }, onChange: (e, checked) => {
12128
12119
  if (checked) {
12129
12120
  // When enabling auto-refresh, set end to now
12130
12121
  // and keep the current period to calculate start
@@ -12143,8 +12134,12 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12143
12134
  setAutoRefresh(checked);
12144
12135
  } }),
12145
12136
  React__default.createElement(Divider, { orientation: "vertical", flexItem: true }),
12146
- React__default.createElement(Button, { variant: "outlined", size: "small", color: "primary", startIcon: React__default.createElement(ZoomIn, null), onClick: handleZoomIn, style: { fontSize: "0.7rem" } }, "Zoom"),
12147
- React__default.createElement(Button, { variant: "outlined", size: "small", color: "primary", startIcon: React__default.createElement(Restore, null), onClick: handleRestoreZoom, style: { fontSize: "0.7rem" } }, "Restore")))),
12137
+ React__default.createElement(Tooltip, { title: "Area zoom", arrow: true },
12138
+ React__default.createElement(IconButton$1, { color: "primary", onClick: handleZoomIn, size: "small" },
12139
+ React__default.createElement(ZoomIn, { fontSize: "small" }))),
12140
+ React__default.createElement(Tooltip, { title: "Restore zoom", arrow: true },
12141
+ React__default.createElement(IconButton$1, { color: "primary", onClick: handleRestoreZoom, size: "small" },
12142
+ React__default.createElement(Restore, { fontSize: "small" })))))),
12148
12143
  React__default.createElement(Grid2, { size: { md: 2, sm: 6, xs: 12 }, container: true, justifyContent: "flex-end", alignItems: "center" },
12149
12144
  React__default.createElement(Paper, { elevation: 0, sx: {
12150
12145
  p: 1,
@@ -14539,10 +14534,21 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14539
14534
  steppedLines: true,
14540
14535
  showLegend: true,
14541
14536
  showTooltip: true,
14542
- combinedView: false,
14537
+ combinedView: true,
14543
14538
  showToolbox: true,
14544
- showYAxisNames: true,
14539
+ showYAxisNames: false,
14545
14540
  };
14541
+ const getTagName = useCallback((tag) => tag.Alias || tag.TagName, []);
14542
+ const getActiveAxisTag = useCallback((tags) => {
14543
+ if (tags.length === 0)
14544
+ return null;
14545
+ if (highlightedSeries) {
14546
+ const highlightedTag = tags.find((tag) => tag.IsVisible && getTagName(tag) === highlightedSeries);
14547
+ if (highlightedTag)
14548
+ return highlightedTag;
14549
+ }
14550
+ return tags.find((tag) => tag.IsVisible) || null;
14551
+ }, [highlightedSeries, getTagName]);
14546
14552
  // Clear zoom state when time scope changes or combined view toggles
14547
14553
  useEffect(() => {
14548
14554
  const currentTimeScope = `${timeScopeStart.getTime()}-${timeScopeEnd.getTime()}`;
@@ -14561,13 +14567,14 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14561
14567
  prevCombinedViewRef.current = opts.combinedView;
14562
14568
  }, [timeScopeStart, timeScopeEnd, opts.combinedView]);
14563
14569
  // Helper to build yAxis config with scale settings
14564
- const buildYAxisConfig = useCallback((tag, gridIndex, position, offset = 0) => {
14570
+ const buildYAxisConfig = useCallback((tag, gridIndex, position, offset = 0, isAxisVisible = true) => {
14565
14571
  const baseConfig = {
14566
14572
  gridIndex,
14567
14573
  type: "value",
14568
- name: opts.showYAxisNames ? tag.Alias || tag.TagName : "",
14574
+ show: isAxisVisible,
14575
+ name: isAxisVisible && opts.showYAxisNames ? getTagName(tag) : "",
14569
14576
  nameLocation: "middle",
14570
- nameGap: 45 + offset,
14577
+ nameGap: 45,
14571
14578
  position,
14572
14579
  offset,
14573
14580
  splitNumber: 8, // Suggest 8 divisions, ECharts will adjust for readability
@@ -14577,21 +14584,24 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14577
14584
  fontWeight: "bold",
14578
14585
  },
14579
14586
  axisLine: {
14580
- show: true,
14587
+ show: isAxisVisible,
14581
14588
  lineStyle: {
14582
14589
  color: tag.Color,
14590
+ width: 2,
14583
14591
  },
14584
14592
  },
14585
14593
  axisTick: {
14586
- show: true,
14594
+ show: isAxisVisible,
14587
14595
  },
14588
14596
  axisLabel: {
14589
- show: true,
14597
+ show: isAxisVisible,
14590
14598
  color: tag.Color,
14591
14599
  fontSize: 10,
14592
14600
  },
14593
14601
  splitLine: {
14594
- show: position === "left" && offset === 0 ? opts.showGridLines : false,
14602
+ show: isAxisVisible && position === "left" && offset === 0
14603
+ ? opts.showGridLines
14604
+ : false,
14595
14605
  lineStyle: {
14596
14606
  color: "#e0e0e0",
14597
14607
  type: "solid",
@@ -14623,7 +14633,7 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14623
14633
  delete baseConfig.scale;
14624
14634
  }
14625
14635
  return baseConfig;
14626
- }, [opts.showGridLines, true, opts.showYAxisNames]);
14636
+ }, [opts.showGridLines, opts.showYAxisNames, getTagName]);
14627
14637
  // Determine if we should use separate grids (analog/digital)
14628
14638
  const useSeparateGrids = !opts.combinedView &&
14629
14639
  processedData.analogTags.length > 0 &&
@@ -14754,21 +14764,8 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14754
14764
  isUserDraggingRef.current = false;
14755
14765
  }, [handleCursor2Change]);
14756
14766
  const chartOptions = useMemo(() => {
14757
- // Calculate dynamic margins based on number of tags to ensure all Y-axes are visible
14758
- // Formula: Each pair of tags (left + right) needs 60px offset
14759
- // Base margin is 60px, then add 60px for each additional pair
14760
- const calculateMargin = (tagCount) => {
14761
- if (tagCount === 0)
14762
- return 60;
14763
- // Number of axes on each side (alternating left/right)
14764
- const axesPerSide = Math.ceil(tagCount / 2);
14765
- // Last axis offset = (axesPerSide - 1) * 60
14766
- // Total margin = last offset + base margin (60px)
14767
- return (axesPerSide - 1) * 60 + 60;
14768
- };
14769
- const analogMargin = calculateMargin(processedData.analogTags.length);
14770
- const digitalMargin = calculateMargin(processedData.digitalTags.length);
14771
- const combinedMargin = calculateMargin(processedData.analogTags.length + processedData.digitalTags.length);
14767
+ const chartLeftMargin = opts.showYAxisNames ? 96 : 72;
14768
+ const chartRightMargin = 32;
14772
14769
  return {
14773
14770
  animation: false,
14774
14771
  backgroundColor: "#fff",
@@ -14777,16 +14774,16 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14777
14774
  ? [
14778
14775
  {
14779
14776
  id: "analog",
14780
- left: `${analogMargin}px`,
14781
- right: `${analogMargin}px`,
14777
+ left: `${chartLeftMargin}px`,
14778
+ right: `${chartRightMargin}px`,
14782
14779
  top: opts.showLegend ? "70px" : "50px", // Increased to prevent cursor circle clipping
14783
14780
  bottom: "55%",
14784
14781
  containLabel: false,
14785
14782
  },
14786
14783
  {
14787
14784
  id: "digital",
14788
- left: `${digitalMargin}px`,
14789
- right: `${digitalMargin}px`,
14785
+ left: `${chartLeftMargin}px`,
14786
+ right: `${chartRightMargin}px`,
14790
14787
  top: "55%",
14791
14788
  bottom: 60,
14792
14789
  containLabel: false,
@@ -14795,8 +14792,8 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14795
14792
  : [
14796
14793
  {
14797
14794
  id: "combined",
14798
- left: `${combinedMargin}px`,
14799
- right: `${combinedMargin}px`,
14795
+ left: `${chartLeftMargin}px`,
14796
+ right: `${chartRightMargin}px`,
14800
14797
  top: opts.showLegend ? "70px" : "50px", // Increased to prevent cursor circle clipping
14801
14798
  bottom: 60,
14802
14799
  containLabel: false,
@@ -15023,34 +15020,25 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
15023
15020
  yAxis: (() => {
15024
15021
  const yAxisArray = [];
15025
15022
  if (useSeparateGrids) {
15026
- // Separate view with both analog and digital: analog in grid 0, digital in grid 1
15027
- // Add analog axes (grid 0)
15023
+ const activeAnalogTag = getActiveAxisTag(processedData.analogTags);
15024
+ const activeDigitalTag = getActiveAxisTag(processedData.digitalTags);
15028
15025
  processedData.analogTags.forEach((tag, idx) => {
15029
- const position = idx % 2 === 0 ? "left" : "right";
15030
- const offset = Math.floor(idx / 2) * 60;
15031
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15026
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeAnalogTag));
15032
15027
  });
15033
- // Add digital axes (grid 1)
15034
- processedData.digitalTags.forEach((tag, idx) => {
15035
- const position = idx % 2 === 0 ? "left" : "right";
15036
- const offset = Math.floor(idx / 2) * 60;
15037
- yAxisArray.push(buildYAxisConfig(tag, 1, position, offset));
15028
+ processedData.digitalTags.forEach((tag) => {
15029
+ yAxisArray.push(buildYAxisConfig(tag, 1, "left", 0, tag === activeDigitalTag));
15038
15030
  });
15039
15031
  }
15040
15032
  else {
15041
- // Combined view or only one type: all axes in grid 0
15042
- // Add analog axes
15043
- processedData.analogTags.forEach((tag, idx) => {
15044
- const position = idx % 2 === 0 ? "left" : "right";
15045
- const offset = Math.floor(idx / 2) * 60;
15046
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15033
+ const activeCombinedTag = getActiveAxisTag([
15034
+ ...processedData.analogTags,
15035
+ ...processedData.digitalTags,
15036
+ ]);
15037
+ processedData.analogTags.forEach((tag) => {
15038
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeCombinedTag));
15047
15039
  });
15048
- // Add digital axes
15049
- processedData.digitalTags.forEach((tag, idx) => {
15050
- const position = idx % 2 === 0 ? "left" : "right";
15051
- const baseOffset = Math.ceil(processedData.analogTags.length / 2) * 60;
15052
- const offset = baseOffset + Math.floor(idx / 2) * 60;
15053
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15040
+ processedData.digitalTags.forEach((tag) => {
15041
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeCombinedTag));
15054
15042
  });
15055
15043
  }
15056
15044
  // If no axes were created at all, add a default one to prevent errors
@@ -15239,6 +15227,7 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
15239
15227
  timeScopeStart,
15240
15228
  timeScopeEnd,
15241
15229
  buildYAxisConfig,
15230
+ getActiveAxisTag,
15242
15231
  zoomState,
15243
15232
  useSeparateGrids,
15244
15233
  ]);
@@ -15609,9 +15598,9 @@ const TrendingsPageV2 = () => {
15609
15598
  steppedLines: true,
15610
15599
  showLegend: false,
15611
15600
  showTooltip: true,
15612
- combinedView: false,
15601
+ combinedView: true,
15613
15602
  showToolbox: true,
15614
- showYAxisNames: true,
15603
+ showYAxisNames: false,
15615
15604
  });
15616
15605
  const [aggregationMode, setAggregationMode] = useState("avg");
15617
15606
  const [error, setError] = useState("");