agentcss 0.0.0-stage → 0.11.3

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 (274) hide show
  1. package/01-tokens/README.md +236 -0
  2. package/01-tokens/behavior/dismissable.js +132 -0
  3. package/01-tokens/behavior/emit.js +76 -0
  4. package/01-tokens/behavior/focus-return.js +81 -0
  5. package/01-tokens/behavior/roving.js +152 -0
  6. package/01-tokens/behavior/typeahead.js +124 -0
  7. package/01-tokens/focus-ring-demo.html +133 -0
  8. package/01-tokens/focus-ring.css +102 -0
  9. package/01-tokens/page.css +244 -0
  10. package/01-tokens/polyfill.js +116 -0
  11. package/01-tokens/responsive-demo.html +171 -0
  12. package/01-tokens/scrollbar-demo.html +194 -0
  13. package/01-tokens/scrollbar.css +179 -0
  14. package/01-tokens/theme-toggle.js +103 -0
  15. package/01-tokens/tokens.css +972 -0
  16. package/01-tokens/typography.css +156 -0
  17. package/02-primitives/badge/README.md +71 -0
  18. package/02-primitives/badge/badge.css +141 -0
  19. package/02-primitives/badge/demo.html +101 -0
  20. package/02-primitives/button/README.md +99 -0
  21. package/02-primitives/button/button.css +353 -0
  22. package/02-primitives/button/demo.html +200 -0
  23. package/02-primitives/card/README.md +145 -0
  24. package/02-primitives/card/card.css +246 -0
  25. package/02-primitives/card/demo.html +170 -0
  26. package/02-primitives/choice/README.md +161 -0
  27. package/02-primitives/choice/choice.css +395 -0
  28. package/02-primitives/choice/demo.html +277 -0
  29. package/02-primitives/combobox/README.md +79 -0
  30. package/02-primitives/combobox/combobox.css +223 -0
  31. package/02-primitives/combobox/combobox.js +485 -0
  32. package/02-primitives/combobox/demo.html +109 -0
  33. package/02-primitives/date-range/README.md +100 -0
  34. package/02-primitives/date-range/date-range.css +206 -0
  35. package/02-primitives/date-range/date-range.js +301 -0
  36. package/02-primitives/date-range/demo.html +104 -0
  37. package/02-primitives/input/README.md +170 -0
  38. package/02-primitives/input/demo.html +246 -0
  39. package/02-primitives/input/input.css +239 -0
  40. package/02-primitives/popover/README.md +80 -0
  41. package/02-primitives/popover/demo.html +150 -0
  42. package/02-primitives/popover/popover.css +187 -0
  43. package/02-primitives/popover/popover.js +331 -0
  44. package/02-primitives/progress/README.md +82 -0
  45. package/02-primitives/progress/demo.html +154 -0
  46. package/02-primitives/progress/progress.css +172 -0
  47. package/02-primitives/select/README.md +95 -0
  48. package/02-primitives/select/demo.html +121 -0
  49. package/02-primitives/select/select.css +151 -0
  50. package/02-primitives/select/select.js +549 -0
  51. package/02-primitives/separator/README.md +63 -0
  52. package/02-primitives/separator/demo.html +84 -0
  53. package/02-primitives/separator/separator.css +73 -0
  54. package/02-primitives/skeleton/README.md +69 -0
  55. package/02-primitives/skeleton/demo.html +110 -0
  56. package/02-primitives/skeleton/skeleton.css +96 -0
  57. package/02-primitives/switch/README.md +65 -0
  58. package/02-primitives/switch/demo.html +115 -0
  59. package/02-primitives/switch/switch.css +370 -0
  60. package/03-patterns/accordion/README.md +121 -0
  61. package/03-patterns/accordion/accordion.css +453 -0
  62. package/03-patterns/accordion/accordion.js +369 -0
  63. package/03-patterns/accordion/demo.html +223 -0
  64. package/03-patterns/content/README.md +103 -0
  65. package/03-patterns/content/content.css +286 -0
  66. package/03-patterns/content/demo.html +88 -0
  67. package/03-patterns/drawer/README.md +79 -0
  68. package/03-patterns/drawer/demo.html +101 -0
  69. package/03-patterns/drawer/drawer.css +129 -0
  70. package/03-patterns/drawer/drawer.js +258 -0
  71. package/03-patterns/dropdown/README.md +78 -0
  72. package/03-patterns/dropdown/demo.html +101 -0
  73. package/03-patterns/dropdown/dropdown.css +135 -0
  74. package/03-patterns/dropdown/dropdown.js +451 -0
  75. package/03-patterns/form-validation/README.md +147 -0
  76. package/03-patterns/form-validation/demo.html +280 -0
  77. package/03-patterns/form-validation/form-validation.css +263 -0
  78. package/03-patterns/list/README.md +150 -0
  79. package/03-patterns/list/demo.html +225 -0
  80. package/03-patterns/list/flip.js +201 -0
  81. package/03-patterns/list/list.css +162 -0
  82. package/03-patterns/nav/README.md +225 -0
  83. package/03-patterns/nav/demo.html +131 -0
  84. package/03-patterns/nav/nav.css +314 -0
  85. package/03-patterns/nav/nav.js +430 -0
  86. package/03-patterns/nav/toc.js +111 -0
  87. package/03-patterns/overlay/README.md +196 -0
  88. package/03-patterns/overlay/demo.html +241 -0
  89. package/03-patterns/overlay/overlay.css +319 -0
  90. package/03-patterns/overlay/overlay.js +563 -0
  91. package/03-patterns/pagination/README.md +114 -0
  92. package/03-patterns/pagination/demo.html +165 -0
  93. package/03-patterns/pagination/pagination.css +195 -0
  94. package/03-patterns/pagination/pagination.js +395 -0
  95. package/03-patterns/reveal/README.md +91 -0
  96. package/03-patterns/reveal/demo.html +106 -0
  97. package/03-patterns/reveal/reveal.css +93 -0
  98. package/03-patterns/reveal/reveal.js +172 -0
  99. package/03-patterns/states/README.md +141 -0
  100. package/03-patterns/states/demo.html +240 -0
  101. package/03-patterns/states/states.css +252 -0
  102. package/03-patterns/tabs/README.md +84 -0
  103. package/03-patterns/tabs/demo.html +139 -0
  104. package/03-patterns/tabs/tabs.css +172 -0
  105. package/03-patterns/tabs/tabs.js +307 -0
  106. package/03-patterns/tooltip/README.md +96 -0
  107. package/03-patterns/tooltip/demo.html +78 -0
  108. package/03-patterns/tooltip/tooltip.css +89 -0
  109. package/03-patterns/tooltip/tooltip.js +288 -0
  110. package/03-patterns/tree/README.md +94 -0
  111. package/03-patterns/tree/demo.html +138 -0
  112. package/03-patterns/tree/tree.css +113 -0
  113. package/03-patterns/tree/tree.js +456 -0
  114. package/04-recipes/analysis-report/README.md +80 -0
  115. package/04-recipes/analysis-report/analysis-report.css +187 -0
  116. package/04-recipes/analysis-report/demo.html +274 -0
  117. package/04-recipes/data-showcase/README.md +45 -0
  118. package/04-recipes/data-showcase/demo.html +247 -0
  119. package/04-recipes/detail-page/README.md +93 -0
  120. package/04-recipes/detail-page/demo.html +55 -0
  121. package/04-recipes/detail-page/detail-page.css +190 -0
  122. package/04-recipes/detail-page/full.html +60 -0
  123. package/04-recipes/detail-page/null.html +60 -0
  124. package/04-recipes/detail-page/partial.html +60 -0
  125. package/04-recipes/detail-page/verify-skeleton.py +19 -0
  126. package/04-recipes/longform/README.md +93 -0
  127. package/04-recipes/longform/agc-memory.svg +4 -0
  128. package/04-recipes/longform/content.html +610 -0
  129. package/04-recipes/longform/content.md +51 -0
  130. package/04-recipes/longform/longform.html +627 -0
  131. package/04-recipes/report/README.md +176 -0
  132. package/04-recipes/report/demo.html +355 -0
  133. package/04-recipes/report/report.css +364 -0
  134. package/04-recipes/table/README.md +103 -0
  135. package/04-recipes/table/demo.html +455 -0
  136. package/04-recipes/table/table.css +372 -0
  137. package/04-recipes/tierA-tokens.css +189 -0
  138. package/09-assets/README.md +74 -0
  139. package/09-assets/bar/README.md +94 -0
  140. package/09-assets/bar/bar.css +166 -0
  141. package/09-assets/bar/bar.js +320 -0
  142. package/09-assets/bar/demo.html +176 -0
  143. package/09-assets/echarts-adapter/demo.html +192 -0
  144. package/09-assets/echarts-adapter/echarts-adapter.js +277 -0
  145. package/09-assets/model-viewer/README.md +155 -0
  146. package/09-assets/model-viewer/demo.html +105 -0
  147. package/09-assets/model-viewer/model-viewer.css +143 -0
  148. package/09-assets/model-viewer/model-viewer.js +423 -0
  149. package/09-assets/scientific-plot/README.md +94 -0
  150. package/09-assets/scientific-plot/demo.html +252 -0
  151. package/09-assets/scientific-plot/scientific-plot.css +141 -0
  152. package/09-assets/scientific-plot/scientific-plot.js +610 -0
  153. package/09-assets/sparkline/README.md +153 -0
  154. package/09-assets/sparkline/demo.html +163 -0
  155. package/09-assets/sparkline/sparkline.css +158 -0
  156. package/09-assets/sparkline/sparkline.js +508 -0
  157. package/API.md +332 -0
  158. package/CHANGELOG.md +3138 -0
  159. package/CODE_OF_CONDUCT.md +64 -0
  160. package/CONTRIBUTING.md +89 -0
  161. package/ERRORS.md +1658 -0
  162. package/LICENSE +21 -0
  163. package/README.md +497 -2
  164. package/SECURITY.md +72 -0
  165. package/START-HERE.md +164 -0
  166. package/SUPPORT.md +109 -0
  167. package/adapters/presentation/README.md +113 -0
  168. package/adapters/presentation/check.js +101 -0
  169. package/adapters/presentation/deck.schema.json +74 -0
  170. package/adapters/presentation/to-doc.js +138 -0
  171. package/ai/START-HERE.md +104 -0
  172. package/ai/behaviors.json +380 -0
  173. package/ai/behaviors.schema.json +61 -0
  174. package/ai/capabilities.json +56 -0
  175. package/ai/cli.js +387 -0
  176. package/ai/components.json +1944 -0
  177. package/ai/components.meta.json +168 -0
  178. package/ai/components.schema.json +220 -0
  179. package/ai/contract.schema.json +147 -0
  180. package/ai/deprecations.json +55 -0
  181. package/ai/deprecations.schema.json +85 -0
  182. package/ai/motion-policy.json +22 -0
  183. package/ai/patch.js +323 -0
  184. package/ai/patch.schema.json +63 -0
  185. package/ai/profiles.json +92 -0
  186. package/ai/tokens.audience.json +55 -0
  187. package/ai/tokens.audience.schema.json +73 -0
  188. package/ai/tokens.json +762 -0
  189. package/ai/tokens.schema.json +58 -0
  190. package/ai/tokens.tree.json +752 -0
  191. package/ai/tokens.tree.schema.json +56 -0
  192. package/ai/validate.js +383 -0
  193. package/dist/01-tokens/behavior/dismissable.js +60 -0
  194. package/dist/01-tokens/behavior/emit.js +21 -0
  195. package/dist/01-tokens/behavior/focus-return.js +31 -0
  196. package/dist/01-tokens/behavior/roving.js +77 -0
  197. package/dist/01-tokens/behavior/typeahead.js +61 -0
  198. package/dist/01-tokens/focus-ring.css +1 -0
  199. package/dist/01-tokens/page.css +1 -0
  200. package/dist/01-tokens/polyfill.js +78 -0
  201. package/dist/01-tokens/scrollbar.css +1 -0
  202. package/dist/01-tokens/theme-toggle.js +61 -0
  203. package/dist/01-tokens/tokens.css +1 -0
  204. package/dist/01-tokens/typography.css +1 -0
  205. package/dist/02-primitives/badge/badge.css +1 -0
  206. package/dist/02-primitives/button/button.css +1 -0
  207. package/dist/02-primitives/card/card.css +1 -0
  208. package/dist/02-primitives/choice/choice.css +1 -0
  209. package/dist/02-primitives/combobox/combobox.css +1 -0
  210. package/dist/02-primitives/combobox/combobox.js +439 -0
  211. package/dist/02-primitives/date-range/date-range.css +1 -0
  212. package/dist/02-primitives/date-range/date-range.js +267 -0
  213. package/dist/02-primitives/input/input.css +1 -0
  214. package/dist/02-primitives/popover/popover.css +1 -0
  215. package/dist/02-primitives/popover/popover.js +257 -0
  216. package/dist/02-primitives/progress/progress.css +1 -0
  217. package/dist/02-primitives/select/select.css +1 -0
  218. package/dist/02-primitives/select/select.js +449 -0
  219. package/dist/02-primitives/separator/separator.css +1 -0
  220. package/dist/02-primitives/skeleton/skeleton.css +1 -0
  221. package/dist/02-primitives/switch/switch.css +1 -0
  222. package/dist/03-patterns/accordion/accordion.css +1 -0
  223. package/dist/03-patterns/accordion/accordion.js +219 -0
  224. package/dist/03-patterns/content/content.css +1 -0
  225. package/dist/03-patterns/drawer/drawer.css +1 -0
  226. package/dist/03-patterns/drawer/drawer.js +229 -0
  227. package/dist/03-patterns/dropdown/dropdown.css +1 -0
  228. package/dist/03-patterns/dropdown/dropdown.js +365 -0
  229. package/dist/03-patterns/form-validation/form-validation.css +1 -0
  230. package/dist/03-patterns/list/flip.js +117 -0
  231. package/dist/03-patterns/list/list.css +1 -0
  232. package/dist/03-patterns/nav/nav.css +1 -0
  233. package/dist/03-patterns/nav/nav.js +322 -0
  234. package/dist/03-patterns/nav/toc.js +76 -0
  235. package/dist/03-patterns/overlay/overlay.css +1 -0
  236. package/dist/03-patterns/overlay/overlay.js +398 -0
  237. package/dist/03-patterns/pagination/pagination.css +1 -0
  238. package/dist/03-patterns/pagination/pagination.js +273 -0
  239. package/dist/03-patterns/reveal/reveal.css +1 -0
  240. package/dist/03-patterns/reveal/reveal.js +138 -0
  241. package/dist/03-patterns/states/states.css +1 -0
  242. package/dist/03-patterns/tabs/tabs.css +1 -0
  243. package/dist/03-patterns/tabs/tabs.js +242 -0
  244. package/dist/03-patterns/tooltip/tooltip.css +1 -0
  245. package/dist/03-patterns/tooltip/tooltip.js +213 -0
  246. package/dist/03-patterns/tree/tree.css +1 -0
  247. package/dist/03-patterns/tree/tree.js +383 -0
  248. package/dist/04-recipes/analysis-report/analysis-report.css +1 -0
  249. package/dist/04-recipes/detail-page/detail-page.css +1 -0
  250. package/dist/04-recipes/report/report.css +1 -0
  251. package/dist/04-recipes/table/table.css +1 -0
  252. package/dist/04-recipes/tierA-tokens.css +1 -0
  253. package/dist/09-assets/bar/bar.css +1 -0
  254. package/dist/09-assets/bar/bar.js +222 -0
  255. package/dist/09-assets/echarts-adapter/echarts-adapter.js +185 -0
  256. package/dist/09-assets/model-viewer/model-viewer.css +1 -0
  257. package/dist/09-assets/model-viewer/model-viewer.js +320 -0
  258. package/dist/09-assets/scientific-plot/scientific-plot.css +1 -0
  259. package/dist/09-assets/scientific-plot/scientific-plot.js +568 -0
  260. package/dist/09-assets/sparkline/sparkline.css +1 -0
  261. package/dist/09-assets/sparkline/sparkline.js +265 -0
  262. package/dist/COSTS.md +56 -0
  263. package/docs/AI-CONTRACT.md +197 -0
  264. package/docs/BACKLOG.md +127 -0
  265. package/docs/BENCHMARK.md +252 -0
  266. package/docs/GUIDANCE.md +154 -0
  267. package/docs/INVARIANT.md +372 -0
  268. package/docs/LAYER-BASELINE.md +158 -0
  269. package/docs/RELEASING.md +311 -0
  270. package/docs/RFC-THEME-SCOPE.md +141 -0
  271. package/docs/ROADMAP.md +182 -0
  272. package/index.html +82 -0
  273. package/package.json +107 -4
  274. package/types/index.d.ts +310 -0
