@rfkit/charts 1.10.5 → 1.10.7

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/README.md CHANGED
@@ -94,6 +94,19 @@ export function GaugeDemo() {
94
94
  - `SetSegments`
95
95
  - `SetMarker`
96
96
 
97
+ `PublishDial` 支持推送 `series`、`range`、`yawAngle`、`isNorthFacing`,以及可选 `polygon: DialPolygon[]` 绘制雷达多边形:每个多边形提供 `values`(各方向归一化值 0-1,长度即方向数,按 0..360 度均匀分布)与可选 `color`(缺省走主题主色)。各方向值决定半径,连成闭合多边形,半透明填充 + 同色描边;`series` 已改为可选,纯雷达数据可以只传 `polygon`。
98
+
99
+ ```tsx
100
+ import { Dial, PSType, type Publish } from '@rfkit/charts';
101
+
102
+ const dialRef = useRef<Publish>(null);
103
+
104
+ dialRef.current?.({
105
+ pstype: PSType.Dial,
106
+ polygon: [{ values: [0.9, 0.6, 0.8, 0.45, 0.75, 0.5, 0.85, 0.7] }]
107
+ });
108
+ ```
109
+
97
110
  `PublishSpectrum` 支持推送内置频谱数据线,包括 `data`、`maxData`、`minData`、`avgData`、`thresholdData`、`templateData`、`backgroundNoiseData` 和 `extraData`。`thresholdData` 不传 `segmentOffset` / `offset` 时按整条门限替换;传入 `segmentOffset` 或 `offset` 时按局部门限写入。
98
111
 
99
112
  `extraData` 默认保持完整数组设置语义;设置 `segmentedExtraData: true` 后,同一次推送中的每条额外频谱线会独立使用 `segmentOffset + offset` 拼接,并随主实时值同步缩放。
@@ -111,11 +124,13 @@ publish({ pstype: PSType.Signal, type: SignalDataType.Station, data: station });
111
124
  publish({ pstype: PSType.Signal, type: SignalDataType.Simple, data: simple });
112
125
  ```
113
126
 
114
- 同一来源后续发布会替换上一批数据,发布空数组可单独清空该来源。频谱游标命中台站库时显示完整台站信息,命中信号库时显示来源、频率范围、带宽、类型,以及合法信号的等级。
127
+ 同一来源后续发布会替换上一批数据,发布空数组可单独清空该来源。`SignalData.details` 可传入 `name`、`organization`、`modulation` 和 `remark`;频谱游标命中台站库或信号库时会展示两者共有的详情,合法信号库数据额外显示等级。
128
+
129
+ 树形筛选默认在台站库、信号库、类型和等级节点后显示当前发布数据的数量;业务侧可通过 `signal={{ showCount: false }}` 关闭数量显示,筛选和数据本身不受影响。
115
130
 
116
131
  内置颜色直接复用主题的 `success`、`primary`、`warning`、`destructive` 和 `mutedForeground` 语义 token;需要整体调整时通过 `initChartsTheme({ tokens: { semantic: ... } })` 覆盖,单条业务标注仍使用 `color` 覆盖。
117
132
 
118
- 筛选树色点表示分类的内置语义色;单条数据传入 `color` 后,图上标注和游标详情色点使用该实际颜色,不会反向改变整类数据的树图例。
133
+ 筛选树与游标详情直接使用类型或等级文字表达颜色,不再额外显示色点。信号库的“合法”父级保持中性文字,具体等级文字与图上标注颜色一致;其他类型文字与对应标注颜色一致。单条数据传入 `color` 时仍保持最高优先级;`rgba(...)` 的透明度只作用于图上标注,文字使用相同 RGB 色相的不透明颜色保证可读性。
119
134
 
120
135
  台站数据需要提供 `startFrequency` / `stopFrequency`(也可以由 MHz 中心频率和 kHz 带宽在业务侧计算)。
121
136
 
package/index.d.ts CHANGED
@@ -6,9 +6,9 @@ export { setFrequencyAllocationChannelsToCache, setFrequencyAllocationToCache }
6
6
  export { type ChartsThemeChange, type InitChartsThemeOptions, type InitChartsThemeResult, initChartsTheme } from './theme/init-charts-theme';
7
7
  export { type ChartsThemePreference, type ChartsThemeState, getChartsThemeState, subscribeChartsThemeChange } from './theme/theme-runtime';
8
8
  export type { ChartsSizeTokensConfig, ChartsThemeTokensConfig } from './theme/theme-tokens';
9
- export type { AxisXProps, AxisYRange, BandProps, ChartRef, FrequencyAllocationChannel, FrequencyAllocationDensity, FrequencyAllocationItem, MarkerProps, MarkerType, Publish, PublishData, PublishDial, PublishGauge, PublishHeatmap, PublishIQ, PublishLevelStream, PublishOccupancy, PublishSpectrum, RecursiveFunction, // 递归方法 后期会删除
9
+ export type { AxisXProps, AxisYRange, BandProps, ChartRef, DialPolygon, FrequencyAllocationChannel, FrequencyAllocationDensity, FrequencyAllocationItem, MarkerProps, MarkerType, Publish, PublishData, PublishDial, PublishGauge, PublishHeatmap, PublishIQ, PublishLevelStream, PublishOccupancy, PublishSpectrum, RecursiveFunction, // 递归方法 后期会删除
10
10
  RecursiveObject, // 递归对象 后期会删除
11
- Render, Reset, SegmentsOriginal, SeriesConfig, SetAntennaFactor, SetChannels, SetMarker, SetSegments, SetSeries, SetSpectrumBandwidth, SignalData, SpectrumBandwidth, SpectrumExtraData, StationInfoType } from './types';
11
+ Render, Reset, SegmentsOriginal, SeriesConfig, SetAntennaFactor, SetChannels, SetMarker, SetSegments, SetSeries, SetSpectrumBandwidth, SignalData, SignalDetails, SpectrumBandwidth, SpectrumExtraData, StationInfoType } from './types';
12
12
  export { HeatmapCaptureType, MarkerMode } from './types';
13
13
  export { SignalDataType } from './types/store';
14
14
  export type { FrequencyUnitResult } from './utils';
package/index.js CHANGED
@@ -831,11 +831,6 @@ var __webpack_modules__ = {
831
831
  display: inline-flex;
832
832
  }
833
833
 
834
- [data-rfkit-charts-root] .size-2 {
835
- width: calc(var(--spacing) * 2);
836
- height: calc(var(--spacing) * 2);
837
- }
838
-
839
834
  [data-rfkit-charts-root] .size-3 {
840
835
  width: calc(var(--spacing) * 3);
841
836
  height: calc(var(--spacing) * 3);
@@ -2213,10 +2208,6 @@ var __webpack_modules__ = {
2213
2208
  opacity: .3;
2214
2209
  }
2215
2210
 
2216
- [data-rfkit-charts-root] .opacity-35 {
2217
- opacity: .35;
2218
- }
2219
-
2220
2211
  [data-rfkit-charts-root] .opacity-40 {
2221
2212
  opacity: .4;
2222
2213
  }
@@ -2321,11 +2312,6 @@ var __webpack_modules__ = {
2321
2312
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2322
2313
  }
2323
2314
 
2324
- [data-rfkit-charts-root] .ring-1 {
2325
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2326
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2327
- }
2328
-
2329
2315
  [data-rfkit-charts-root] .\\[box-shadow\\:0_0_0_1px_color-mix\\(in_srgb\\,var\\(--background\\)_82\\%\\,transparent\\)\\,[data-rfkit-charts-root] 0_1px_4px_color-mix\\(in_srgb\\,var\\(--foreground\\)_32\\%\\,transparent\\)\\] {
2330
2316
  box-shadow: 0 0 0 1px var(--background), 0 1px 4px var(--foreground);
2331
2317
  }
@@ -2346,20 +2332,6 @@ var __webpack_modules__ = {
2346
2332
  }
2347
2333
  }
2348
2334
 
2349
- [data-rfkit-charts-root] .ring-background\\/30 {
2350
- --tw-ring-color: var(--background);
2351
- }
2352
-
2353
- @supports (color: color-mix(in lab, red, red)) {
2354
- [data-rfkit-charts-root] .ring-background\\/30 {
2355
- --tw-ring-color: color-mix(in oklab, var(--background) 30%, transparent);
2356
- }
2357
- }
2358
-
2359
- [data-rfkit-charts-root] .ring-border {
2360
- --tw-ring-color: var(--border);
2361
- }
2362
-
2363
2335
  [data-rfkit-charts-root] .ring-offset-background {
2364
2336
  --tw-ring-offset-color: var(--background);
2365
2337
  }
@@ -2529,10 +2501,6 @@ var __webpack_modules__ = {
2529
2501
  animation-play-state: paused;
2530
2502
  }
2531
2503
 
2532
- [data-rfkit-charts-root] .ring-inset {
2533
- --tw-ring-inset: inset;
2534
- }
2535
-
2536
2504
  [data-rfkit-charts-root] .group-focus-within\\:opacity-90:is(:where(.group):focus-within *) {
2537
2505
  opacity: .9;
2538
2506
  }
@@ -5976,6 +5944,7 @@ function createParams() {
5976
5944
  display: false,
5977
5945
  data: [],
5978
5946
  hiddenCategoryKeys: [],
5947
+ showCount: true,
5979
5948
  onChange: ()=>{}
5980
5949
  },
5981
5950
  signalAnalysis: {
@@ -11104,6 +11073,12 @@ const withAlpha = (value1, opacity)=>{
11104
11073
  if (!color) return value1;
11105
11074
  return `rgba(${color.r}, ${color.g}, ${color.b}, ${Number((color.alpha * normalizedOpacity).toFixed(4))})`;
11106
11075
  };
11076
+ const toOpaqueCssColor = (value1)=>{
11077
+ const parsedHex = value1.startsWith('#') ? parseHexColor(value1) : null;
11078
+ const parsedRgb = parsedHex ? null : parseRgbColor(value1);
11079
+ const color = parsedHex ?? parsedRgb;
11080
+ return color ? `rgb(${color.r}, ${color.g}, ${color.b})` : value1;
11081
+ };
11107
11082
  function getThemeFillStyle(scopeTarget) {
11108
11083
  const themeColorBase = getThemePropertyValue('--foreground', scopeTarget);
11109
11084
  const themeColorPrimary = getThemePropertyValue('--primary', scopeTarget);
@@ -23174,15 +23149,32 @@ function getUnifiedSignalKey(item) {
23174
23149
  return `${source}:${item.frequency}-${item.bandwidth}`;
23175
23150
  }
23176
23151
  const buildSignalTree = (signalItems)=>{
23177
- const leafKeysWithData = new Set(signalItems.map(getSignalLeafKey));
23178
- const explicitLeafColors = new Map();
23152
+ const leafKeysWithData = new Set();
23153
+ const leafCounts = new Map();
23154
+ const leafColors = new Map();
23179
23155
  for (const item of signalItems){
23180
- if ('string' != typeof item.color || '' === item.color.trim()) continue;
23181
23156
  const leafKey = getSignalLeafKey(item);
23182
- if (!explicitLeafColors.has(leafKey)) explicitLeafColors.set(leafKey, item.color);
23157
+ const source = resolveSignalSource(item);
23158
+ leafKeysWithData.add(leafKey);
23159
+ leafCounts.set(leafKey, (leafCounts.get(leafKey) ?? 0) + 1);
23160
+ const colors = leafColors.get(leafKey) ?? new Set();
23161
+ colors.add(resolveSignalColor({
23162
+ ...item,
23163
+ source
23164
+ }));
23165
+ leafColors.set(leafKey, colors);
23183
23166
  }
23184
- const resolveSharedExplicitColor = (leafKeys)=>{
23185
- const colors = new Set(leafKeys.map((leafKey)=>explicitLeafColors.get(leafKey)).filter((color)=>null != color));
23167
+ const resolveCount = (leafKeys)=>leafKeys.reduce((count, leafKey)=>count + (leafCounts.get(leafKey) ?? 0), 0);
23168
+ const resolveLeafColor = (leafKey)=>{
23169
+ const colors = leafColors.get(leafKey);
23170
+ return colors?.size === 1 ? [
23171
+ ...colors
23172
+ ][0] : void 0;
23173
+ };
23174
+ const resolveSharedColor = (leafKeys)=>{
23175
+ const resolvedColors = leafKeys.map(resolveLeafColor);
23176
+ if (resolvedColors.some((color)=>null == color)) return;
23177
+ const colors = new Set(resolvedColors);
23186
23178
  return 1 === colors.size ? [
23187
23179
  ...colors
23188
23180
  ][0] : void 0;
@@ -23200,6 +23192,7 @@ const buildSignalTree = (signalItems)=>{
23200
23192
  leafKeys: sourceDataLeafKeys,
23201
23193
  dataLeafKeys: sourceDataLeafKeys,
23202
23194
  hasData: true,
23195
+ count: resolveCount(sourceDataLeafKeys),
23203
23196
  types: []
23204
23197
  });
23205
23198
  continue;
@@ -23212,7 +23205,8 @@ const buildSignalTree = (signalItems)=>{
23212
23205
  label: SIGNAL_LEVEL_MAP[level].name,
23213
23206
  leafKey,
23214
23207
  hasData: leafKeysWithData.has(leafKey),
23215
- color: explicitLeafColors.get(leafKey)
23208
+ count: leafCounts.get(leafKey) ?? 0,
23209
+ color: resolveLeafColor(leafKey)
23216
23210
  };
23217
23211
  });
23218
23212
  const leafKeys = levels.map((level)=>level.leafKey);
@@ -23224,7 +23218,8 @@ const buildSignalTree = (signalItems)=>{
23224
23218
  leafKeys,
23225
23219
  dataLeafKeys,
23226
23220
  hasData: dataLeafKeys.length > 0,
23227
- color: resolveSharedExplicitColor(dataLeafKeys),
23221
+ count: resolveCount(dataLeafKeys),
23222
+ color: resolveSharedColor(dataLeafKeys),
23228
23223
  levels: signalType === SignalType.LEGITIMATE ? levels.filter((level)=>level.hasData) : []
23229
23224
  };
23230
23225
  });
@@ -23237,6 +23232,7 @@ const buildSignalTree = (signalItems)=>{
23237
23232
  leafKeys,
23238
23233
  dataLeafKeys,
23239
23234
  hasData: true,
23235
+ count: resolveCount(dataLeafKeys),
23240
23236
  types
23241
23237
  });
23242
23238
  }
@@ -23340,6 +23336,11 @@ const resolveSignalPresentation = (item)=>{
23340
23336
  });
23341
23337
  const frequencyText = resolveFrequencyPresentation(item);
23342
23338
  const bandwidthText = null != item.bandwidth ? `\u{5E26}\u{5BBD}: ${item.bandwidth}kHz` : void 0;
23339
+ const details = tree_isStationInfo(item) ? {
23340
+ name: item.signalName,
23341
+ organization: item.orgName,
23342
+ modulation: item.modulation
23343
+ } : item.details;
23343
23344
  if (tree_isStationInfo(item)) return {
23344
23345
  color,
23345
23346
  tooltip: [
@@ -23352,9 +23353,12 @@ const resolveSignalPresentation = (item)=>{
23352
23353
  return {
23353
23354
  color,
23354
23355
  tooltip: [
23356
+ details?.name,
23355
23357
  SIGNAL_SOURCE_LABEL[source],
23356
23358
  frequencyText,
23359
+ details?.organization && `\u{5355}\u{4F4D}: ${details.organization}`,
23357
23360
  bandwidthText,
23361
+ details?.modulation && `\u{8C03}\u{5236}: ${details.modulation}`,
23358
23362
  signalTypeName && `\u{7C7B}\u{578B}: ${signalTypeName}`,
23359
23363
  signalType === SignalType.LEGITIMATE && levelName && `\u{7B49}\u{7EA7}: ${levelName}`
23360
23364
  ].filter(Boolean).join(' | ')
@@ -23564,26 +23568,23 @@ const SignalInfoRow = ({ label, value: value1, tabular = false })=>/*#__PURE__*/
23564
23568
  })
23565
23569
  ]
23566
23570
  });
23567
- const SignalMetaValue = ({ color, label, testId })=>/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("span", {
23568
- className: "inline-flex items-center gap-1.5 font-medium text-foreground",
23569
- children: [
23570
- /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
23571
- "aria-hidden": "true",
23572
- className: "size-2 shrink-0 rounded-full ring-1 ring-inset ring-border",
23573
- "data-testid": testId,
23574
- style: {
23575
- backgroundColor: color
23576
- }
23577
- }),
23578
- /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
23579
- children: label
23580
- })
23581
- ]
23571
+ const SignalMetaValue = ({ color, label, testId })=>/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
23572
+ className: "font-medium text-foreground",
23573
+ "data-testid": testId,
23574
+ style: color ? {
23575
+ color: toOpaqueCssColor(color)
23576
+ } : void 0,
23577
+ children: label
23582
23578
  });
23583
23579
  const SignalInfoPanel = ({ signalInfo })=>{
23584
23580
  if (!signalInfo) return null;
23585
23581
  const source = resolveSignalSource(signalInfo);
23586
- const stationInfo = tree_isStationInfo(signalInfo) ? signalInfo : void 0;
23582
+ const details = tree_isStationInfo(signalInfo) ? {
23583
+ name: signalInfo.signalName,
23584
+ organization: signalInfo.orgName,
23585
+ modulation: signalInfo.modulation,
23586
+ remark: signalInfo.remark
23587
+ } : signalInfo.details;
23587
23588
  const signalType = normalizeSignalType(signalInfo.signalType);
23588
23589
  const signalTypeInfo = SIGNAL_TYPE_MAP[signalType];
23589
23590
  const levelInfo = SIGNAL_LEVEL_MAP[normalizeSignalLevel(signalInfo.level)];
@@ -23592,7 +23593,7 @@ const SignalInfoPanel = ({ signalInfo })=>{
23592
23593
  ...signalInfo,
23593
23594
  source
23594
23595
  });
23595
- const typeColor = showLevel ? signalTypeInfo.color : resolvedColor;
23596
+ const typeColor = showLevel ? void 0 : resolvedColor;
23596
23597
  const hasFrequencyRange = null != signalInfo.startFrequency && null != signalInfo.stopFrequency;
23597
23598
  return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
23598
23599
  className: "mt-2 border-t border-border/60 pt-2 text-xs leading-5 text-foreground",
@@ -23605,13 +23606,13 @@ const SignalInfoPanel = ({ signalInfo })=>{
23605
23606
  label: "\u6765\u6E90",
23606
23607
  value: SIGNAL_SOURCE_LABEL[source]
23607
23608
  }),
23608
- stationInfo?.signalName ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23609
+ details?.name ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23609
23610
  label: "\u540D\u79F0",
23610
- value: stationInfo.signalName
23611
+ value: details.name
23611
23612
  }) : null,
23612
- stationInfo?.orgName ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23613
+ details?.organization ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23613
23614
  label: "\u5355\u4F4D",
23614
- value: stationInfo.orgName
23615
+ value: details.organization
23615
23616
  }) : null,
23616
23617
  null != signalInfo.frequency ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23617
23618
  label: "\u9891\u7387",
@@ -23627,16 +23628,16 @@ const SignalInfoPanel = ({ signalInfo })=>{
23627
23628
  value: `${signalInfo.bandwidth}kHz`,
23628
23629
  tabular: true
23629
23630
  }) : null,
23630
- stationInfo?.modulation ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23631
+ details?.modulation ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23631
23632
  label: "\u8C03\u5236",
23632
- value: stationInfo.modulation
23633
+ value: details.modulation
23633
23634
  }) : null,
23634
23635
  /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23635
23636
  label: "\u7C7B\u578B",
23636
23637
  value: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalMetaValue, {
23637
23638
  color: typeColor,
23638
23639
  label: signalTypeInfo.name,
23639
- testId: "signal-info-type-swatch"
23640
+ testId: "signal-info-type-color"
23640
23641
  })
23641
23642
  }),
23642
23643
  showLevel ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
@@ -23644,12 +23645,12 @@ const SignalInfoPanel = ({ signalInfo })=>{
23644
23645
  value: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalMetaValue, {
23645
23646
  color: resolvedColor,
23646
23647
  label: levelInfo.name,
23647
- testId: "signal-info-level-swatch"
23648
+ testId: "signal-info-level-color"
23648
23649
  })
23649
23650
  }) : null,
23650
- stationInfo?.remark ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23651
+ details?.remark ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalInfoRow, {
23651
23652
  label: "\u5907\u6CE8",
23652
- value: stationInfo.remark
23653
+ value: details.remark
23653
23654
  }) : null
23654
23655
  ]
23655
23656
  })
@@ -29227,10 +29228,20 @@ const toCheckboxValue = (state)=>{
29227
29228
  if ('indeterminate' === state) return 'indeterminate';
29228
29229
  return false;
29229
29230
  };
29230
- const SignalTypeRow = ({ source, type, leafKeysWithData, hiddenKeys, expanded, onToggleExpanded, onToggleNode })=>{
29231
+ const SignalNodeCount = ({ count, show, testId })=>show ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("span", {
29232
+ className: "shrink-0 tabular-nums text-[11px] font-normal text-muted-foreground",
29233
+ "data-testid": testId,
29234
+ children: [
29235
+ "(",
29236
+ count,
29237
+ ")"
29238
+ ]
29239
+ }) : null;
29240
+ const SignalTypeRow = ({ source, type, leafKeysWithData, hiddenKeys, showCount, expanded, onToggleExpanded, onToggleNode })=>{
29231
29241
  const state = resolveNodeCheckState(leafKeysWithData, hiddenKeys, type.leafKeys);
29232
29242
  const checkboxId = `signal-tree-type-checkbox-${source.source}-${type.signalType}`;
29233
29243
  const hasLevels = type.levels.length > 0;
29244
+ const typeColor = hasLevels ? void 0 : type.color ?? SIGNAL_TYPE_MAP[type.signalType].color;
29234
29245
  return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("div", {
29235
29246
  children: [
29236
29247
  /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("div", {
@@ -29262,17 +29273,18 @@ const SignalTypeRow = ({ source, type, leafKeysWithData, hiddenKeys, expanded, o
29262
29273
  disabled: 'disabled' === state,
29263
29274
  onCheckedChange: ()=>onToggleNode(type.leafKeys)
29264
29275
  }),
29265
- /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
29266
- "aria-hidden": "true",
29267
- className: cn_cn('size-2 shrink-0 rounded-full ring-1 ring-inset ring-background/30', 'disabled' === state && 'opacity-35'),
29268
- "data-testid": `signal-tree-type-color-${source.source}-${type.signalType}`,
29269
- style: {
29270
- backgroundColor: type.color ?? SIGNAL_TYPE_MAP[type.signalType].color
29271
- }
29272
- }),
29273
29276
  /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
29274
29277
  className: cn_cn('min-w-0 truncate text-xs font-medium', 'disabled' === state ? 'text-muted-foreground' : 'text-foreground/90'),
29278
+ "data-testid": `signal-tree-type-color-${source.source}-${type.signalType}`,
29279
+ style: 'disabled' === state || null == typeColor ? void 0 : {
29280
+ color: toOpaqueCssColor(typeColor)
29281
+ },
29275
29282
  children: type.label
29283
+ }),
29284
+ /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalNodeCount, {
29285
+ count: type.count,
29286
+ show: showCount,
29287
+ testId: `signal-tree-type-count-${source.source}-${type.signalType}`
29276
29288
  })
29277
29289
  ]
29278
29290
  })
@@ -29286,13 +29298,14 @@ const SignalTypeRow = ({ source, type, leafKeysWithData, hiddenKeys, expanded, o
29286
29298
  level: level,
29287
29299
  leafKeysWithData: leafKeysWithData,
29288
29300
  hiddenKeys: hiddenKeys,
29301
+ showCount: showCount,
29289
29302
  onToggleNode: onToggleNode
29290
29303
  }, level.leafKey))
29291
29304
  }) : null
29292
29305
  ]
29293
29306
  }, type.signalType);
29294
29307
  };
29295
- const SignalLevelRow = ({ source, signalType, level, leafKeysWithData, hiddenKeys, onToggleNode })=>{
29308
+ const SignalLevelRow = ({ source, signalType, level, leafKeysWithData, hiddenKeys, showCount, onToggleNode })=>{
29296
29309
  const state = resolveNodeCheckState(leafKeysWithData, hiddenKeys, [
29297
29310
  level.leafKey
29298
29311
  ]);
@@ -29314,22 +29327,23 @@ const SignalLevelRow = ({ source, signalType, level, leafKeysWithData, hiddenKey
29314
29327
  ])
29315
29328
  }),
29316
29329
  /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
29317
- "aria-hidden": "true",
29318
- className: cn_cn('size-2 shrink-0 rounded-full ring-1 ring-inset ring-background/30', 'disabled' === state && 'opacity-35'),
29330
+ className: cn_cn('text-xs font-medium', 'disabled' === state ? 'text-muted-foreground' : 'text-foreground/80'),
29319
29331
  "data-testid": `signal-tree-level-color-${source}-${signalType}-${level.level}`,
29320
- style: {
29321
- backgroundColor: level.color ?? SIGNAL_LEVEL_MAP[level.level].color
29322
- }
29323
- }),
29324
- /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
29325
- className: cn_cn('text-xs', 'disabled' === state ? 'text-muted-foreground' : 'text-foreground/80'),
29332
+ style: 'disabled' === state ? void 0 : {
29333
+ color: toOpaqueCssColor(level.color ?? SIGNAL_LEVEL_MAP[level.level].color)
29334
+ },
29326
29335
  children: level.label
29336
+ }),
29337
+ /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalNodeCount, {
29338
+ count: level.count,
29339
+ show: showCount,
29340
+ testId: `signal-tree-level-count-${source}-${signalType}-${level.level}`
29327
29341
  })
29328
29342
  ]
29329
29343
  })
29330
29344
  });
29331
29345
  };
29332
- const SignalAnnotationTree = ({ tree, leafKeysWithData, hiddenKeys, onToggleNode })=>{
29346
+ const SignalAnnotationTree = ({ tree, leafKeysWithData, hiddenKeys, showCount, onToggleNode })=>{
29333
29347
  const [collapsedKeys, setCollapsedKeys] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>new Set());
29334
29348
  const [collapsedSourceKeys, setCollapsedSourceKeys] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>new Set());
29335
29349
  const toggleExpanded = (0, __WEBPACK_EXTERNAL_MODULE_react__.useCallback)((key)=>{
@@ -29391,6 +29405,11 @@ const SignalAnnotationTree = ({ tree, leafKeysWithData, hiddenKeys, onToggleNode
29391
29405
  /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
29392
29406
  className: "text-xs font-medium text-foreground",
29393
29407
  children: source.label
29408
+ }),
29409
+ /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(SignalNodeCount, {
29410
+ count: source.count,
29411
+ show: showCount,
29412
+ testId: `signal-tree-source-count-${source.source}`
29394
29413
  })
29395
29414
  ]
29396
29415
  })
@@ -29403,6 +29422,7 @@ const SignalAnnotationTree = ({ tree, leafKeysWithData, hiddenKeys, onToggleNode
29403
29422
  type: type,
29404
29423
  leafKeysWithData: leafKeysWithData,
29405
29424
  hiddenKeys: hiddenKeys,
29425
+ showCount: showCount,
29406
29426
  expanded: !collapsedKeys.has(`${source.source}:${type.signalType}`),
29407
29427
  onToggleExpanded: ()=>toggleExpanded(`${source.source}:${type.signalType}`),
29408
29428
  onToggleNode: onToggleNode
@@ -29492,6 +29512,7 @@ const Signal_Switch_Switch = ()=>{
29492
29512
  tree: tree,
29493
29513
  leafKeysWithData: leafKeysWithData,
29494
29514
  hiddenKeys: hiddenKeys,
29515
+ showCount: false !== signal.showCount,
29495
29516
  onToggleNode: toggleNode
29496
29517
  })
29497
29518
  }),
@@ -27,6 +27,7 @@ export interface SignalTreeLevelNode {
27
27
  label: string;
28
28
  leafKey: string;
29
29
  hasData: boolean;
30
+ count: number;
30
31
  color?: string;
31
32
  }
32
33
  export interface SignalTreeTypeNode {
@@ -35,6 +36,7 @@ export interface SignalTreeTypeNode {
35
36
  leafKeys: string[];
36
37
  dataLeafKeys: string[];
37
38
  hasData: boolean;
39
+ count: number;
38
40
  color?: string;
39
41
  levels: SignalTreeLevelNode[];
40
42
  }
@@ -44,6 +46,7 @@ export interface SignalTreeSourceNode {
44
46
  leafKeys: string[];
45
47
  dataLeafKeys: string[];
46
48
  hasData: boolean;
49
+ count: number;
47
50
  types: SignalTreeTypeNode[];
48
51
  }
49
52
  export interface SignalTree {
@@ -13,12 +13,20 @@ export interface CircularSeriesItem {
13
13
  lineWidth?: number;
14
14
  radio?: number;
15
15
  }
16
+ /**
17
+ * 雷达多边形数据项
18
+ */
19
+ export interface CircularPolygonItem {
20
+ values: number[];
21
+ color?: string;
22
+ }
16
23
  /**
17
24
  * 圆形图表数据
18
25
  */
19
26
  export interface CircularData {
20
27
  series?: CircularSeriesItem[];
21
28
  range?: number[];
29
+ polygon?: CircularPolygonItem[];
22
30
  yawAngle?: number;
23
31
  isNorthFacing?: boolean;
24
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rfkit/charts",
3
- "version": "1.10.5",
3
+ "version": "1.10.7",
4
4
  "type": "module",
5
5
  "description": "Chart components for wireless monitoring web applications",
6
6
  "exports": {
@@ -3,5 +3,7 @@ export interface ThemeFillStyle {
3
3
  fillStylePrimary: string;
4
4
  fillStyleTransparentBase: string;
5
5
  }
6
+ /** 文本图例沿用颜色色相,但去除业务填充色的透明度以保证可读性。 */
7
+ export declare const toOpaqueCssColor: (value: string) => string;
6
8
  export declare function getThemeFillStyle(scopeTarget?: Element | null): ThemeFillStyle;
7
9
  export declare const getThemeColor: (property: string, opacity?: number, scopeTarget?: Element | null) => string;
@@ -90,13 +90,20 @@ export interface PublishIQ {
90
90
  IData: number[];
91
91
  QData: number[];
92
92
  }
93
+ export interface DialPolygon {
94
+ /** 各方向归一化值(0-1),长度即方向数,按 0..360 度均匀分布;值决定该方向半径,1 贴最外网格 */
95
+ values: number[];
96
+ /** 多边形颜色;缺省走主题主色 fillStylePrimary,边框与半透明填充均由此色派生 */
97
+ color?: string;
98
+ }
93
99
  export interface PublishDial {
94
100
  pstype?: PSType.Dial;
95
- series: Array<{
101
+ series?: Array<{
96
102
  value: number;
97
103
  color: string;
98
104
  }>;
99
105
  range?: number[];
106
+ polygon?: DialPolygon[];
100
107
  yawAngle?: number;
101
108
  isNorthFacing?: boolean;
102
109
  }
@@ -2,6 +2,13 @@ export declare enum SignalDataType {
2
2
  Station = "station",// 台站信号(详细信息)
3
3
  Simple = "simple"
4
4
  }
5
+ /** 信号库可选详情;与台站库的公共展示信息保持一致。 */
6
+ export interface SignalDetails {
7
+ name?: string;
8
+ organization?: string;
9
+ modulation?: string;
10
+ remark?: string;
11
+ }
5
12
  export interface SignalData {
6
13
  id?: string;
7
14
  startFrequency?: number | string;
@@ -11,6 +18,7 @@ export interface SignalData {
11
18
  color?: string;
12
19
  signalType?: string;
13
20
  level?: number;
21
+ details?: SignalDetails;
14
22
  }
15
23
  export type SelectedSignal = {
16
24
  segIndex: number;
@@ -21,6 +29,7 @@ export interface SignalProps {
21
29
  display: boolean;
22
30
  data: SignalData[];
23
31
  hiddenCategoryKeys: string[];
32
+ showCount: boolean;
24
33
  onChange: (e: SelectedSignal) => void;
25
34
  }
26
35
  export interface SignalAnalysisProps {