@opsnow-mcp/opsnow-mcp-common-ui-server 1.0.25 → 1.0.26

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.
@@ -6838,6 +6838,119 @@ export const XyMultiChartExamples = [
6838
6838
  chartCustomCategory={chartCustomCategory}
6839
6839
  />`
6840
6840
  },
6841
+ {
6842
+ title: 'XY 멀티 차트 - bullet.hitRadius (작은 bullet 의 클릭 영역만 넓히기)',
6843
+ description: 'bullet.hitRadius 속성으로 bullet 의 시각적 크기는 그대로 두고 클릭/호버 인식 영역만 넓히는 예제입니다. anomaly(이상치) 마커처럼 시각적으로는 작아야 하지만 클릭은 쉬워야 하는 경우, bullet 주변 영역까지 클릭할 수 있도록 확장합니다. hitRadius=14 를 적용하면 visible radius 는 동일하지만 hit area 가 약 3배가 됩니다.',
6844
+ code_props_usage: `
6845
+ const chartId = 'multi-chart-${generateUniqueGeneralId()}'
6846
+ const chartRef = useRef(null)
6847
+
6848
+ const [chartProps, setChartProps] = useState({
6849
+ xAxis: {
6850
+ type: 'date',
6851
+ dateFormats: [{ type: 'day', dateFormat: 'yyyy/MM/dd' }],
6852
+ baseInterval: { timeUnit: 'day', count: 1 },
6853
+ gridHidden: true,
6854
+ renderer: { minGridDistance: 30 },
6855
+ },
6856
+ yAxis: {
6857
+ type: 'value',
6858
+ numberFormatter: { numberFormat: '#.#a' },
6859
+ },
6860
+ series: {
6861
+ valueXField: 'date',
6862
+ dataProcessor: { dateFields: ['date'], dateFormat: 'yyyy-MM-dd' },
6863
+ seriesTypes: [
6864
+ // 민감도 범위 (range area)
6865
+ {
6866
+ type: 'line',
6867
+ categoryGroupName: 'sensitivity',
6868
+ strokeWidth: 0,
6869
+ area: {
6870
+ type: 'range',
6871
+ openValueField: 'sensitivity_open',
6872
+ fillOpacity: 0.2,
6873
+ },
6874
+ bullet: { type: 'circle', lineOnly: true },
6875
+ },
6876
+ // 실제 값 (기본 bullet)
6877
+ {
6878
+ type: 'line',
6879
+ categoryGroupName: 'actual',
6880
+ clickTarget: true,
6881
+ bullet: { type: 'circle', cursorOverStyle: 'pointer' },
6882
+ },
6883
+ // anomaly 마커 — hitRadius 로 클릭 영역만 확장
6884
+ {
6885
+ type: 'line',
6886
+ categoryGroupName: 'anomaly',
6887
+ strokeWidth: 0,
6888
+ clickTarget: true,
6889
+ bullet: {
6890
+ type: 'circle',
6891
+ customField: 'bullet_alarm',
6892
+ cursorOverStyle: 'pointer',
6893
+ hitRadius: 14, // 시각 radius 는 유지, 클릭 영역만 확장
6894
+ },
6895
+ },
6896
+ ],
6897
+ tooltip: {
6898
+ type: 'CG',
6899
+ showAt: 'actual',
6900
+ orientation: 'vertical',
6901
+ header: { name: '{valueX.formatDate("yyyy/MM/dd")}' },
6902
+ body: {
6903
+ maxRowCount: 10,
6904
+ name: '{name}',
6905
+ value: '\${valueY}',
6906
+ useMarker: true,
6907
+ },
6908
+ },
6909
+ },
6910
+ legend: { useExtension: false, clickTarget: 'none' },
6911
+ cursor: { visibleY: false },
6912
+ })
6913
+
6914
+ const [chartData, setChartData] = useState([
6915
+ { date: '2026-05-01', sensitivity_open: 10, sensitivity_close: 20, actual_cost: 13 },
6916
+ { date: '2026-05-02', sensitivity_open: 20, sensitivity_close: 30, actual_cost: 22 },
6917
+ {
6918
+ date: '2026-05-03',
6919
+ sensitivity_open: 10, sensitivity_close: 20,
6920
+ actual_cost: 27,
6921
+ anomaly_cost: 27,
6922
+ bullet_alarm: { type: 'alarm', target: 'anomaly_cost' },
6923
+ },
6924
+ { date: '2026-05-04', sensitivity_open: 30, sensitivity_close: 40, actual_cost: 35 },
6925
+ {
6926
+ date: '2026-05-05',
6927
+ sensitivity_open: 40, sensitivity_close: 50,
6928
+ actual_cost: 28,
6929
+ anomaly_cost: 28,
6930
+ bullet_alarm: { type: 'alarm', target: 'anomaly_cost' },
6931
+ },
6932
+ { date: '2026-05-06', sensitivity_open: 20, sensitivity_close: 30, actual_cost: 22 },
6933
+ ])
6934
+ const [chartCategory] = useState([
6935
+ { name: 'sensitivity', categories: ['sensitivity_close'] },
6936
+ { name: 'actual', categories: ['actual_cost'] },
6937
+ { name: 'anomaly', categories: ['anomaly_cost'] },
6938
+ ])
6939
+ const [chartCustomCategory] = useState([
6940
+ { name: 'sensitivity_close', color: '#8cc9ff' },
6941
+ { name: 'actual_cost', color: '#086ce8' },
6942
+ { name: 'anomaly_cost', color: '#d92936', legendMarkerType: 'alarm' },
6943
+ ])
6944
+ `,
6945
+ code: `<OpsnowCommonXyMultiChart
6946
+ ref={chartRef}
6947
+ chartId={chartId}
6948
+ chartProps={chartProps}
6949
+ chartCategory={chartCategory}
6950
+ chartData={chartData}
6951
+ chartCustomCategory={chartCustomCategory}
6952
+ />`
6953
+ },
6841
6954
  ];
6842
6955
  // Heatmap Chart 컴포넌트 예제 데이터
6843
6956
  export const HeatmapChartExamples = [
@@ -7264,3 +7377,239 @@ export const HeatmapChartExamples = [
7264
7377
  <button onClick={() => handleDownload('pdf')}>Download PDF</button>`
7265
7378
  },
