@moda-chart/core 0.1.2

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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/dist/conformance.d.ts +40 -0
  4. package/dist/conformance.d.ts.map +1 -0
  5. package/dist/conformance.js +1608 -0
  6. package/dist/conformance.js.map +1 -0
  7. package/dist/core.d.ts +448 -0
  8. package/dist/core.d.ts.map +1 -0
  9. package/dist/core.js +6026 -0
  10. package/dist/core.js.map +1 -0
  11. package/dist/geo.d.ts +85 -0
  12. package/dist/geo.d.ts.map +1 -0
  13. package/dist/geo.js +264 -0
  14. package/dist/geo.js.map +1 -0
  15. package/dist/geometry.d.ts +29 -0
  16. package/dist/geometry.d.ts.map +1 -0
  17. package/dist/geometry.js +92 -0
  18. package/dist/geometry.js.map +1 -0
  19. package/dist/hierarchy.d.ts +142 -0
  20. package/dist/hierarchy.d.ts.map +1 -0
  21. package/dist/hierarchy.js +422 -0
  22. package/dist/hierarchy.js.map +1 -0
  23. package/dist/index.d.ts +18 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +12 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/maps/world.d.ts +9 -0
  28. package/dist/maps/world.d.ts.map +1 -0
  29. package/dist/maps/world.js +9 -0
  30. package/dist/maps/world.js.map +1 -0
  31. package/dist/mount.d.ts +75 -0
  32. package/dist/mount.d.ts.map +1 -0
  33. package/dist/mount.js +795 -0
  34. package/dist/mount.js.map +1 -0
  35. package/dist/scales.d.ts +22 -0
  36. package/dist/scales.d.ts.map +1 -0
  37. package/dist/scales.js +118 -0
  38. package/dist/scales.js.map +1 -0
  39. package/dist/sparkline.d.ts +4 -0
  40. package/dist/sparkline.d.ts.map +1 -0
  41. package/dist/sparkline.js +62 -0
  42. package/dist/sparkline.js.map +1 -0
  43. package/dist/styles.css +989 -0
  44. package/dist/svg.d.ts +21 -0
  45. package/dist/svg.d.ts.map +1 -0
  46. package/dist/svg.js +1022 -0
  47. package/dist/svg.js.map +1 -0
  48. package/dist/text.d.ts +23 -0
  49. package/dist/text.d.ts.map +1 -0
  50. package/dist/text.js +67 -0
  51. package/dist/text.js.map +1 -0
  52. package/dist/types.d.ts +1881 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +8 -0
  55. package/dist/types.js.map +1 -0
  56. package/dist/xml.d.ts +13 -0
  57. package/dist/xml.d.ts.map +1 -0
  58. package/dist/xml.js +109 -0
  59. package/dist/xml.js.map +1 -0
  60. package/package.json +44 -0
