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,252 @@
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>scientific-plot · 二维科学绘图 · 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="scientific-plot.css">
12
+ <style>
13
+ /* 示例页自己的排布;不属于组件样式 */
14
+ .fig { margin: 0 0 var(--sp-6); }
15
+ .fig__cap { font-size: var(--fs-sm); color: var(--text-secondary); margin: var(--sp-2) 0 0; }
16
+ .fig__box { border: 1px solid var(--border-decor); border-radius: var(--r-md);
17
+ padding: var(--sp-3); background: var(--surface); overflow-x: auto; }
18
+ .data-sum { font-size: var(--fs-xs); color: var(--text-tertiary); margin: var(--sp-2) 0 0; }
19
+ .data-sum table { border-collapse: collapse; }
20
+ .data-sum th, .data-sum td { padding: 2px var(--sp-3) 2px 0; text-align: start; }
21
+ .data-sum td.num { font-variant-numeric: tabular-nums; }
22
+ </style>
23
+ </head>
24
+ <body class="page">
25
+ <main class="wrap">
26
+
27
+ <h1>scientific-plot · 二维科学绘图</h1>
28
+ <p class="lede">
29
+ 坐标轴、单位、刻度、误差棒、置信区间带 —— 用原生 SVG 画,
30
+ 零第三方运行时依赖。<strong>本模块不计算任何统计量</strong>,
31
+ 它只把调用方给的数画在正确的位置上。
32
+ </p>
33
+
34
+ <!-- ==================================================================== -->
35
+ <h2 class="rule-top">1 · 函数曲线与坐标轴</h2>
36
+ <p class="note">
37
+ 阻尼振荡 <code>y(t) = A·e^(−λt)·cos(2πft)</code>。
38
+ 曲线是<strong>采样</strong>出来的数据点 —— 调用方传的是函数,不是字符串表达式,
39
+ 本模块<strong>不做表达式求值</strong>。
40
+ </p>
41
+ <figure class="fig">
42
+ <div class="fig__box" id="fig1"></div>
43
+ <figcaption class="fig__cap">
44
+ 图 1 · 阻尼振荡位移随时间的变化。A = 1.00 m,λ = 0.35 s⁻¹,f = 1.20 Hz。
45
+ </figcaption>
46
+ </figure>
47
+
48
+ <!-- ==================================================================== -->
49
+ <h2 class="rule-top">2 · 离散测量 + 误差棒</h2>
50
+ <p class="note">
51
+ 误差棒画的是<strong>调用方给的</strong>误差边界。本模块不判断它表示标准差还是标准误,
52
+ 也不据此推断显著性 —— 这两件事必须由测量者说清楚。
53
+ </p>
54
+ <figure class="fig">
55
+ <div class="fig__box" id="fig2"></div>
56
+ <figcaption class="fig__cap">
57
+ 图 2 · 五种催化剂在不同温度下的转化率(示例数据,误差棒为 ±1 个测量标准差)。
58
+ </figcaption>
59
+ </figure>
60
+
61
+ <!-- ==================================================================== -->
62
+ <h2 class="rule-top">3 · 折线 + 置信区间带 + 参考线</h2>
63
+ <p class="note">
64
+ 区间带是<strong>调用方算好的上下边界</strong>。图上的水平虚线是工艺控制下限。
65
+ </p>
66
+ <figure class="fig">
67
+ <div class="fig__box" id="fig3"></div>
68
+ <figcaption class="fig__cap">
69
+ 图 3 · 反应收率随生产批号的走势与 95% 置信区间(示例数据)。
70
+ </figcaption>
71
+ </figure>
72
+
73
+ <!-- ==================================================================== -->
74
+ <h2 class="rule-top">4 · 对数坐标</h2>
75
+ <p class="note">
76
+ 对数轴<strong>必须显式声明</strong>。跨度跨 6 个数量级时自动只保留 10 的幂做刻度,
77
+ 避免标签挤成一团。若给对数轴一个 ≤ 0 的边界,模块会<strong>直接报错</strong>而不是悄悄修正。
78
+ </p>
79
+ <figure class="fig">
80
+ <div class="fig__box" id="fig4"></div>
81
+ <figcaption class="fig__cap">
82
+ 图 4 · 细菌培养液浓度随时间变化(对数纵轴,示例数据)。
83
+ </figcaption>
84
+ </figure>
85
+
86
+ <h2 class="rule-top">4b · 对数轴上的无效数据(≤ 0)必须明说</h2>
87
+ <p class="note">
88
+ 对数轴上 <code>0</code> 和负数<strong>没有位置</strong>。这里的做法不是"悄悄当成一个很小的正数"
89
+ (那会画出一条看起来正常、实际是假的线),也不是"静默丢掉"(读者会以为那里本来就没测):
90
+ 曲线<strong>断在这两个点两侧</strong>,并且图上明写"有几个点未绘制"。
91
+ </p>
92
+ <figure class="fig">
93
+ <div class="fig__box" id="figLogBad"></div>
94
+ <figcaption class="fig__cap">
95
+ 图 4b · 测值含 0 与负值的情形(示例数据)。第 4 点为 0、第 7 点为负,两者都不在 log 轴上。
96
+ </figcaption>
97
+ </figure>
98
+
99
+ <!-- ==================================================================== -->
100
+ <h2 class="rule-top">5 · 缺失值 ≠ 零(这一节是反例自证)</h2>
101
+ <p class="note">
102
+ 两个序列的<strong>非缺失数据完全相同</strong>,只有缺失的处理方式不同:
103
+ 左边把 <code>null</code> 当缺失 ⇒ 曲线<strong>断开</strong>;
104
+ 右边把缺失当 <code>0</code> ⇒ 曲线<strong>掉到零再爬回来</strong>。
105
+ 后者画出的是一段<strong>不存在的趋势</strong>。
106
+ </p>
107
+ <figure class="fig">
108
+ <div class="fig__box" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--sp-3)">
109
+ <div id="figGap"></div>
110
+ <div id="figZero"></div>
111
+ </div>
112
+ <figcaption class="fig__cap">
113
+ 图 5 · 同一组数据,两种缺失处理。左:缺失断开(正确)。右:缺失当 0(错误,仅用于对照)。
114
+ </figcaption>
115
+ </figure>
116
+
117
+ <div class="data-sum" id="textEquiv"></div>
118
+
119
+ </main>
120
+
121
+ <script src="scientific-plot.js"></script>
122
+ <script>
123
+ (function () {
124
+ 'use strict';
125
+ var P = window.ScientificPlot;
126
+
127
+ /* ---------------------------------------------------- 图 1:阻尼振荡 */
128
+ function damped(t) {
129
+ return 1.00 * Math.exp(-0.35 * t) * Math.cos(2 * Math.PI * 1.20 * t);
130
+ }
131
+ P.render(document.getElementById('fig1'), {
132
+ width: 680, height: 340,
133
+ title: '阻尼振荡位移',
134
+ desc: '采样 400 点',
135
+ x: { label: '时间', unit: 's', scale: 'linear', domain: [0, 4] },
136
+ y: { label: '位移', unit: 'm', scale: 'linear', domain: [-1.1, 1.1] },
137
+ series: [{ type: 'function', fn: damped, domain: [0, 4], samples: 400 }],
138
+ refs: [{ axis: 'y', value: 0 }]
139
+ });
140
+
141
+ /* --------------------------------------- 图 2:离散测量 + 误差棒 */
142
+ var T = [300, 320, 340, 360, 380, 400];
143
+ var catA = [[300, 12, 3], [320, 21, 4], [340, 33, 5], [360, 41, 4], [380, 47, 6], [400, 52, 5]];
144
+ var catB = [[300, 8, 2], [320, 15, 3], [340, 24, 3], [360, 35, 4], [380, 44, 5], [400, 50, 6]];
145
+ void T;
146
+ P.render(document.getElementById('fig2'), {
147
+ width: 680, height: 340,
148
+ title: '催化剂转化率',
149
+ desc: '误差棒为 ±1 标准差',
150
+ x: { label: '温度', unit: 'K', scale: 'linear', domain: [290, 410] },
151
+ y: { label: '转化率', unit: '%', scale: 'linear', domain: [0, 60] },
152
+ /* 🔴 errorbar 与 line 是**同一个系列**(同一种催化剂的测量值 + 走势)
153
+ ⇒ 名字必须一样,它们才会共用一个色号 */
154
+ series: [
155
+ { type: 'errorbar', data: catA, name: '催化剂 A' },
156
+ { type: 'line', data: catA, name: '催化剂 A' },
157
+ { type: 'errorbar', data: catB, name: '催化剂 B' },
158
+ { type: 'line', data: catB, name: '催化剂 B' }
159
+ ]
160
+ });
161
+
162
+ /* ------------------------- 图 3:折线 + 置信区间带 + 参考线 */
163
+ var batches = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
164
+ var yieldMid = [71.2, 73.5, 72.8, 75.1, 76.4, 74.9, 77.2, 78.1, 77.6, 79.3, 80.1, 79.8];
165
+ var yieldBand = yieldMid.map(function (v, i) {
166
+ var hw = 2.6 - i * 0.09; /* 样本越多、估计越稳 —— 这是**调用方**给的半宽 */
167
+ return [batches[i], v - hw, v + hw];
168
+ });
169
+ P.render(document.getElementById('fig3'), {
170
+ width: 680, height: 340,
171
+ title: '反应收率走势',
172
+ desc: '阴影为 95% 置信区间',
173
+ x: { label: '批号', scale: 'linear', domain: [1, 12] },
174
+ y: { label: '收率', unit: '%', scale: 'linear', domain: [66, 84] },
175
+ /* 带 / 线 / 点属于**同一个**系列 ⇒ 同一份名字 ⇒ 同一支色 */
176
+ series: [
177
+ { type: 'band', data: yieldBand, name: '批次收率' },
178
+ { type: 'line', data: batches.map(function (b, i) { return [b, yieldMid[i]]; }),
179
+ name: '批次收率' },
180
+ { type: 'scatter', data: batches.map(function (b, i) { return [b, yieldMid[i]]; }),
181
+ name: '批次收率' }
182
+ ],
183
+ refs: [{ axis: 'y', value: 72, label: '控制下限 72%' }]
184
+ });
185
+
186
+ /* ------------------------------------------------------ 图 4:对数坐标 */
187
+ var hours = [0, 2, 4, 6, 8, 10, 12, 14, 16];
188
+ var cfu = [1.2e2, 3.4e2, 9.8e2, 2.9e3, 8.6e3, 2.5e4, 7.4e4, 2.1e5, 6.0e5];
189
+ P.render(document.getElementById('fig4'), {
190
+ width: 680, height: 340,
191
+ title: '菌液浓度增长',
192
+ desc: '对数纵轴,跨度跨 4 个数量级',
193
+ x: { label: '培养时间', unit: 'h', scale: 'linear', domain: [0, 16] },
194
+ y: { label: '浓度', unit: 'CFU/mL', scale: 'log', domain: [1e2, 1e6] },
195
+ series: [{ type: 'line', data: hours.map(function (h, i) { return [h, cfu[i]]; }),
196
+ name: '实测值' },
197
+ { type: 'scatter', data: hours.map(function (h, i) { return [h, cfu[i]]; }),
198
+ name: '实测值' }]
199
+ });
200
+
201
+ /* --------------------- 图 4b:对数轴上的无效数据必须**明说**
202
+ ------------------------------------------------------------------
203
+ 对数轴上 ≤0 的值**没有位置**(log(0) 没有定义)。三种做法的差别:
204
+ · 悄悄把它当成一个很小的正数 ⇒ 画出一条看起来正常、**实际是假**的线
205
+ · 直接扔掉 ⇒ 读者以为"这里本来就没有点"
206
+ · 【本图采用】断在这两点两侧,并在图上写出"有几个点未绘制"
207
+ ⇒ 这也是"异常数据不变成误导图形"的验收点。 */
208
+ var badY = [[1, 3.2e2], [2, 5.6e2], [3, 9.1e2],
209
+ [4, 0], /* ← 0:对数轴上没有位置 */
210
+ [5, 2.7e3], [6, 4.4e3],
211
+ [7, -5], /* ← 负数:同样没有位置 */
212
+ [8, 1.9e4], [9, 5.8e4]];
213
+ P.render(document.getElementById('figLogBad'), {
214
+ width: 680, height: 300,
215
+ title: '对数轴遇到 ≤0:断开 + 明确提示',
216
+ desc: '第 4 点测值为 0、第 7 点为负,均无法在 log 轴上定位',
217
+ x: { label: '培养时间', unit: 'h', scale: 'linear', domain: [0, 10] },
218
+ y: { label: '计数', unit: 'CFU/mL', scale: 'log', domain: [1e2, 1e5] },
219
+ series: [{ type: 'line', data: badY, name: '实测值' },
220
+ { type: 'scatter', data: badY, name: '实测值' }]
221
+ });
222
+
223
+ /* --------------------------------- 图 5:缺失值断开 vs 当零(反例对照) */
224
+ var signal = [[0, 12], [1, 14], [2, null], [3, null], [4, 21], [5, 24], [6, 22]];
225
+ var asZero = signal.map(function (p) { return [p[0], p[1] === null ? 0 : p[1]]; });
226
+
227
+ P.render(document.getElementById('figGap'), {
228
+ width: 460, height: 300,
229
+ title: '缺失断开(正确)',
230
+ x: { label: '采样点', scale: 'linear', domain: [0, 6] },
231
+ y: { label: '读数', scale: 'linear', domain: [0, 30] },
232
+ series: [{ type: 'line', data: signal }, { type: 'scatter', data: signal }]
233
+ });
234
+ P.render(document.getElementById('figZero'), {
235
+ width: 460, height: 300,
236
+ title: '缺失当 0(错误,仅对照)',
237
+ x: { label: '采样点', scale: 'linear', domain: [0, 6] },
238
+ y: { label: '读数', scale: 'linear', domain: [0, 30] },
239
+ series: [{ type: 'line', data: asZero }, { type: 'scatter', data: asZero }]
240
+ });
241
+
242
+ /* --------------------------- 文本等价信息(原则⑤:结论不能只在图里) */
243
+ document.getElementById('textEquiv').innerHTML =
244
+ '<strong>图 5 的文本等价说明:</strong>' +
245
+ '采样点 2、3 处没有读数(缺失)。左图把这两点之间<strong>断开</strong>,' +
246
+ '读者看到的是"中间没有数据";右图把它们画成 0,' +
247
+ '读者看到的是"信号掉到零又回升"—— 后者是一个<strong>不存在的事件</strong>。' +
248
+ '两张图用的是同一组非缺失数据。';
249
+ })();
250
+ </script>
251
+ </body>
252
+ </html>
@@ -0,0 +1,141 @@
1
+ /* ============================================================================
2
+ scientific-plot.css — 二维科学绘图样式(零依赖 · 纯令牌驱动)
3
+ ============================================================================
4
+ 依赖:01-tokens/tokens.css
5
+ 🔴 全部颜色走令牌:
6
+ - 换主题(明/暗)时图表跟着变,不需要重画
7
+ - 本文件的色值一处都不写死(hardcode-gate 会拦)
8
+
9
+ 🔴 分类色只有 5 个(--splot-s0..s4),超出的曲线靠**线型**区分,
10
+ 不循环用色 —— 第 6 条和第 1 条同色,读者分不清谁是谁。
11
+ 这与 09-assets/echarts-adapter 的 seriesColors 是同一条规则。
12
+ ============================================================================ */
13
+
14
+ .splot {
15
+ display: block;
16
+ max-width: 100%;
17
+ height: auto; /* 窄屏时按比例缩,不横向溢出 */
18
+ font-family: var(--sans);
19
+ }
20
+
21
+ /* ---------- 分类色:一个系列一个变量,各元素消费它 ---------- */
22
+ .splot__s0 { --splot-c: var(--accent); }
23
+ .splot__s1 { --splot-c: var(--danger); }
24
+ .splot__s2 { --splot-c: var(--success); }
25
+ .splot__s3 { --splot-c: var(--warning); }
26
+ .splot__s4 { --splot-c: var(--info); }
27
+
28
+ /* ---------- 网格与轴 ---------- */
29
+ .splot__grid {
30
+ stroke: var(--border-decor);
31
+ stroke-width: 1;
32
+ }
33
+ .splot__axis {
34
+ stroke: var(--border-decor-str);
35
+ stroke-width: 1;
36
+ }
37
+ .splot__tick {
38
+ stroke: var(--border-decor-str);
39
+ stroke-width: 1;
40
+ }
41
+
42
+ /* ---------- 文字:刻度 / 轴名 ---------- */
43
+ .splot__tick-label {
44
+ fill: var(--text-tertiary);
45
+ font-size: var(--fs-xs);
46
+ font-variant-numeric: tabular-nums;
47
+ }
48
+ .splot__axis-label {
49
+ fill: var(--text-secondary);
50
+ font-size: var(--fs-xs);
51
+ font-weight: 500;
52
+ }
53
+
54
+ /* ---------- 数据:线 / 点 / 误差棒 / 区间带 ---------- */
55
+ .splot__line {
56
+ fill: none;
57
+ stroke: var(--splot-c, var(--accent));
58
+ stroke-width: 2;
59
+ stroke-linejoin: round;
60
+ stroke-linecap: round;
61
+ }
62
+ .splot__pt {
63
+ fill: var(--splot-c, var(--accent));
64
+ stroke: var(--surface); /* 点压在线上时留一圈底,避免和线糊在一起 */
65
+ stroke-width: 1;
66
+ }
67
+ .splot__err {
68
+ stroke: var(--splot-c, var(--accent));
69
+ stroke-width: 1.5;
70
+ stroke-linecap: round;
71
+ }
72
+ .splot__band {
73
+ fill: var(--splot-c, var(--accent));
74
+ fill-opacity: .14; /* 区间带要能被下面的网格透出来 */
75
+ stroke: none;
76
+ }
77
+
78
+ /* ---------- 图例 ---------- *
79
+ 🔴 为什么要有:颜色**不是**自解释的。三条不同颜色的曲线但没有名字,
80
+ 这张图就答不出"哪条是哪个"。色号由系列类提供 ⇒ 不可能与图上的线不一致。 */
81
+ .splot__legend {
82
+ display: flex;
83
+ flex-wrap: wrap;
84
+ gap: var(--sp-2) var(--sp-4, 1rem);
85
+ margin: var(--sp-2) 0 0;
86
+ padding: 0;
87
+ list-style: none;
88
+ font-size: var(--fs-xs);
89
+ color: var(--text-secondary);
90
+ }
91
+
92
+ .splot__legend-item {
93
+ display: inline-flex;
94
+ align-items: center;
95
+ gap: var(--sp-1);
96
+ }
97
+
98
+ .splot__legend-mark {
99
+ flex: 0 0 auto;
100
+ overflow: visible;
101
+ }
102
+
103
+ .splot__legend-mark line {
104
+ stroke: var(--splot-c, var(--accent));
105
+ }
106
+
107
+ /* ---------- 参考线 / 标注 / 备注 ---------- */
108
+ .splot__ref {
109
+ stroke: var(--text-tertiary);
110
+ stroke-width: 1;
111
+ stroke-dasharray: 4 4;
112
+ }
113
+ .splot__ref-label {
114
+ fill: var(--text-tertiary);
115
+ font-size: var(--fs-xs);
116
+ }
117
+ .splot__anno-dot {
118
+ fill: var(--text-primary);
119
+ }
120
+ .splot__anno {
121
+ fill: var(--text-primary);
122
+ font-size: var(--fs-xs);
123
+ font-weight: 600;
124
+ }
125
+ .splot__note {
126
+ fill: var(--warning);
127
+ font-size: var(--fs-xs);
128
+ }
129
+
130
+ /* ---------- 高对比度模式:加粗轴与线,避免糊在一起 ---------- */
131
+ @media (prefers-contrast: more) {
132
+ .splot__axis,
133
+ .splot__tick { stroke: var(--text-primary); }
134
+ .splot__line { stroke-width: 3; }
135
+ }
136
+
137
+ /* ---------- 打印:网格退到更浅,线保持清晰 ---------- */
138
+ @media print {
139
+ .splot__grid { stroke: var(--border-decor); }
140
+ .splot__band { fill-opacity: .22; }
141
+ }