7266
7379
  ];
7380
+ // Bubble Chart 컴포넌트 예제 데이터
7381
+ export const BubbleChartExamples = [
7382
+ {
7383
+ title: '버블 차트 - 국가별 GDP (sizeField + colorField + 다국어)',
7384
+ description: '국가별 GDP 지수(X) × 기대수명(Y) × 인구(size)를 버블로 표시하는 기본 예제입니다. sizeField로 버블 크기를 데이터에 매핑하고, colorField 로 항목별 색상을 직접 지정합니다. chartLocaleMessage 로 country_xx 키를 다국어 국가명으로 치환합니다.',
7385
+ code_props_usage: `
7386
+ const chartId = 'bubble-chart-${generateUniqueGeneralId()}'
7387
+ const chartRef = useRef(null)
7388
+ const [chartProps, setChartProps] = useState({
7389
+ xAxis: { gridHidden: false, labelHidden: false },
7390
+ yAxis: { gridHidden: false, labelHidden: false },
7391
+ series: {
7392
+ valueXField: 'x',
7393
+ valueYField: 'y',
7394
+ sizeField: 'value',
7395
+ minBulletSize: 6,
7396
+ maxBulletSize: 40,
7397
+ colorField: 'fillColor',
7398
+ fillOpacity: 0.7,
7399
+ tooltip: {
7400
+ header: { name: '[bold]{name}[/]' },
7401
+ body: {
7402
+ value:
7403
+ '{l.gdpIndex}: {valueX}\\n{l.lifeExp}: {valueY}\\n{l.population}: {value}',
7404
+ },
7405
+ },
7406
+ },
7407
+ cursor: { behavior: 'none', visibleX: true, visibleY: true },
7408
+ })
7409
+ const [chartData, setChartData] = useState([
7410
+ { x: 83, y: 78.2, value: 330000, name: 'country_us', fillColor: '#4caf50' },
7411
+ { x: 64, y: 75.4, value: 1400000, name: 'country_cn', fillColor: '#f44336' },
7412
+ { x: 47, y: 73.1, value: 1380000, name: 'country_in', fillColor: '#ff9800' },
7413
+ { x: 42, y: 84.2, value: 125000, name: 'country_jp', fillColor: '#2196f3' },
7414
+ { x: 70, y: 80.9, value: 83000, name: 'country_de', fillColor: '#9c27b0' },
7415
+ { x: 72, y: 81.3, value: 67000, name: 'country_uk', fillColor: '#00bcd4' },
7416
+ { x: 58, y: 82.6, value: 51000, name: 'country_kr', fillColor: '#3f51b5' },
7417
+ ])
7418
+ const chartLocaleMessage = [
7419
+ { name: 'country_us', locale: '미국' },
7420
+ { name: 'country_cn', locale: '중국' },
7421
+ { name: 'country_in', locale: '인도' },
7422
+ { name: 'country_jp', locale: '일본' },
7423
+ { name: 'country_de', locale: '독일' },
7424
+ { name: 'country_uk', locale: '영국' },
7425
+ { name: 'country_kr', locale: '대한민국' },
7426
+ ]
7427
+ const chartLocaleProps = [
7428
+ { name: 'l.gdpIndex', locale: 'GDP 지수' },
7429
+ { name: 'l.lifeExp', locale: '기대 수명' },
7430
+ { name: 'l.population', locale: '인구' },
7431
+ ]
7432
+ `,
7433
+ code: `<OpsnowCommonBubbleChart
7434
+ chartId={chartId}
7435
+ chartRef={chartRef}
7436
+ chartProps={chartProps}
7437
+ chartData={chartData}
7438
+ chartLocaleMessage={chartLocaleMessage}
7439
+ chartLocaleProps={chartLocaleProps}
7440
+ />`
7441
+ },
7442
+ {
7443
+ title: '버블 차트 - 클러스터 분포 (클릭 이벤트)',
7444
+ description: '클러스터별 분포(X, Y)와 멤버 수(size), 위험도(색상)를 표시하는 버블 차트 예제입니다. avg_distance 값에 따라 색상이 다르게 지정되고 (severity: critical/warning/info), onChartClick 으로 클릭한 클러스터 정보를 받습니다.',
7445
+ code_props_usage: `
7446
+ const chartId = 'bubble-chart-${generateUniqueGeneralId()}'
7447
+ const chartRef = useRef(null)
7448
+ const [clickedItem, setClickedItem] = useState(null)
7449
+ const [chartProps, setChartProps] = useState({
7450
+ xAxis: { gridHidden: false, labelHidden: true },
7451
+ yAxis: { gridHidden: false, labelHidden: true },
7452
+ series: {
7453
+ valueXField: 'x',
7454
+ valueYField: 'y',
7455
+ sizeField: 'value',
7456
+ minBulletSize: 5,
7457
+ maxBulletSize: 30,
7458
+ colorField: 'fillColor',
7459
+ fillOpacity: 0.65,
7460
+ tooltip: {
7461
+ header: { name: '[bold]{name}[/]' },
7462
+ body: {
7463
+ value: '{l.logs}: {member_count}\\n{l.clarity}: {avg_distance}',
7464
+ },
7465
+ },
7466
+ },
7467
+ cursor: { behavior: 'none' },
7468
+ })
7469
+ // avg_distance 임계값 기반으로 fillColor 매핑
7470
+ const [chartData, setChartData] = useState([
7471
+ { x: 0.2, y: 5.8, value: 1200, member_count: 1200, avg_distance: 0.85, fillColor: '#f44336', name: 'cluster_1' },
7472
+ { x: 1.5, y: 4.2, value: 800, member_count: 800, avg_distance: 0.55, fillColor: '#ff9800', name: 'cluster_2' },
7473
+ { x: 4.1, y: 2.0, value: 2000, member_count: 6500, avg_distance: 0.25, fillColor: '#4caf50', name: 'cluster_3' },
7474
+ { x: 4.8, y: 3.1, value: 1500, member_count: 4200, avg_distance: 0.3, fillColor: '#4caf50', name: 'cluster_4' },
7475
+ { x: 8.2, y: 0.5, value: 600, member_count: 600, avg_distance: 0.72, fillColor: '#f44336', name: 'cluster_5' },
7476
+ ])
7477
+ const chartLocaleMessage = chartData.map((d, i) => ({
7478
+ name: d.name,
7479
+ locale: \`클러스터 #\${i + 1}\`,
7480
+ }))
7481
+ const chartLocaleProps = [
7482
+ { name: 'l.logs', locale: '로그 수' },
7483
+ { name: 'l.clarity', locale: '평균 거리' },
7484
+ ]
7485
+ const handleChartClick = (data) => {
7486
+ setClickedItem(data)
7487
+ console.log('Clicked bubble:', data)
7488
+ }
7489
+ `,
7490
+ code: `<OpsnowCommonBubbleChart
7491
+ chartId={chartId}
7492
+ chartRef={chartRef}
7493
+ chartProps={chartProps}
7494
+ chartData={chartData}
7495
+ chartLocaleMessage={chartLocaleMessage}
7496
+ chartLocaleProps={chartLocaleProps}
7497
+ onChartClick={handleChartClick}
7498
+ />`
7499
+ },
7500
+ {
7501
+ title: '버블 차트 - 자동 색상 할당 (colorField/sizeField 미지정)',
7502
+ description: 'colorField 와 sizeField 를 생략한 가장 단순한 형태의 버블 차트(산점도) 예제입니다. 색상은 amCharts5 가 자동 할당하며, 모든 버블이 동일 크기로 표시됩니다. 특정 항목만 fillColor 를 직접 지정해 강조할 수 있습니다.',
7503
+ code_props_usage: `
7504
+ const chartId = 'bubble-chart-${generateUniqueGeneralId()}'
7505
+ const chartRef = useRef(null)
7506
+ const [chartProps, setChartProps] = useState({
7507
+ xAxis: { gridHidden: false, labelHidden: false },
7508
+ yAxis: { gridHidden: false, labelHidden: false },
7509
+ series: {
7510
+ valueXField: 'x',
7511
+ valueYField: 'y',
7512
+ fillOpacity: 0.8,
7513
+ tooltip: {
7514
+ header: { name: '[bold]{name}[/]' },
7515
+ body: { value: 'x: {valueX}, y: {valueY}' },
7516
+ },
7517
+ },
7518
+ cursor: { behavior: 'none', visibleX: true, visibleY: true },
7519
+ })
7520
+ const [chartData, setChartData] = useState([
7521
+ { x: 1, y: 5, name: 'A' },
7522
+ { x: 3, y: 8, name: 'B' },
7523
+ { x: 5, y: 3, name: 'C' },
7524
+ { x: 7, y: 9, name: 'D' },
7525
+ { x: 2, y: 7, name: 'E' },
7526
+ { x: 8, y: 2, name: 'F' },
7527
+ { x: 4, y: 6, name: 'G' },
7528
+ // 특정 항목만 fillColor 로 강조
7529
+ { x: 6, y: 4, name: 'h_label', fillColor: '#000000' },
7530
+ ])
7531
+ const chartLocaleMessage = [
7532
+ { name: 'h_label', locale: '강조 H' },
7533
+ ]
7534
+ `,
7535
+ code: `<OpsnowCommonBubbleChart
7536
+ chartId={chartId}
7537
+ chartRef={chartRef}
7538
+ chartProps={chartProps}
7539
+ chartData={chartData}
7540
+ chartLocaleMessage={chartLocaleMessage}
7541
+ />`
7542
+ },
7543
+ {
7544
+ title: '버블 차트 - 축 Padding (extraMin/extraMax 로 가장자리 잘림 방지)',
7545
+ description: '버블이 X/Y 축의 최소/최대값에 가까울 경우 버블이 차트 가장자리에 잘리는 현상을 방지하는 예제입니다. xAxis/yAxis 의 extraMin / extraMax 값(0~1, 비율) 으로 축 양 끝에 여백을 추가할 수 있습니다. 좌(기본) / 우(extraMin=0.1, extraMax=0.1) 비교 시 효과를 확인할 수 있습니다.',
7546
+ code_props_usage: `
7547
+ const chartIdA = 'bubble-padding-default-${generateUniqueGeneralId()}'
7548
+ const chartIdB = 'bubble-padding-extra-${generateUniqueGeneralId()}'
7549
+ const chartRefA = useRef(null)
7550
+ const chartRefB = useRef(null)
7551
+
7552
+ // Before — extraMin/extraMax 없음 (모서리 버블이 잘림)
7553
+ const [chartPropsA] = useState({
7554
+ xAxis: { gridHidden: false, labelHidden: false },
7555
+ yAxis: { gridHidden: false, labelHidden: false },
7556
+ series: {
7557
+ valueXField: 'x',
7558
+ valueYField: 'y',
7559
+ sizeField: 'value',
7560
+ minBulletSize: 8,
7561
+ maxBulletSize: 24,
7562
+ colorField: 'fillColor',
7563
+ fillOpacity: 0.7,
7564
+ tooltip: {
7565
+ header: { name: '[bold]{name}[/]' },
7566
+ body: { value: 'x: {valueX}, y: {valueY}' },
7567
+ },
7568
+ },
7569
+ cursor: { behavior: 'none' },
7570
+ })
7571
+ // After — extraMin/extraMax 적용 (가장자리 여백 확보)
7572
+ const [chartPropsB] = useState({
7573
+ xAxis: { gridHidden: false, labelHidden: false, extraMin: 0.1, extraMax: 0.1 },
7574
+ yAxis: { gridHidden: false, labelHidden: false, extraMin: 0.1, extraMax: 0.1 },
7575
+ series: {
7576
+ valueXField: 'x',
7577
+ valueYField: 'y',
7578
+ sizeField: 'value',
7579
+ minBulletSize: 8,
7580
+ maxBulletSize: 24,
7581
+ colorField: 'fillColor',
7582
+ fillOpacity: 0.7,
7583
+ tooltip: {
7584
+ header: { name: '[bold]{name}[/]' },
7585
+ body: { value: 'x: {valueX}, y: {valueY}' },
7586
+ },
7587
+ },
7588
+ cursor: { behavior: 'none' },
7589
+ })
7590
+ const [chartData] = useState([
7591
+ { x: 0, y: 0, value: 100, name: 'edge_bl', fillColor: '#f44336' }, // 좌하단
7592
+ { x: 0, y: 10, value: 100, name: 'edge_tl', fillColor: '#ff9800' }, // 좌상단
7593
+ { x: 10, y: 0, value: 100, name: 'edge_br', fillColor: '#4caf50' }, // 우하단
7594
+ { x: 10, y: 10, value: 100, name: 'edge_tr', fillColor: '#2196f3' }, // 우상단
7595
+ { x: 5, y: 5, value: 200, name: 'center', fillColor: '#9c27b0' },
7596
+ ])
7597
+ `,
7598
+ code: `<>
7599
+ {/* Before — extraMin/extraMax 없음 */}
7600
+ <OpsnowCommonBubbleChart
7601
+ chartId={chartIdA}
7602
+ chartRef={chartRefA}
7603
+ chartProps={chartPropsA}
7604
+ chartData={chartData}
7605
+ />
7606
+ {/* After — extraMin/extraMax=0.1 (가장자리 여백) */}
7607
+ <OpsnowCommonBubbleChart
7608
+ chartId={chartIdB}
7609
+ chartRef={chartRefB}
7610
+ chartProps={chartPropsB}
7611
+ chartData={chartData}
7612
+ />
7613
+ </>`
7614
+ },
7615
+ ];
@@ -105,6 +105,7 @@ const XyMultiChartSchema = z.object({
105
105
  "type": "circle", // 불릿 타입: 'circle' | 'square' | 'triangle' | 'label'
106
106
  "lineOnly": true, // 라인만 표시 여부
107
107
  "cursorOverStyle": "pointer", // 마우스 오버시 커서 스타일
108
+ "hitRadius": 14, // 클릭/호버 감지 영역(hit area) 확장 반경(px). bullet 의 시각적 크기는 그대로 두고, 클릭 가능한 hit area 만 넓힘. 작은 점(작은 bullet) 도 클릭하기 쉽게 만들 때 사용. anomaly/이상치 마커처럼 시각적으론 작아야 하지만 인터랙션은 쉬워야 하는 경우 유용.
108
109
  "customField": "custom_bullet", // 불릿 커스텀 필드
109
110
  "locationX": 0.5, // 불릿 X축 위치 (0~1, type이 'label'일 때 사용)
110
111
  "locationY": 1, // 불릿 Y축 위치 (0~1, type이 'label'일 때 사용)
@@ -1503,6 +1504,94 @@ export const HeatmapChartSchema = z.object({
1503
1504
  isDarkMode: z.boolean().optional().describe("다크 모드 활성화 여부"),
1504
1505
  onChartClick: z.string().optional().describe('셀 클릭 시 호출되는 콜백 함수(stringified). 클릭 시 { xField, yField, valueField, from: "heatmap" } 객체를 전달합니다.')
1505
1506
  });
1507
+ // opsnow-common-bubble-chart
1508
+ export const BubbleChartSchema = z.object({
1509
+ chartId: z.string().describe("차트의 고유 식별자"),
1510
+ chartProps: z.object({}).describe(`
1511
+ 다음 정의된 형식 예를 보고 버블 차트 속성을 설정하세요.
1512
+ **유효한 JSON 형식이어야 합니다.**
1513
+ {
1514
+ // 차트 기본 설정
1515
+ "chart": {
1516
+ "paddingTop": 0,
1517
+ "paddingBottom": 0,
1518
+ "paddingLeft": 0,
1519
+ "paddingRight": 0
1520
+ },
1521
+
1522
+ // X축 설정 (수치 축)
1523
+ "xAxis": {
1524
+ "gridHidden": false, // 격자선 숨김 여부
1525
+ "labelHidden": false, // 라벨 숨김 여부
1526
+ "extraMin": 0.1, // 축 최소쪽 여백 비율 (0~1) — bullet 이 가장자리에 잘리지 않도록 패딩
1527
+ "extraMax": 0.1, // 축 최대쪽 여백 비율 (0~1)
1528
+ "label": { "fontSize": 11 }
1529
+ },
1530
+
1531
+ // Y축 설정 (수치 축)
1532
+ "yAxis": {
1533
+ "gridHidden": false,
1534
+ "labelHidden": false,
1535
+ "extraMin": 0.1,
1536
+ "extraMax": 0.1,
1537
+ "label": { "fontSize": 11 }
1538
+ },
1539
+
1540
+ // 시리즈 설정 (단일 BubbleSeries)
1541
+ "series": {
1542
+ "valueXField": "x", // X 값 필드 (chartData 의 필드명)
1543
+ "valueYField": "y", // Y 값 필드
1544
+ "sizeField": "value", // 버블 크기에 매핑할 값 필드 (생략 시 모든 버블이 동일 크기)
1545
+ "minBulletSize": 6, // 버블 최소 크기 (px)
1546
+ "maxBulletSize": 40, // 버블 최대 크기 (px)
1547
+ "colorField": "fillColor",// 데이터 항목별 색상을 지정하는 필드 (CSS 색상 문자열). 미지정 시 자동 색상 할당
1548
+ "fillOpacity": 0.7, // 버블 채우기 투명도 (0~1)
1549
+ "tooltip": {
1550
+ "header": { "name": "[bold]{name}[/]" }, // 헤더 포맷 ({} 로 필드 참조, [bold]...[/] 굵게)
1551
+ "body": {
1552
+ "value": "{l.label}: {valueX}\\n{l.label2}: {valueY}\\n{l.label3}: {value}" // \\n 으로 줄바꿈, {l.xxx} locale 참조
1553
+ }
1554
+ }
1555
+ },
1556
+
1557
+ // 커서 설정
1558
+ "cursor": {
1559
+ "behavior": "none", // 'none' | 'selectX' | 'selectY' | 'zoomX' | 'zoomY' | 'zoomXY'
1560
+ "visibleX": true, // X 가이드라인 표시
1561
+ "visibleY": true // Y 가이드라인 표시
1562
+ }
1563
+ }
1564
+ `),
1565
+ chartData: z.array(z.record(z.any())).optional().describe(`버블 차트에 표시할 데이터 배열입니다. 각 항목은 X값, Y값, (선택) 크기값/색상값을 포함합니다.
1566
+ 예시)
1567
+ [
1568
+ { "x": 83, "y": 78.2, "value": 330000, "name": "country_us", "fillColor": "#4caf50" },
1569
+ { "x": 64, "y": 75.4, "value": 1400000, "name": "country_cn", "fillColor": "#f44336" },
1570
+ { "x": 42, "y": 84.2, "value": 125000, "name": "country_jp", "fillColor": "#2196f3" }
1571
+ ]`),
1572
+ chartLocaleProps: z.array(z.object({
1573
+ name: z.string(),
1574
+ locale: z.string()
1575
+ })).optional().describe(`차트에 적용할 다국어 플레이스홀더 목록입니다. {l.xxx} 형태로 chartProps 의 tooltip 에서 참조합니다.
1576
+ 예시)
1577
+ [
1578
+ { "name": "l.gdpIndex", "locale": "GDP 지수" },
1579
+ { "name": "l.lifeExp", "locale": "기대 수명" },
1580
+ { "name": "l.population", "locale": "인구" }
1581
+ ]`),
1582
+ chartLocaleMessage: z.array(z.object({
1583
+ name: z.string().describe("chartData 항목의 name 키 (또는 카테고리 키)"),
1584
+ locale: z.string().describe("표시할 다국어 텍스트")
1585
+ })).optional().describe(`데이터 항목의 name 을 다국어 텍스트로 치환합니다. 툴팁 헤더({name}) 에 표시되는 텍스트를 언어별로 바꿀 때 사용합니다.
1586
+ 예시)
1587
+ [
1588
+ { "name": "country_us", "locale": "미국" },
1589
+ { "name": "country_cn", "locale": "중국" }
1590
+ ]`),
1591
+ langCd: z.enum(['ko', 'en', 'ja', 'zh', 'ar']).optional().describe("언어 코드"),
1592
+ onChartClick: z.string().optional().describe(`버블 클릭 시 호출되는 콜백 함수(stringified). 클릭한 데이터 항목 객체를 인자로 전달합니다.
1593
+ 예시) "(data) => { console.log(data) }"`)
1594
+ });
1506
1595
  // Chart 컴포넌트 함수 - 배열 반환
1507
1596
  export function createChartComponent() {
1508
1597
  return [
@@ -1858,5 +1947,52 @@ export function createChartComponent() {
1858
1947
  };
1859
1948
  }
1860
1949
  },
1950
+ {
1951
+ name: "createBubbleChart",
1952
+ description: `버블 차트 컴포넌트 - 3차원(X, Y, 크기) 데이터 시각화 지원
1953
+
1954
+ **이 차트 컴포넌트는 amCharts5를 기반으로 구현되었습니다.**
1955
+
1956
+ X축/Y축 모두 수치(value) 축이며, 각 데이터 항목을 버블(원)로 표시합니다.
1957
+ sizeField 로 버블 크기, colorField 로 항목별 색상을 지정할 수 있고,
1958
+ colorField 미지정 시 자동 색상 할당이 동작합니다.
1959
+ GDP 분포(국가별 X=지수, Y=수명, size=인구), 클러스터 분포, 산점도(scatter) 형태의
1960
+ 3차원 데이터 시각화에 적합합니다.
1961
+
1962
+ **import:**
1963
+ \`\`\`javascript
1964
+ import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
1965
+ const { OpsnowCommonBubbleChart } = useCommonComponents();
1966
+ \`\`\``,
1967
+ parameters: BubbleChartSchema,
1968
+ handler: async (args) => {
1969
+ const props = [];
1970
+ if (args.chartId)
1971
+ props.push(`chartId="${args.chartId}"`);
1972
+ if (args.chartProps)
1973
+ props.push(`chartProps={${args.chartProps}}`);
1974
+ if (args.chartData)
1975
+ props.push(`chartData={${args.chartData}}`);
1976
+ else
1977
+ props.push(`chartData={[]}`);
1978
+ if (args.chartLocaleProps)
1979
+ props.push(`chartLocaleProps={${args.chartLocaleProps}}`);
1980
+ if (args.chartLocaleMessage)
1981
+ props.push(`chartLocaleMessage={${args.chartLocaleMessage}}`);
1982
+ if (args.langCd)
1983
+ props.push(`langCd="${args.langCd}"`);
1984
+ if (args.onChartClick)
1985
+ props.push(`onChartClick={${args.onChartClick}}`);
1986
+ const code = `<OpsnowCommonBubbleChart ${props.join(' ')} />`;
1987
+ return {
1988
+ content: [
1989
+ {
1990
+ type: "text",
1991
+ text: `\`\`\`jsx\n${code}\n\`\`\``
1992
+ }
1993
+ ]
1994
+ };
1995
+ }
1996
+ },
1861
1997
  ];
1862
1998
  }