@@ -0,0 +1,176 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <link rel="icon" href="data:,">
7
+ <title>bar · 柱状图 · frontend-lib</title>
8
+ <link rel="stylesheet" href="../../01-tokens/tokens.css">
9
+ <link rel="stylesheet" href="../../01-tokens/typography.css">
10
+ <link rel="stylesheet" href="../../01-tokens/page.css">
11
+ <link rel="stylesheet" href="bar.css">
12
+ <style>
13
+ .note code { font-family: var(--font-mono, monospace); }
14
+ #err {
15
+ margin: var(--sp-3) 0 0; padding: var(--sp-3);
16
+ background: var(--surface-sunken); border-radius: var(--r-sm);
17
+ font-size: var(--fs-sm); color: var(--danger);
18
+ white-space: pre-wrap;
19
+ }
20
+ </style>
21
+ </head>
22
+ <body class="page page">
23
+ <main class="wrap">
24
+
25
+ <h1>bar · 柱状图</h1>
26
+
27
+ <p class="note">
28
+ 按 <strong>charter 13 图表规范</strong>四条铁律实现。
29
+ <br>① 超量程被容器裁剪(<code>.bar</code> + <code>.bar__svg</code> 两道
30
+ <code>overflow:hidden</code>,缺一不可)
31
+ <br>② 标注只标关键点(<strong>永远 ≤ 4 个</strong>)且画在柱顶外侧
32
+ <br>③ <code>max</code> <strong>必填</strong>,不替调用方决定量程
33
+ <br>④ 判据可证伪(<code>chart-check.js</code> 覆盖本组件)
34
+ </p>
35
+
36
+ <h2>1 · 正常量程(两系列堆叠)</h2>
37
+ <p class="note">
38
+ <strong>堆叠(stack,默认)</strong>:第二系列画在第一系列<b>顶端</b>,
39
+ 柱子的总高 = 该列的<b>合计</b>,顶端标注写的也是合计。
40
+ <br>🔴 修复前这里写的也是"堆叠",但实现把累计数组在每个系列开头清零了
41
+ ⇒ 两个系列都从基线起算、还<b>同宽同位</b> ⇒ 后者把前者的底部整块盖掉,
42
+ 读者看到的其实是<b>最后那个系列</b>的值,而且<b>不会报错</b>。
43
+ </p>
44
+ <div class="bar" id="b1"></div>
45
+
46
+ <h2>1b · 并列分组(group):同一个 ay,另一种语义</h2>
47
+ <p class="note">
48
+ 分组用于"同一组数据要<b>比大小</b>":每个系列各占一条窄柱,不看总高、看长短。
49
+ <br>取舍:<b>堆叠</b>回答"合计是多少、由什么组成";<b>分组</b>回答"谁更高"。
50
+ 选错模式不是审美问题 —— 堆叠用来比大小会让人误读<b>累计的厚度</b>。
51
+ </p>
52
+ <div class="bar" id="b1b"></div>
53
+
54
+ <h2>1c · 🔴 堆叠合计超出量程:不能假装没超</h2>
55
+ <p class="note">
56
+ 两个系列各自都没超上限,但<b>加起来超了</b>。
57
+ 这里的行为是:超出部分<b>被裁掉</b>,并且脚下写明"类目的合计超出量程"。
58
+ <br>⚠️ 这是堆叠独有的坑 —— 只检查单个系列超没超,抓不到这种情况。
59
+ </p>
60
+ <div class="bar" id="b1c"></div>
61
+
62
+ <h2>2 · 🔴 超量程:09-01 那根超出上限</h2>
63
+ <p class="note">
64
+ 这一张<b>故意</b>把 09-01 设成 0.42,而上限是 0.35 ⇒ 它会被裁到顶,
65
+ 并标 <code>data-clipped</code> + 给出脚注。
66
+ <br>⚠️ 若没有那两道 <code>overflow:hidden</code>,这根柱子会
67
+ <b>穿透到页面其他内容上</b>(这是实机遇到过的真实问题)。
68
+ </p>
69
+ <div class="bar" id="b2"></div>
70
+
71
+ <h2>3 · 阈值线 + 标注只标关键点</h2>
72
+ <div class="bar" id="b3"></div>
73
+
74
+ <h2>4 · 🔴 量程必填:不给 max 会直接报错</h2>
75
+ <p class="note">
76
+ charter 13 铁律三:<b>量程不得自动适配</b>。
77
+ <br>一个 400 的异常值 + 30 个 0.35 的常态值,若 Y 轴自适应到 400
78
+ ⇒ 所有常态值被压成<b>一条贴底的直线</b>
79
+ ⇒ 读者会得出「这些天完全没有变化」的<b>错误结论</b>。
80
+ <br>⇒ 宁可报错,也不悄悄替调用方做决定。
81
+ </p>
82
+ <button class="btn" id="try">不给 max,看会发生什么</button>
83
+ <div id="err"></div>
84
+
85
+ </main>
86
+
87
+ <script src="bar.js"></script>
88
+ <script>
89
+ (function () {
90
+ var LBL = ['09-01','09-02','09-03','09-04','09-05','09-06','09-07',
91
+ '09-08','09-09','09-10','09-11','09-12'];
92
+
93
+ /* 1 · 正常:两系列堆叠 */
94
+ Bar.draw({
95
+ host: document.getElementById('b1'),
96
+ max: 30,
97
+ height: 190,
98
+ labels: LBL,
99
+ series: [
100
+ { name: '夜间', values: [3, 6, 4, 5, 2, 6, 5, 7, 6, 8, 7, 9] },
101
+ { name: '日间', values: [5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9] },
102
+ ],
103
+ ariaLabel: '每日两系列堆叠柱状图',
104
+ });
105
+
106
+ /* 1b · 并列分组:同一组数据,另一种语义(比长短,不看总高) */
107
+ Bar.draw({
108
+ host: document.getElementById('b1b'),
109
+ mode: 'group',
110
+ max: 12,
111
+ height: 190,
112
+ labels: LBL,
113
+ series: [
114
+ { name: '夜间', values: [3, 6, 4, 5, 2, 6, 5, 7, 6, 8, 7, 9] },
115
+ { name: '日间', values: [5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9] },
116
+ ],
117
+ ariaLabel: '每日两系列并列分组柱状图',
118
+ });
119
+
120
+ /* 1c · 🔴 堆叠合计超量程:单系列都没超(7 + 6 = 13 > 12)也要报错式提示 */
121
+ Bar.draw({
122
+ host: document.getElementById('b1c'),
123
+ max: 12,
124
+ height: 190,
125
+ labels: LBL,
126
+ series: [
127
+ { name: '线上', values: [7, 5, 6, 4, 5, 6, 7, 5, 6, 7, 5, 6] },
128
+ { name: '线下', values: [6, 4, 5, 5, 4, 5, 6, 4, 5, 6, 4, 5] },
129
+ ],
130
+ ariaLabel: '堆叠合计超出量程的示例',
131
+ });
132
+
133
+ /* 2 · 🔴 超量程:09-01 = 0.42 超出上限 0.35 */
134
+ Bar.draw({
135
+ host: document.getElementById('b2'),
136
+ max: 0.35, /* 🔴 必填 */
137
+ height: 190,
138
+ labels: LBL,
139
+ series: [{
140
+ name: '空闲水平',
141
+ values: [0.42, 0.24, 0.25, 0.25, 0.24, 0.25, 0.26, 0.25,
142
+ 0.26, 0.27, 0.26, 0.27],
143
+ }],
144
+ note: '09-01 为 0.42,超出量程上限 0.35,已按上限截断显示。',
145
+ ariaLabel: '每日空闲水平,第 1 天超出量程',
146
+ });
147
+
148
+ /* 3 · 阈值线 */
149
+ Bar.draw({
150
+ host: document.getElementById('b3'),
151
+ max: 25,
152
+ height: 190,
153
+ labels: LBL,
154
+ threshold: 1,
155
+ series: [{ name: '早于 09:00 的件数', values: [5, 0, 1, 0, 2, 0, 1, 0, 9, 6, 5, 7] }],
156
+ ariaLabel: '每日 09:00 前的事项数,含阈值线 1',
157
+ });
158
+
159
+ /* 4 · 演示"量程必填" */
160
+ document.getElementById('try').addEventListener('click', function () {
161
+ var box = document.getElementById('err');
162
+ try {
163
+ Bar.draw({
164
+ host: document.getElementById('b3'),
165
+ series: [{ values: [1, 2, 3] }],
166
+ /* 故意不给 max */
167
+ });
168
+ box.textContent = '🔴 不该走到这里';
169
+ } catch (e) {
170
+ box.textContent = '✓ 已按规范拒绝:' + e.message;
171
+ }
172
+ });
173
+ })();
174
+ </script>
175
+ </body>
176
+ </html>
@@ -0,0 +1,192 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6
+ <meta name="color-scheme" content="light dark">
7
+ <title>图表规范 · frontend-lib</title>
8
+ <link rel="stylesheet" href="../../01-tokens/tokens.css">
9
+ <link rel="stylesheet" href="../../01-tokens/typography.css">
10
+ <link rel="stylesheet" href="../../01-tokens/page.css">
11
+ <link rel="stylesheet" href="../../09-assets/sparkline/sparkline.css">
12
+ <style>
13
+ h3 { font-size: var(--fs-base); margin: var(--sp-5) 0 var(--sp-2); color: var(--text-primary); }
14
+ .ok { color: var(--success); }
15
+ .no { color: var(--danger); }
16
+ table { width:100%; border-collapse: collapse; font-size: var(--fs-sm); margin: 0 0 var(--sp-3); }
17
+ th, td { text-align: left; padding: var(--sp-2) var(--sp-3);
18
+ border-bottom: 1px solid var(--border-decor); }
19
+ th { font-size: var(--fs-xs); color: var(--text-secondary); font-weight: 500; }
20
+ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
21
+ .up { color: var(--danger); }
22
+ .down { color: var(--success); }
23
+ /* A股:涨红跌绿 */
24
+ /* 图表位:ECharts 未引入时显示这里 */
25
+ .chart { width: 100%; height: 260px; display: flex; align-items: center;
26
+ justify-content: center; flex-direction: column; gap: var(--sp-2);
27
+ color: var(--text-tertiary); font-size: var(--fs-sm);
28
+ background: var(--surface-sunken); border-radius: var(--r-sm); }
29
+ .chart canvas { max-width: 100%; }
30
+ .flex { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
31
+ .flex>* { flex: 1 1 260px; min-width: 0; }
32
+ .swatch { display:inline-block; width:10px; height:10px; border-radius:2px;
33
+ vertical-align:middle; margin-right:4px; }
34
+ </style>
35
+ </head>
36
+ <body class="page page">
37
+ <div class="wrap">
38
+ <h1>图表规范</h1>
39
+ <p class="lede">
40
+ <strong>下次画图照这里做就行</strong>,不用再反复微调。
41
+ 全部规则来自本库的分析类可视化约定,
42
+ 并且<strong>大部分已经变成 <code>echarts-adapter.js</code> 里的默认值</strong> ——
43
+ 你不写,它就帮你合规。
44
+ </p>
45
+
46
+ <h2 class="rule-top">0 · 边界:什么该用本库,什么该用 ECharts</h2>
47
+ <table>
48
+ <tr><th>场景</th><th>用什么</th><th>谁维护</th></tr>
49
+ <tr><td>列表右侧的<strong>迷你趋势</strong>(看走势)</td>
50
+ <td class="ok">本库 <code>sparkline</code>(1.5KB,零依赖)</td><td>我们</td></tr>
51
+ <tr><td>表格里的迷你条 / 状态点</td><td class="ok">本库</td><td>我们</td></tr>
52
+ <tr><td><strong>多系列</strong>折线 / 柱 / 饼 / 桑基 / 热力 / 仪表盘</td>
53
+ <td class="no">ECharts 或 Recharts</td><td><strong>他们</strong></td></tr>
54
+ </table>
55
+ <p class="note">
56
+ <strong>判据一句话</strong>:「<strong>看走势</strong>」用本库;「<strong>看数据、用它做判断</strong>」用 ECharts。
57
+ </p>
58
+ <p class="note">
59
+ ⚠️ 精简档(某项目)<strong>不要引 ECharts</strong>(约 1MB gzip)——那边继续用 sparkline。
60
+ </p>
61
+
62
+ <h2 class="rule-top">1 · 本库负责的:迷你趋势(sparkline)</h2>
63
+ <div class="box">
64
+ <div class="row" style="display:flex;align-items:center;gap:var(--sp-4);padding:4px 0">
65
+ <span style="width:60px;font-size:var(--fs-sm)">600519</span>
66
+ <span style="width:84px;text-align:right;font-family:var(--mono);font-size:var(--fs-sm)">1,684.20</span>
67
+ <span class="up" style="width:56px;font-size:var(--fs-xs)">+2.31%</span>
68
+ <span class="sparkline" data-spark="1602,1618,1609,1631,1625,1648,1662,1655,1684"
69
+ data-spark-height="34" data-spark-last="yes"
70
+ style="flex:1 1 auto;min-width:60px"></span>
71
+ </div>
72
+ <div class="row" style="display:flex;align-items:center;gap:var(--sp-4);padding:4px 0">
73
+ <span style="width:60px;font-size:var(--fs-sm)">000001</span>
74
+ <span style="width:84px;text-align:right;font-family:var(--mono);font-size:var(--fs-sm)">11.87</span>
75
+ <span class="down" style="width:56px;font-size:var(--fs-xs)">−0.84%</span>
76
+ <span class="sparkline" data-spark="12.05,12.11,12.02,11.96,11.99,11.92,11.88,11.91,11.87"
77
+ data-spark-height="34" data-spark-last="yes"
78
+ style="flex:1 1 auto;min-width:60px"></span>
79
+ </div>
80
+ </div>
81
+ <p class="note">
82
+ 🔴 <strong>旁边必须有数字</strong>——sparkline 本身<strong>没有可读的信息</strong>
83
+ (读屏读不出路径)。这是它最容易出的错。
84
+ </p>
85
+
86
+ <h2 class="rule-top">2 · ECharts 负责的:数据分析图表</h2>
87
+ <p class="note">
88
+ 本页<strong>没有引 ECharts</strong>(本库零依赖)。下面是<strong>规范示例</strong> ——
89
+ 数字用本库的格式规则画出来,图表位留给 ECharts。
90
+ <br>想在浏览器里看真图,主项目里引一行
91
+ <code>&lt;script src="echarts.min.js"&gt;</code> 即可,适配层会自动接管主题。
92
+ </p>
93
+
94
+ <div class="flex">
95
+ <div class="box">
96
+ <h3 style="margin-top:0">✅ 规范:柱状图(分类轴从 0)</h3>
97
+ <table>
98
+ <tr><th>季度</th><th class="num">营收(亿)</th><th class="num">同比</th></tr>
99
+ <tr><td>Q1</td><td class="num">128.4</td><td class="num up">+12.4%</td></tr>
100
+ <tr><td>Q2</td><td class="num">136.1</td><td class="num up">+8.1%</td></tr>
101
+ <tr><td>Q3</td><td class="num">141.7</td><td class="num down">−2.3%</td></tr>
102
+ <tr><td>Q4</td><td class="num">155.2</td><td class="num up">+9.5%</td></tr>
103
+ </table>
104
+ <p class="note">
105
+ <strong>柱状图的 y 轴必须从 0 开始</strong> —— 截断基线会夸大差异,
106
+ 这是最容易骗人的一种图。<code>adapter.defaults()</code> 已自动加 <code>min:0</code>。
107
+ </p>
108
+ </div>
109
+
110
+ <div class="box">
111
+ <h3 style="margin-top:0">✅ 规范:多系列(≤ 5 条)</h3>
112
+ <table>
113
+ <tr><th>年份</th>
114
+ <th class="num"><span class="swatch" style="background:var(--accent)"></span>A 股</th>
115
+ <th class="num"><span class="swatch" style="background:var(--danger)"></span>B 股</th>
116
+ <th class="num"><span class="swatch" style="background:var(--success)"></span>C 股</th></tr>
117
+ <tr><td>2022</td><td class="num">1,284</td><td class="num">862</td><td class="num">517</td></tr>
118
+ <tr><td>2023</td><td class="num">1,506</td><td class="num">747</td><td class="num">603</td></tr>
119
+ <tr><td>2024</td><td class="num">1,706</td><td class="num">863</td><td class="num">714</td></tr>
120
+ </table>
121
+ <p class="note">
122
+ <strong>系列上限 5</strong>。超过时 <code>adapter</code> 会
123
+ <span class="no">在控制台警告</span>——
124
+ 因为颜色循环会让第 6 条和第 1 条同色,用户分不清谁是谁。
125
+ 「颜色不够用」是<strong>该换图表</strong>的信号。
126
+ </p>
127
+ </div>
128
+ </div>
129
+
130
+ <div class="chart" id="chart-demo">
131
+ <div>ECharts 图表位</div>
132
+ <div style="font-size:var(--fs-xs)">主项目引 echarts.min.js 后,这里会自动出图并套用本库主题</div>
133
+ </div>
134
+
135
+ <h2 class="rule-top">3 · 数字格式(已经在用)</h2>
136
+ <table>
137
+ <tr><th>类型</th><th>规则</th><th>例子</th></tr>
138
+ <tr><td>千分位</td><td>每三位加逗号</td><td class="num">1,234,567</td></tr>
139
+ <tr><td>百分比</td><td>固定 1–2 位小数</td><td class="num">42.6%</td></tr>
140
+ <tr><td>大额</td><td>走「万 / 亿」,不写成 100,000,000</td><td class="num">1.28 亿</td></tr>
141
+ <tr><td>缺失值</td><td><strong>留空,不写 0</strong></td><td class="num">—</td></tr>
142
+ </table>
143
+ <p class="note">
144
+ 🔴 <strong>缺失 ≠ 0</strong>:这是本库的
145
+ <code>MISSING != ZERO</code> 契约,图表里同样适用
146
+ —— 缺失点应该<strong>断开</strong>,不能画成 0。
147
+ </p>
148
+
149
+ <h2 class="rule-top">4 · 明确禁止(这些是"看起来专业但会骗人"的)</h2>
150
+ <div class="box bad">
151
+ <table>
152
+ <tr><th>不要做</th><th>为什么</th></tr>
153
+ <tr><td class="no">3D 图表</td><td>透视扭曲会<b>误导读数</b>(Tufte 的核心结论)</td></tr>
154
+ <tr><td class="no">双 Y 轴</td><td>两轴的交叉点可以被随意搬动 ⇒ <b>视觉在说谎</b></td></tr>
155
+ <tr><td class="no">大面积渐变填充</td><td>只在面积图用,透明度 ≤ 0.15</td></tr>
156
+ <tr><td class="no">只用颜色区分系列</td><td>色盲用户看不出 ⇒ 加虚线或标记点</td></tr>
157
+ <tr><td class="no">平滑曲线(smooth)</td><td>会造出<b>数据里没有的中间值</b>,adapter 已默认关掉</td></tr>
158
+ </table>
159
+ </div>
160
+
161
+ <h2 class="rule-top">5 · 无障碍</h2>
162
+ <div class="box">
163
+ <ul style="margin:0;padding-left:20px">
164
+ <li>图表旁<strong>必须有等价的数字或表格</strong>(本页每个图都配了表)</li>
165
+ <li>数据图表的 <code>&lt;svg&gt;</code> 加 <code>role="img"</code> + <code>aria-label</code></li>
166
+ <li>⚠️ <strong>装饰性 sparkline 反而不要</strong> 加 <code>role="img"</code>
167
+ ——它没有可读等价物,加了会误导</li>
168
+ <li>不能只用颜色区分系列</li>
169
+ </ul>
170
+ </div>
171
+
172
+ <h2 class="rule-top">6 · 怎么用(下次直接照抄)</h2>
173
+ <div class="box">
174
+ <pre style="margin:0;font-family:var(--mono);font-size:var(--fs-xs);overflow-x:auto"><code>&lt;script src="echarts.min.js"&gt;&lt;/script&gt; &lt;!-- 主项目引 --&gt;
175
+ &lt;script src="09-assets/echarts-adapter/echarts-adapter.js"&gt;&lt;/script&gt;
176
+
177
+ var c = ChartAdapter.create(document.getElementById('chart'), {
178
+ xAxis: { type: 'category', data: ['Q1','Q2','Q3','Q4'] },
179
+ yAxis: { type: 'value' },
180
+ series: [{ type: 'bar', data: [128.4, 136.1, 141.7, 155.2] }]
181
+ });
182
+ // ↑ 就这样。主题、y 轴从 0、字号、网格边距都已经合规了。</code></pre>
183
+ </div>
184
+ <p class="note">
185
+ 换主题时调 <code>ChartAdapter.refresh(c)</code>,图表会跟着变
186
+ (配合 <code>01-tokens/theme-toggle.js</code>)。
187
+ </p>
188
+ </div>
189
+ <script src="../../09-assets/sparkline/sparkline.js"></script>
190
+ <script src="../../09-assets/echarts-adapter/echarts-adapter.js"></script>
191
+ </body>
192
+ </html>
@@ -0,0 +1,277 @@
1
+ /*
2
+ * echarts-adapter.js — 把本库令牌喂给 Apache ECharts(零依赖 · ES5)
3
+ *
4
+ * ============================================================================
5
+ * ⚠️ 本文件**不含 ECharts**,也不加载它。
6
+ * 它只在 ECharts **已存在**时工作(主项目按需引),本库自己零依赖。
7
+ * ============================================================================
8
+ *
9
+ * ============================================================================
10
+ * 🔴 它解决什么问题
11
+ * ============================================================================
12
+ * 「有了这东西之后,我们画图能够画的更精准更好,
13
+ * 不用每次都花 token 花在画各种不规范的图上面,然后反复地去修改」
14
+ *
15
+ * ⇒ 本文件是**图表规范的机器可读版本**:
16
+ * - 主题:换主题时图表跟着变(不用手改 ECharts 配置)
17
+ * - 规范:把 charter 10 里的规则**变成默认值**(不用每次重想)
18
+ *
19
+ * ============================================================================
20
+ * 为什么这个维护成本≈0
21
+ * ============================================================================
22
+ * **它不碰任何图表逻辑。** 只做三件事:
23
+ * ① 从 CSS 变量读颜色 ② 映射成 ECharts 主题对象
24
+ * ③ 提供一组「合规的默认配置」
25
+ * 图表怎么画、怎么交互 —— 那是 ECharts 的事。
26
+ *
27
+ * ============================================================================
28
+ * 用法
29
+ * ============================================================================
30
+ * <script src="echarts.min.js"></script> ← 主项目自己引
31
+ * <script src="09-assets/echarts-adapter/echarts-adapter.js"></script>
32
+ * <script>
33
+ * var c = ChartAdapter.create(document.getElementById('c'));
34
+ * c.setOption(ChartAdapter.options({
35
+ * xAxis: { type: 'category', data: ['1月','2月','3月'] },
36
+ * series: [{ type: 'line', data: [120, 200, 150] }],
37
+ * }));
38
+ * </script>
39
+ *
40
+ * ⚠️ 精简档(某项目)**不要引 ECharts**(约 1MB gzip)——
41
+ * 那边继续用 09-assets/sparkline。见 charter 10。
42
+ */
43
+ (function () {
44
+ 'use strict';
45
+
46
+ /* ---------- 1. 从 CSS 变量取令牌 ---------- */
47
+
48
+ /** 读一个 CSS 变量(读不到就返回 fallback)。 */
49
+ function cssVar(name, fallback) {
50
+ if (typeof window.getComputedStyle !== 'function') return fallback;
51
+ var v = getComputedStyle(document.documentElement).getPropertyValue(name);
52
+ return (v && v.trim()) || fallback;
53
+ }
54
+
55
+ /**
56
+ * 拿到本库的调色板。
57
+ * 🔴 全部有 fallback —— 万一页面没引 tokens.css 也能出图
58
+ * (不因为缺令牌就整个图表画不出来)。
59
+ */
60
+ function palette() {
61
+ return {
62
+ text: cssVar('--text-primary', '#15181c'),
63
+ textSub: cssVar('--text-secondary', '#5b6472'),
64
+ textTertiary: cssVar('--text-tertiary', '#8a94a3'),
65
+ surface: cssVar('--surface', '#ffffff'),
66
+ paper: cssVar('--paper', '#f6f7f8'),
67
+ border: cssVar('--border-decor', '#e2e5e9'),
68
+ borderStrong: cssVar('--border-control', '#868b94'),
69
+ danger: cssVar('--danger', '#c0392b'), // A 股:涨红
70
+ success: cssVar('--success', '#2e7d52'), // 跌绿
71
+ warn: cssVar('--warning', '#b8860b'),
72
+ info: cssVar('--info', '#2b7a9e'),
73
+ accent: cssVar('--accent', '#1b4d8f'),
74
+ };
75
+ }
76
+
77
+ /* ---------- 2. 系列配色 ---------- */
78
+
79
+ /**
80
+ * 取 n 个系列的颜色。
81
+ * 🔴 **不让调色板自己循环** —— 超过可用色数就返回 null,
82
+ * 调用方应当**改图表类型**(charter 10 的规则:系列 ≤ 5)。
83
+ *
84
+ * 为什么不循环:第 6 个颜色和第 1 个同色,用户分不清谁是谁。
85
+ * 「颜色不够用」是**该换图表**的信号,不是该加颜色的理由。
86
+ */
87
+ function seriesColors(n, p) {
88
+ var ramp = [p.accent, p.danger, p.success, p.warn, p.info];
89
+ if (n > ramp.length) return null;
90
+ return ramp.slice(0, n);
91
+ }
92
+
93
+ /* ---------- 3. 主题对象(喂给 echarts.registerTheme) ---------- */
94
+
95
+ /**
96
+ * 生成 ECharts 主题。
97
+ * @param {string} name 主题名
98
+ * @param {object} p 调色板(默认自动取)
99
+ */
100
+ function theme(name, p) {
101
+ p = p || palette();
102
+ var isDark = document.documentElement.getAttribute('data-theme-current') === 'dark'
103
+ || cssVar('--paper', '#fff') !== '#f6f7f8';
104
+
105
+ return {
106
+ color: [p.accent, p.danger, p.success, p.warn, p.info],
107
+ backgroundColor: 'transparent', // 交给页面的背景
108
+ textStyle: {
109
+ color: p.text,
110
+ fontFamily: cssVar('--sans', 'system-ui, sans-serif'),
111
+ },
112
+ title: {
113
+ textStyle: { color: p.text, fontWeight: 600 },
114
+ subtextStyle: { color: p.textSub },
115
+ },
116
+ legend: { textStyle: { color: p.textSub } },
117
+ tooltip: {
118
+ backgroundColor: isDark ? '#1c2024' : '#ffffff',
119
+ borderColor: p.border,
120
+ borderWidth: 1,
121
+ textStyle: { color: p.text, fontSize: 12 },
122
+ // 🔴 数字统一等宽 + 千分位(charter 10 的数字格式规则)
123
+ extraCssText: isDark
124
+ ? 'box-shadow:0 2px 8px rgba(0,0,0,.5);'
125
+ : 'box-shadow:0 2px 8px rgba(0,0,0,.1);',
126
+ },
127
+ categoryAxis: axisCommon(p, isDark),
128
+ valueAxis: axisCommon(p, isDark),
129
+ logAxis: axisCommon(p, isDark),
130
+ timeAxis: axisCommon(p, isDark),
131
+ };
132
+ }
133
+
134
+ function axisCommon(p, isDark) {
135
+ return {
136
+ axisLine: { lineStyle: { color: p.border } },
137
+ axisTick: { show: false },
138
+ axisLabel: { color: p.textSub, fontSize: 11 },
139
+ splitLine: { lineStyle: { color: p.border, type: 'dashed' } },
140
+ // 🔴 分类轴从 0 开始(柱状图的诚实性要求,见 charter 10)
141
+ splitNumber: 4,
142
+ };
143
+ }
144
+
145
+ /* ---------- 4. 合规的默认配置 ---------- */
146
+
147
+ /**
148
+ * 一组**符合 charter 10 规范**的默认 option。
149
+ * 覆盖 ECharts 的默认值 —— 让你不写就合规。
150
+ */
151
+ function defaults(option) {
152
+ var p = palette();
153
+ var o = option || {};
154
+
155
+ // 🔴 数字格式:千分位 + 等宽
156
+ o.textStyle = merge(o.textStyle, {
157
+ fontFamily: cssVar('--mono', 'ui-monospace, monospace'),
158
+ });
159
+
160
+ // 网格:留够左边距给 y 轴标签
161
+ o.grid = merge(o.grid, { left: 56, right: 24, top: 32, bottom: 32, containLabel: false });
162
+
163
+ // 折线:不平滑(平滑会**造出数据里没有的中间值**)
164
+ o.series = (o.series || []).map(function (s) {
165
+ if (s.type === 'line') {
166
+ return merge(s, {
167
+ smooth: false, // 🔴 别撒谎
168
+ showSymbol: (s.data || []).length <= 7, // ≤7 才显示点
169
+ symbolSize: 5,
170
+ lineStyle: merge(s.lineStyle, { width: 2 }),
171
+ });
172
+ }
173
+ if (s.type === 'bar') {
174
+ return merge(s, {
175
+ barMaxWidth: 28, // 细柱更清爽
176
+ // 🔴 分类轴从 0 开始由 yAxis.min=0 保证(见下)
177
+ });
178
+ }
179
+ if (s.type === 'area') {
180
+ return merge(s, {
181
+ areaStyle: merge(s.areaStyle, { opacity: 0.14 }), // ≤0.15
182
+ });
183
+ }
184
+ return s;
185
+ });
186
+
187
+ // y 轴:柱状必须从 0
188
+ var isBar = o.series.some(function (s) { return s.type === 'bar'; });
189
+ if (isBar && o.yAxis) {
190
+ var y = Array.isArray(o.yAxis) ? o.yAxis[0] : o.yAxis;
191
+ if (y && y.min === undefined) y.min = 0;
192
+ }
193
+
194
+ // 🔴 超过 5 个系列 ⇒ 明确警告(charter 10:系列 ≤ 5)
195
+ if (o.series.length > 5) {
196
+ if (typeof console !== 'undefined' && console.warn) {
197
+ console.warn('[frontend-lib] 系列数 ' + o.series.length +
198
+ ' 超过 5 —— 请改图表类型或分屏,见 charter 10。配色循环会让颜色撞车。');
199
+ }
200
+ }
201
+
202
+ return o;
203
+ }
204
+
205
+ /* ---------- 5. 高层封装 ---------- */
206
+
207
+ /**
208
+ * 创建一个已应用本库主题的 ECharts 实例。
209
+ * ECharts 不在 ⇒ 返回 null(调用方自己决定怎么办)。
210
+ *
211
+ * 🔴 修正:初版我写了个蠢流程(init → setOption → dispose → 再 init)。
212
+ * ECharts 5 的主题就是**一个名字**,两种正规用法:
213
+ * ① init(dom, themeName)
214
+ * ② setOption(option, themeName)
215
+ * 不需要任何"先注册再重初始化"的 dance。
216
+ */
217
+ function currentThemeName() {
218
+ return 'fe-' +
219
+ (document.documentElement.getAttribute('data-theme-current') || 'light');
220
+ }
221
+
222
+ function create(dom, opt) {
223
+ if (typeof window.echarts === 'undefined') {
224
+ if (typeof console !== 'undefined' && console.warn) {
225
+ console.warn('[frontend-lib] 未检测到 ECharts —— ' +
226
+ '请在主项目里自行引入(前端库本身零依赖)。');
227
+ }
228
+ return null;
229
+ }
230
+ var name = currentThemeName();
231
+ // 🔴 每次都注册:换主题后令牌变了,得重新注册同名主题
232
+ if (typeof window.echarts.registerTheme === 'function') {
233
+ window.echarts.registerTheme(name, theme(name));
234
+ }
235
+ var inst = window.echarts.init(dom, name);
236
+ inst.__feDom = dom; // refresh 要用
237
+ inst.__feOpts = opt || {};
238
+ inst.__feTheme = name;
239
+ inst.setOption(defaults(inst.__feOpts));
240
+ return inst;
241
+ }
242
+
243
+ /* ---------- 小工具 ---------- */
244
+ function merge(a, b) {
245
+ var o = {}, k;
246
+ if (a) for (k in a) if (a.hasOwnProperty(k)) o[k] = a[k];
247
+ if (b) for (k in b) if (b.hasOwnProperty(k)) o[k] = b[k];
248
+ return o;
249
+ }
250
+
251
+ /* ---------- 导出 ---------- */
252
+ var ChartAdapter = {
253
+ cssVar: cssVar,
254
+ palette: palette,
255
+ seriesColors: seriesColors,
256
+ theme: theme,
257
+ defaults: defaults,
258
+ create: create,
259
+ /** 主题切换后重设(配合 theme-toggle.js 调用) */
260
+ refresh: function (inst) {
261
+ if (!inst) return;
262
+ var name = currentThemeName();
263
+ if (typeof window.echarts !== 'undefined' && window.echarts.registerTheme) {
264
+ window.echarts.registerTheme(name, theme(name));
265
+ }
266
+ // 🔴 主题名变了必须重建实例(ECharts 的主题在 init 时绑定)
267
+ if (inst.__feDom) {
268
+ var opt = inst.__feOpts;
269
+ inst.dispose();
270
+ return create(inst.__feDom, opt);
271
+ }
272
+ inst.setOption(defaults(inst.__feOpts), name);
273
+ return inst;
274
+ },
275
+ };
276
+ if (typeof window !== 'undefined') window.ChartAdapter = ChartAdapter;
277
+ })();