@@ -0,0 +1,989 @@
1
+ /* @moda-chart/core 공통 스타일 — 어댑터는 @import로 재사용한다.
2
+ * 색상은 --chart-* CSS 변수로 노출해 테마를 연다.
3
+ * .mc-root[data-theme="dark"]가 다크 모드 변수를 덮어쓴다. */
4
+
5
+ .mc-root {
6
+ --chart-bg: #ffffff;
7
+ --chart-text-color: #1e293b;
8
+ --chart-text-muted: #64748b;
9
+ --chart-border-color: #e2e8f0;
10
+ --chart-grid-color: #e2e8f0;
11
+ --chart-axis-color: #cbd5e1;
12
+ --chart-tooltip-bg: #0f172a;
13
+ --chart-tooltip-color: #f8fafc;
14
+ --chart-selection-color: rgba(37, 99, 235, 0.12);
15
+ --chart-focus-color: #0f172a;
16
+ --chart-mark-color: #f43f5e;
17
+ --chart-mark-band-color: rgba(244, 63, 94, 0.08);
18
+ --chart-up-color: #16a34a;
19
+ --chart-down-color: #dc2626;
20
+ --chart-waterfall-line-color: #94a3b8;
21
+ --chart-heat-from: #dbeafe;
22
+ --chart-heat-to: #1d4ed8;
23
+ --chart-annotation-color: #475569;
24
+ --chart-error-color: #64748b;
25
+ --chart-nav-bg: #f1f5f9;
26
+ --chart-nav-handle: #94a3b8;
27
+ --chart-map-from: #dbeafe;
28
+ --chart-map-to: #1d4ed8;
29
+ --chart-map-empty: #e2e8f0;
30
+ --chart-map-border: #ffffff;
31
+ --chart-node-border: #ffffff;
32
+ --chart-link-opacity: 0.45;
33
+ --chart-gauge-track: #e2e8f0;
34
+ --chart-gauge-needle: #475569;
35
+ --chart-menu-bg: #ffffff;
36
+ --chart-menu-hover: #f1f5f9;
37
+ --chart-org-link-color: #94a3b8;
38
+ --chart-map-line-color: #64748b;
39
+ --chart-draw-color: #7c3aed;
40
+ --chart-loading-bg: rgba(255, 255, 255, 0.7);
41
+ --chart-palette-1: #2563eb;
42
+ --chart-palette-2: #16a34a;
43
+ --chart-palette-3: #f59e0b;
44
+ --chart-palette-4: #dc2626;
45
+ --chart-palette-5: #7c3aed;
46
+ --chart-palette-6: #0891b2;
47
+ --chart-palette-7: #db2777;
48
+ --chart-palette-8: #65a30d;
49
+
50
+ position: relative;
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 6px;
54
+ color: var(--chart-text-color);
55
+ font: inherit;
56
+ outline: none;
57
+ max-width: 100%;
58
+ }
59
+
60
+ .mc-root[data-theme="dark"] {
61
+ --chart-bg: #0f172a;
62
+ --chart-text-color: #e2e8f0;
63
+ --chart-text-muted: #94a3b8;
64
+ --chart-border-color: #334155;
65
+ --chart-grid-color: #1e293b;
66
+ --chart-axis-color: #475569;
67
+ --chart-tooltip-bg: #f1f5f9;
68
+ --chart-tooltip-color: #0f172a;
69
+ --chart-selection-color: rgba(96, 165, 250, 0.18);
70
+ --chart-focus-color: #f8fafc;
71
+ --chart-mark-color: #fb7185;
72
+ --chart-mark-band-color: rgba(251, 113, 133, 0.14);
73
+ --chart-up-color: #4ade80;
74
+ --chart-down-color: #f87171;
75
+ --chart-waterfall-line-color: #64748b;
76
+ --chart-heat-from: #1e293b;
77
+ --chart-heat-to: #38bdf8;
78
+ --chart-annotation-color: #94a3b8;
79
+ --chart-error-color: #94a3b8;
80
+ --chart-nav-bg: #1e293b;
81
+ --chart-nav-handle: #475569;
82
+ --chart-map-from: #1e293b;
83
+ --chart-map-to: #38bdf8;
84
+ --chart-map-empty: #334155;
85
+ --chart-map-border: #0f172a;
86
+ --chart-node-border: #0f172a;
87
+ --chart-gauge-track: #334155;
88
+ --chart-gauge-needle: #cbd5e1;
89
+ --chart-menu-bg: #1e293b;
90
+ --chart-menu-hover: #334155;
91
+ --chart-org-link-color: #64748b;
92
+ --chart-map-line-color: #94a3b8;
93
+ --chart-draw-color: #a78bfa;
94
+ --chart-loading-bg: rgba(15, 23, 42, 0.7);
95
+ --chart-palette-1: #60a5fa;
96
+ --chart-palette-2: #4ade80;
97
+ --chart-palette-3: #fbbf24;
98
+ --chart-palette-4: #f87171;
99
+ --chart-palette-5: #a78bfa;
100
+ --chart-palette-6: #22d3ee;
101
+ --chart-palette-7: #f472b6;
102
+ --chart-palette-8: #a3e635;
103
+ }
104
+
105
+ .mc-root:focus-visible {
106
+ outline: 2px solid var(--chart-palette-1);
107
+ outline-offset: 2px;
108
+ }
109
+
110
+ /* 제목/부제목 — 없으면 hidden으로 렌더된다 */
111
+ .mc-title {
112
+ font-size: 15px;
113
+ font-weight: 700;
114
+ color: var(--chart-text-color);
115
+ }
116
+
117
+ .mc-subtitle {
118
+ font-size: 12px;
119
+ color: var(--chart-text-muted);
120
+ }
121
+
122
+ /* 범례 위치 — left/right면 세로 배치 */
123
+ .mc-root[data-legend="top"],
124
+ .mc-root[data-legend="bottom"] {
125
+ flex-direction: column;
126
+ }
127
+ .mc-root[data-legend="left"],
128
+ .mc-root[data-legend="right"] {
129
+ flex-direction: row;
130
+ align-items: flex-start;
131
+ }
132
+ .mc-root[data-legend="left"] .mc-legend {
133
+ order: -1;
134
+ }
135
+ .mc-root[data-legend="top"] .mc-legend {
136
+ order: -1;
137
+ }
138
+ .mc-root[data-legend="right"] .mc-legend {
139
+ order: 1;
140
+ }
141
+
142
+ .mc-toolbar {
143
+ display: flex;
144
+ justify-content: flex-end;
145
+ gap: 6px;
146
+ }
147
+
148
+ .mc-toolbar button {
149
+ font: inherit;
150
+ font-size: 11px;
151
+ padding: 3px 10px;
152
+ border: 1px solid var(--chart-border-color);
153
+ border-radius: 5px;
154
+ background: var(--chart-bg);
155
+ color: var(--chart-text-muted);
156
+ cursor: pointer;
157
+ }
158
+
159
+ .mc-toolbar button:hover:not(:disabled) {
160
+ color: var(--chart-text-color);
161
+ border-color: var(--chart-axis-color);
162
+ }
163
+
164
+ .mc-toolbar button:disabled {
165
+ opacity: 0.4;
166
+ cursor: default;
167
+ }
168
+
169
+ .mc-viewport {
170
+ position: relative;
171
+ }
172
+
173
+ .mc-svg {
174
+ display: block;
175
+ max-width: 100%;
176
+ }
177
+
178
+ .mc-axis-line,
179
+ .mc-tick-line {
180
+ stroke: var(--chart-axis-color);
181
+ }
182
+
183
+ .mc-grid-line {
184
+ stroke: var(--chart-grid-color);
185
+ stroke-dasharray: 2 3;
186
+ }
187
+
188
+ .mc-tick-label,
189
+ .mc-axis-label {
190
+ fill: var(--chart-text-muted);
191
+ font-size: 11px;
192
+ }
193
+
194
+ .mc-axis-label {
195
+ font-weight: 600;
196
+ }
197
+
198
+ .mc-line {
199
+ stroke-width: 2;
200
+ stroke-linejoin: round;
201
+ stroke-linecap: round;
202
+ }
203
+
204
+ .mc-area {
205
+ opacity: 0.25;
206
+ }
207
+
208
+ .mc-point {
209
+ stroke: var(--chart-bg);
210
+ stroke-width: 1.5;
211
+ }
212
+
213
+ .mc-bubble {
214
+ fill-opacity: 0.7;
215
+ }
216
+
217
+ .mc-heat-cell {
218
+ stroke: var(--chart-bg);
219
+ stroke-width: 1;
220
+ }
221
+
222
+ .mc-slice {
223
+ stroke: var(--chart-bg);
224
+ }
225
+
226
+ .mc-point.mc-focused,
227
+ .mc-bar.mc-focused,
228
+ .mc-slice.mc-focused,
229
+ .mc-heat-cell.mc-focused {
230
+ stroke: var(--chart-focus-color);
231
+ stroke-width: 2.5;
232
+ }
233
+
234
+ .mc-point.mc-dimmed,
235
+ .mc-bar.mc-dimmed,
236
+ .mc-slice.mc-dimmed,
237
+ .mc-heat-cell.mc-dimmed {
238
+ opacity: 0.35;
239
+ }
240
+
241
+ /* allowPointSelect — 클릭으로 선택된 요소 */
242
+ .mc-point.mc-selected,
243
+ .mc-bar.mc-selected,
244
+ .mc-slice.mc-selected,
245
+ .mc-bubble.mc-selected,
246
+ .mc-heat-cell.mc-selected {
247
+ stroke: var(--chart-focus-color);
248
+ stroke-width: 2;
249
+ }
250
+
251
+ /* 워드클라우드 — 카테고리=단어, 값=크기 */
252
+ .mc-word {
253
+ text-anchor: middle;
254
+ dominant-baseline: central;
255
+ font-weight: 600;
256
+ }
257
+ .mc-word.mc-dimmed {
258
+ opacity: 0.35;
259
+ }
260
+ .mc-word.mc-selected {
261
+ text-decoration: underline;
262
+ }
263
+
264
+ /* 레이더 — 극좌표 그리드 + 폴리곤 */
265
+ .mc-radar-ring,
266
+ .mc-radar-spoke {
267
+ stroke: var(--chart-grid-color);
268
+ }
269
+ .mc-radar-ring-label,
270
+ .mc-spoke-label {
271
+ fill: var(--chart-text-muted);
272
+ font-size: 10px;
273
+ }
274
+ .mc-radar {
275
+ stroke-width: 2;
276
+ stroke-linejoin: round;
277
+ }
278
+ /* radar-area는 패턴/팔레트 fill을 쓰고 반투명으로 */
279
+ .mc-radar-area {
280
+ fill-opacity: 0.18;
281
+ }
282
+ .mc-range-area {
283
+ fill-opacity: 0.3;
284
+ }
285
+
286
+ /* 캔들스틱 — up/down 톤은 --chart-up/down-color(waterfall과 공유) */
287
+ .mc-candle-body {
288
+ stroke-width: 1;
289
+ }
290
+ .mc-candle-wick {
291
+ stroke-width: 1.2;
292
+ }
293
+ .mc-candle-up .mc-candle-wick {
294
+ stroke: var(--chart-up-color);
295
+ }
296
+ .mc-candle-down .mc-candle-wick {
297
+ stroke: var(--chart-down-color);
298
+ }
299
+ .mc-candle.mc-focused .mc-candle-body,
300
+ .mc-range-bar.mc-focused {
301
+ stroke: var(--chart-focus-color);
302
+ stroke-width: 2.5;
303
+ }
304
+ .mc-candle.mc-dimmed,
305
+ .mc-range-bar.mc-dimmed {
306
+ opacity: 0.35;
307
+ }
308
+ .mc-range-bar.mc-selected {
309
+ stroke: var(--chart-focus-color);
310
+ stroke-width: 2;
311
+ }
312
+ .mc-candle.mc-selected .mc-candle-body {
313
+ stroke: var(--chart-focus-color);
314
+ stroke-width: 2;
315
+ }
316
+
317
+ /* 에러바 — 포인트 값±오차 오버레이 */
318
+ .mc-errors {
319
+ pointer-events: none;
320
+ }
321
+ .mc-error {
322
+ stroke: var(--chart-error-color);
323
+ stroke-width: 1.4;
324
+ }
325
+
326
+ /* 추세선 — series.trend 오버레이 (선색은 시리즈 색상으로 인라인) */
327
+ .mc-trendlines {
328
+ pointer-events: none;
329
+ }
330
+ .mc-trendline {
331
+ stroke-width: 1.6;
332
+ stroke-dasharray: 6 3;
333
+ }
334
+
335
+ /* 네비게이터 — 플롯 아래 미니맵. 창 드래그·핸들 리사이즈·트랙 점프 */
336
+ .mc-navigator {
337
+ pointer-events: all;
338
+ }
339
+ .mc-nav-bg {
340
+ fill: var(--chart-nav-bg);
341
+ }
342
+ .mc-nav-track {
343
+ stroke-width: 1.5;
344
+ pointer-events: none;
345
+ }
346
+ .mc-nav-window {
347
+ fill: var(--chart-selection-color);
348
+ stroke: var(--chart-palette-1);
349
+ stroke-opacity: 0.4;
350
+ cursor: grab;
351
+ }
352
+ .mc-nav-handle {
353
+ fill: var(--chart-nav-handle);
354
+ cursor: ew-resize;
355
+ }
356
+
357
+ /* 지도 — 지역 폴리곤 (choropleth). 데이터 없음은 --chart-map-empty */
358
+ .mc-map-region {
359
+ stroke: var(--chart-map-border);
360
+ stroke-width: 0.5;
361
+ }
362
+ .mc-map-no-data {
363
+ fill: var(--chart-map-empty);
364
+ }
365
+ .mc-map-region.mc-focused {
366
+ stroke: var(--chart-focus-color);
367
+ stroke-width: 2;
368
+ }
369
+ .mc-map-region.mc-dimmed {
370
+ opacity: 0.35;
371
+ }
372
+ .mc-map-region.mc-selected {
373
+ stroke: var(--chart-focus-color);
374
+ stroke-width: 1.8;
375
+ }
376
+ .mc-map-scale-bar {
377
+ stroke: var(--chart-border-color);
378
+ stroke-width: 0.5;
379
+ }
380
+ .mc-map-scale-label {
381
+ fill: var(--chart-text-muted);
382
+ font-size: 10px;
383
+ }
384
+
385
+ /* 계층 차트 — sunburst 섹터 / treemap 노드 (노드 경계는 --chart-node-border) */
386
+ .mc-sunburst-node,
387
+ .mc-treemap-node,
388
+ .mc-sankey-node,
389
+ .mc-chord-group,
390
+ .mc-nightingale-node,
391
+ .mc-radial-bar,
392
+ .mc-radial-column {
393
+ stroke: var(--chart-node-border);
394
+ stroke-width: 1;
395
+ }
396
+ .mc-sunburst-node.mc-focused,
397
+ .mc-treemap-node.mc-focused,
398
+ .mc-sankey-node.mc-focused,
399
+ .mc-chord-group.mc-focused,
400
+ .mc-nightingale-node.mc-focused,
401
+ .mc-radial-bar.mc-focused,
402
+ .mc-radial-column.mc-focused {
403
+ stroke: var(--chart-focus-color);
404
+ stroke-width: 2.5;
405
+ }
406
+ .mc-sunburst-node.mc-dimmed,
407
+ .mc-treemap-node.mc-dimmed,
408
+ .mc-sankey-node.mc-dimmed,
409
+ .mc-chord-group.mc-dimmed,
410
+ .mc-nightingale-node.mc-dimmed,
411
+ .mc-radial-bar.mc-dimmed,
412
+ .mc-radial-column.mc-dimmed {
413
+ opacity: 0.35;
414
+ }
415
+ .mc-sunburst-node.mc-selected,
416
+ .mc-treemap-node.mc-selected,
417
+ .mc-sankey-node.mc-selected,
418
+ .mc-chord-group.mc-selected,
419
+ .mc-nightingale-node.mc-selected,
420
+ .mc-radial-bar.mc-selected,
421
+ .mc-radial-column.mc-selected,
422
+ .mc-gauge-value.mc-selected {
423
+ stroke: var(--chart-focus-color);
424
+ stroke-width: 2;
425
+ }
426
+
427
+ /* 게이지 — 배경 트랙/바늘/중앙 라벨 */
428
+ .mc-gauge-track {
429
+ fill: var(--chart-gauge-track);
430
+ }
431
+ .mc-gauge-needle {
432
+ stroke: var(--chart-gauge-needle);
433
+ stroke-width: 2.5;
434
+ }
435
+ .mc-gauge-hub {
436
+ fill: var(--chart-gauge-needle);
437
+ }
438
+ .mc-gauge-target {
439
+ stroke: var(--chart-mark-color);
440
+ stroke-width: 2;
441
+ }
442
+ .mc-gauge-label {
443
+ fill: var(--chart-text-color);
444
+ font-size: 20px;
445
+ font-weight: 600;
446
+ }
447
+ .mc-gauge-tick {
448
+ fill: var(--chart-text-muted);
449
+ font-size: 10px;
450
+ }
451
+ .mc-gauge-value.mc-focused {
452
+ stroke: var(--chart-focus-color);
453
+ stroke-width: 2.5;
454
+ }
455
+
456
+ /* 플로우 — 리본은 노드 색을 계승하고 반투명 */
457
+ .mc-sankey-link,
458
+ .mc-chord-ribbon {
459
+ fill-opacity: var(--chart-link-opacity);
460
+ stroke: none;
461
+ }
462
+
463
+ /* 인라인 주석 — annotations 옵션 */
464
+ .mc-annotations {
465
+ pointer-events: none;
466
+ }
467
+ .mc-annotation-dot {
468
+ fill: var(--chart-annotation-color);
469
+ }
470
+ .mc-annotation-label {
471
+ fill: var(--chart-annotation-color);
472
+ font-size: 10px;
473
+ }
474
+
475
+ /* 값 라벨 — dataLabels 옵션 */
476
+ .mc-data-label {
477
+ fill: var(--chart-text-muted);
478
+ font-size: 10px;
479
+ pointer-events: none;
480
+ }
481
+
482
+ /* 값 축 기준선/영역 — markLines/markBands 옵션 */
483
+ .mc-mark-line {
484
+ stroke: var(--chart-mark-color);
485
+ stroke-width: 1;
486
+ stroke-dasharray: 5 4;
487
+ pointer-events: none;
488
+ }
489
+
490
+ .mc-mark-band {
491
+ fill: var(--chart-mark-band-color);
492
+ pointer-events: none;
493
+ }
494
+
495
+ .mc-waterfall-line {
496
+ stroke: var(--chart-waterfall-line-color);
497
+ stroke-width: 1;
498
+ stroke-dasharray: 3 3;
499
+ pointer-events: none;
500
+ }
501
+
502
+ .mc-mark-label {
503
+ fill: var(--chart-mark-color);
504
+ font-size: 10px;
505
+ pointer-events: none;
506
+ }
507
+
508
+ /* 로딩 오버레이 — setLoading(true) */
509
+ .mc-loading {
510
+ position: absolute;
511
+ inset: 0;
512
+ display: flex;
513
+ align-items: center;
514
+ justify-content: center;
515
+ background: var(--chart-loading-bg);
516
+ z-index: 3;
517
+ }
518
+
519
+ .mc-loading[hidden] {
520
+ display: none;
521
+ }
522
+
523
+ .mc-spinner {
524
+ width: 26px;
525
+ height: 26px;
526
+ border: 3px solid var(--chart-grid-color);
527
+ border-top-color: var(--chart-palette-1);
528
+ border-radius: 50%;
529
+ animation: mc-spin 0.8s linear infinite;
530
+ }
531
+
532
+ @keyframes mc-spin {
533
+ to {
534
+ transform: rotate(360deg);
535
+ }
536
+ }
537
+
538
+ .mc-crosshair {
539
+ stroke: var(--chart-text-muted);
540
+ stroke-dasharray: 4 3;
541
+ pointer-events: none;
542
+ }
543
+
544
+ .mc-selection {
545
+ fill: var(--chart-selection-color);
546
+ pointer-events: none;
547
+ }
548
+
549
+ .mc-empty {
550
+ fill: var(--chart-text-muted);
551
+ font-size: 13px;
552
+ }
553
+
554
+ .mc-overlay {
555
+ position: absolute;
556
+ cursor: crosshair;
557
+ touch-action: none;
558
+ }
559
+
560
+ .mc-tooltip {
561
+ position: absolute;
562
+ transform: translate(-50%, calc(-100% - 8px));
563
+ background: var(--chart-tooltip-bg);
564
+ color: var(--chart-tooltip-color);
565
+ font-size: 12px;
566
+ padding: 6px 10px;
567
+ border-radius: 6px;
568
+ pointer-events: none;
569
+ white-space: nowrap;
570
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
571
+ z-index: 2;
572
+ }
573
+
574
+ .mc-tooltip.mc-flip-x {
575
+ transform: translate(-90%, calc(-100% - 8px));
576
+ }
577
+
578
+ .mc-tooltip[hidden] {
579
+ display: none;
580
+ }
581
+
582
+ .mc-tooltip-title {
583
+ font-weight: 600;
584
+ margin-bottom: 4px;
585
+ }
586
+
587
+ .mc-tooltip-row {
588
+ display: flex;
589
+ align-items: center;
590
+ gap: 6px;
591
+ }
592
+
593
+ .mc-tooltip-swatch {
594
+ width: 10px;
595
+ height: 10px;
596
+ border-radius: 2px;
597
+ }
598
+
599
+ .mc-tooltip-value {
600
+ margin-left: auto;
601
+ font-variant-numeric: tabular-nums;
602
+ }
603
+
604
+ .mc-legend {
605
+ display: flex;
606
+ flex-wrap: wrap;
607
+ gap: 4px 14px;
608
+ padding: 2px 0;
609
+ }
610
+
611
+ .mc-root[data-legend="left"] .mc-legend,
612
+ .mc-root[data-legend="right"] .mc-legend {
613
+ flex-direction: column;
614
+ }
615
+
616
+ .mc-legend-item {
617
+ display: inline-flex;
618
+ align-items: center;
619
+ gap: 6px;
620
+ font: inherit;
621
+ font-size: 12px;
622
+ background: none;
623
+ border: none;
624
+ padding: 2px 4px;
625
+ color: var(--chart-text-color);
626
+ cursor: pointer;
627
+ border-radius: 4px;
628
+ }
629
+
630
+ .mc-legend-item:hover {
631
+ background: var(--chart-grid-color);
632
+ }
633
+
634
+ .mc-legend-item.mc-hidden {
635
+ opacity: 0.45;
636
+ text-decoration: line-through;
637
+ }
638
+
639
+ .mc-legend-swatch {
640
+ width: 12px;
641
+ height: 12px;
642
+ border-radius: 3px;
643
+ }
644
+
645
+ /* 범례 체크박스 — legend.checkboxes (IBChart seriesCheckBoxClick 해당) */
646
+ .mc-legend-check {
647
+ accent-color: var(--chart-palette-1);
648
+ width: 12px;
649
+ height: 12px;
650
+ margin: 0;
651
+ cursor: pointer;
652
+ }
653
+
654
+ /* 범례 페이지네이션 — legend.pagination */
655
+ .mc-legend-prev,
656
+ .mc-legend-next {
657
+ border: none;
658
+ background: none;
659
+ font: inherit;
660
+ font-size: 13px;
661
+ color: var(--chart-text-muted);
662
+ cursor: pointer;
663
+ padding: 0 4px;
664
+ border-radius: 4px;
665
+ }
666
+
667
+ .mc-legend-prev:hover:not(:disabled),
668
+ .mc-legend-next:hover:not(:disabled) {
669
+ background: var(--chart-grid-color);
670
+ color: var(--chart-text-color);
671
+ }
672
+
673
+ .mc-legend-prev:disabled,
674
+ .mc-legend-next:disabled {
675
+ opacity: 0.35;
676
+ cursor: default;
677
+ }
678
+
679
+ .mc-legend-page {
680
+ align-self: center;
681
+ font-size: 11px;
682
+ color: var(--chart-text-muted);
683
+ }
684
+
685
+ /* 픽토그램 — type:"pictogram"의 사람 아이콘 행 (.mc-picto-*) */
686
+ .mc-picto-label {
687
+ font-size: 11px;
688
+ fill: var(--chart-text-muted);
689
+ }
690
+
691
+ .mc-picto-empty {
692
+ fill: none;
693
+ stroke: var(--chart-grid-color);
694
+ stroke-width: 0.09;
695
+ }
696
+
697
+ /* 주석 그리기 — drawing 옵션 + setDrawMode로 만든 .mc-draw-* 요소 */
698
+ .mc-root.mc-drawing .mc-overlay {
699
+ cursor: crosshair;
700
+ }
701
+
702
+ .mc-draw-seg {
703
+ stroke-width: 1.5;
704
+ }
705
+
706
+ .mc-draw-draft {
707
+ opacity: 0.75;
708
+ }
709
+
710
+ .mc-draw-label {
711
+ font-size: 10px;
712
+ fill: var(--chart-draw-color);
713
+ }
714
+
715
+ /* 컨텍스트 메뉴 — contextMenu 옵션의 우클릭 메뉴 */
716
+ .mc-menu {
717
+ position: absolute;
718
+ min-width: 140px;
719
+ background: var(--chart-menu-bg);
720
+ border: 1px solid var(--chart-border-color);
721
+ border-radius: 6px;
722
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
723
+ padding: 4px;
724
+ z-index: 4;
725
+ display: flex;
726
+ flex-direction: column;
727
+ }
728
+
729
+ .mc-menu[hidden] {
730
+ display: none;
731
+ }
732
+
733
+ .mc-menu-item {
734
+ display: block;
735
+ width: 100%;
736
+ text-align: left;
737
+ background: none;
738
+ border: none;
739
+ font: inherit;
740
+ font-size: 12px;
741
+ color: var(--chart-text-color);
742
+ padding: 6px 10px;
743
+ border-radius: 4px;
744
+ cursor: pointer;
745
+ }
746
+
747
+ .mc-menu-item:hover {
748
+ background: var(--chart-menu-hover);
749
+ }
750
+
751
+ /* 스크롤바 — 미니 시리즈 없는 얇은 줌 스트립 (네비게이터 없을 때) */
752
+ .mc-scrollbar {
753
+ pointer-events: all;
754
+ }
755
+ .mc-sb-bg {
756
+ fill: var(--chart-nav-bg);
757
+ }
758
+ .mc-sb-window {
759
+ fill: var(--chart-selection-color);
760
+ stroke: var(--chart-palette-1);
761
+ stroke-opacity: 0.4;
762
+ cursor: grab;
763
+ }
764
+ .mc-sb-handle {
765
+ fill: var(--chart-nav-handle);
766
+ cursor: ew-resize;
767
+ }
768
+
769
+ /* boxplot — 상자(Q1~Q3) + 수염 + 캡 + 중앙값. 선색은 시리즈색 인라인 */
770
+ .mc-box-body {
771
+ fill-opacity: 0.65;
772
+ stroke-width: 1;
773
+ }
774
+ .mc-box-whisker,
775
+ .mc-box-cap,
776
+ .mc-box-median {
777
+ stroke-width: 1.4;
778
+ }
779
+ .mc-box.mc-focused .mc-box-body {
780
+ stroke: var(--chart-focus-color);
781
+ stroke-width: 2.5;
782
+ }
783
+ .mc-box.mc-dimmed {
784
+ opacity: 0.35;
785
+ }
786
+ .mc-box.mc-selected .mc-box-body {
787
+ stroke: var(--chart-focus-color);
788
+ stroke-width: 2;
789
+ }
790
+
791
+ /* ohlc — 시가(좌)/종가(우) 틱 + 고저 심지. 톤은 up/down 변수 */
792
+ .mc-ohlc line {
793
+ stroke-width: 1.5;
794
+ }
795
+ .mc-ohlc-up line {
796
+ stroke: var(--chart-up-color);
797
+ }
798
+ .mc-ohlc-down line {
799
+ stroke: var(--chart-down-color);
800
+ }
801
+ .mc-ohlc.mc-focused line {
802
+ stroke: var(--chart-focus-color);
803
+ }
804
+ .mc-ohlc.mc-dimmed {
805
+ opacity: 0.35;
806
+ }
807
+ .mc-ohlc.mc-selected line {
808
+ stroke: var(--chart-focus-color);
809
+ }
810
+
811
+ /* linear-gauge — 수평 트랙 + 값 채움 + 목표 눈금 */
812
+ .mc-lg-track {
813
+ fill: var(--chart-gauge-track);
814
+ }
815
+ .mc-lg-target {
816
+ stroke: var(--chart-mark-color);
817
+ stroke-width: 2;
818
+ }
819
+ .mc-lg-label {
820
+ fill: var(--chart-text-color);
821
+ font-size: 14px;
822
+ font-weight: 600;
823
+ }
824
+ .mc-lg-tick {
825
+ fill: var(--chart-text-muted);
826
+ font-size: 10px;
827
+ }
828
+ .mc-lg-value.mc-focused {
829
+ stroke: var(--chart-focus-color);
830
+ stroke-width: 2.5;
831
+ }
832
+ .mc-lg-value.mc-selected {
833
+ stroke: var(--chart-focus-color);
834
+ stroke-width: 2;
835
+ }
836
+
837
+ /* organization — 노드 박스 + 부모→자식 엘보 커넥터 */
838
+ .mc-org-link {
839
+ stroke: var(--chart-org-link-color);
840
+ stroke-width: 1.2;
841
+ pointer-events: none;
842
+ }
843
+ .mc-org-node {
844
+ stroke: var(--chart-node-border);
845
+ stroke-width: 1;
846
+ }
847
+ .mc-org-node.mc-focused {
848
+ stroke: var(--chart-focus-color);
849
+ stroke-width: 2.5;
850
+ }
851
+ .mc-org-node.mc-dimmed {
852
+ opacity: 0.35;
853
+ }
854
+ .mc-org-node.mc-selected {
855
+ stroke: var(--chart-focus-color);
856
+ stroke-width: 2;
857
+ }
858
+
859
+ /* 지도 위성 레이어 — mapPoints 마커 / mapLines 연결선 */
860
+ .mc-map-marker {
861
+ stroke: var(--chart-map-border);
862
+ stroke-width: 1;
863
+ }
864
+ .mc-map-marker.mc-focused {
865
+ stroke: var(--chart-focus-color);
866
+ stroke-width: 2;
867
+ }
868
+ .mc-map-marker.mc-dimmed {
869
+ opacity: 0.35;
870
+ }
871
+ .mc-map-marker.mc-selected {
872
+ stroke: var(--chart-focus-color);
873
+ stroke-width: 1.8;
874
+ }
875
+ .mc-map-line {
876
+ stroke: var(--chart-map-line-color);
877
+ stroke-width: 1.5;
878
+ stroke-dasharray: 4 2;
879
+ pointer-events: none;
880
+ }
881
+
882
+ /* 지도 아바타 핀 — 프로필 이미지 원형 클립 + 외곽 링 */
883
+ .mc-map-avatar-ring {
884
+ stroke: var(--chart-map-avatar-ring, #ffffff);
885
+ stroke-width: 2;
886
+ }
887
+ .mc-map-avatar.mc-dimmed {
888
+ opacity: 0.35;
889
+ }
890
+ /* 내 위치 펄스 — 마커 주위로 퍼지는 링 */
891
+ .mc-map-pulse {
892
+ stroke: var(--chart-map-pulse, #db2777);
893
+ stroke-width: 2;
894
+ opacity: 0.9;
895
+ transform-box: fill-box;
896
+ transform-origin: center;
897
+ animation: mc-map-ping 1.6s ease-out infinite;
898
+ pointer-events: none;
899
+ }
900
+ @keyframes mc-map-ping {
901
+ from {
902
+ transform: scale(1);
903
+ opacity: 0.9;
904
+ }
905
+ to {
906
+ transform: scale(2.6);
907
+ opacity: 0;
908
+ }
909
+ }
910
+ /* 지도 클러스터 — 묶인 마커 수를 보여주는 버블 */
911
+ .mc-map-cluster-bg {
912
+ fill: var(--chart-map-cluster-bg, #475569);
913
+ stroke: var(--chart-bg);
914
+ stroke-width: 1.5;
915
+ }
916
+ .mc-map-cluster-count {
917
+ fill: var(--chart-map-cluster-color, #ffffff);
918
+ font-size: 11px;
919
+ font-weight: 600;
920
+ pointer-events: none;
921
+ }
922
+
923
+ /* 그룹 카테고리 축 — 두 번째 틱 행의 구분선과 그룹 라벨 */
924
+ .mc-tick-group-line {
925
+ stroke: var(--chart-axis-color);
926
+ }
927
+ .mc-tick-group-label {
928
+ fill: var(--chart-text-muted);
929
+ font-size: 10px;
930
+ font-weight: 600;
931
+ }
932
+
933
+ /* 진입 애니메이션 — animation:false면 .mc-animated가 붙지 않는다 */
934
+ .mc-animated .mc-series {
935
+ animation: mc-enter var(--chart-animation-duration, 300ms) ease both;
936
+ }
937
+
938
+ .mc-animated .mc-point,
939
+ .mc-animated .mc-bar,
940
+ .mc-animated .mc-slice {
941
+ transition: opacity 0.15s ease;
942
+ }
943
+
944
+ /* 데이터 갱신 전환 — animation.updates가 켜지고 데이터가 바뀐 첫 렌더에
945
+ .mc-updating이 붙는다. 진입(mc-enter)보다 짧고 옅은 페이드로 구분한다 */
946
+ .mc-animated.mc-updating .mc-series {
947
+ animation: mc-update calc(var(--chart-animation-duration, 300ms) * 0.7)
948
+ ease both;
949
+ }
950
+
951
+ /* 갱신 morph — 같은 키의 bar/point가 이전 박스에서 새 박스로 전이된다.
952
+ applyMorph가 transform을 입히고 해제하면 이 transition이 보간한다 */
953
+ .mc-animated.mc-updating .mc-bar,
954
+ .mc-animated.mc-updating .mc-point {
955
+ transition:
956
+ transform var(--chart-animation-duration, 300ms) ease,
957
+ opacity 0.15s ease;
958
+ transform-box: fill-box;
959
+ }
960
+
961
+ @keyframes mc-enter {
962
+ from {
963
+ opacity: 0;
964
+ transform: translateY(6px);
965
+ }
966
+ to {
967
+ opacity: 1;
968
+ transform: none;
969
+ }
970
+ }
971
+
972
+ @keyframes mc-update {
973
+ from {
974
+ opacity: 0.35;
975
+ }
976
+ to {
977
+ opacity: 1;
978
+ }
979
+ }
980
+
981
+ /* 스크린리더 전용 */
982
+ .mc-a11y {
983
+ position: absolute;
984
+ width: 1px;
985
+ height: 1px;
986
+ overflow: hidden;
987
+ clip: rect(0 0 0 0);
988
+ white-space: nowrap;
989
+ }