@@ -1,7 +1,7 @@
1
1
  import { ButtonExamples, BadgeExamples, TextareaExamples, SwitchExamples, ChipExamples, TextFieldExamples, AvatarExamples, CheckboxExamples, RadioGroupExamples, CollapseExamples, SliderExamples, LinkExamples, TreeViewExamples, InsightCardExamples, InsightContentExamples, ToggleButtonExamples } from "./examples/opsnow-common-forms-examples-data.js";
2
2
  import { IconExamples, MuiIconExamples } from "./examples/opsnow-common-icons-examples-data.js";
3
3
  import { CalendarExamples } from "./examples/opsnow-common-calendar-examples-data.js";
4
- import { GaugeChartExamples, PieChartExamples, BarChartExamples, LineChartExamples, StackChartExamples, XyMultiChartExamples } from "./examples/opsnow-common-chart-examples-data.js";
4
+ import { GaugeChartExamples, PieChartExamples, BarChartExamples, LineChartExamples, StackChartExamples, XyMultiChartExamples, HeatmapChartExamples, BubbleChartExamples } from "./examples/opsnow-common-chart-examples-data.js";
5
5
  import { TooltipExamples } from "./examples/opsnow-common-tooltip-examples-data.js";
6
6
  import { DataGridExamples } from "./examples/opsnow-common-grid-examples-data.js";
7
7
  import { PopupExamples } from "./examples/opsnow-common-popup-examples-data.js";
@@ -44,6 +44,8 @@ const EXAMPLES_MAP = {
44
44
  LineChart: LineChartExamples,
45
45
  StackChart: StackChartExamples,
46
46
  XyMultiChart: XyMultiChartExamples,
47
+ HeatmapChart: HeatmapChartExamples,
48
+ BubbleChart: BubbleChartExamples,
47
49
  Tooltip: TooltipExamples,
48
50
  DataGrid: DataGridExamples,
49
51
  Popup: PopupExamples,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opsnow-mcp/opsnow-mcp-common-ui-server",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "bin": {