agentcss 0.11.14 → 0.11.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/02-primitives/combobox/combobox.js +1 -1
- package/02-primitives/date-range/date-range.js +1 -1
- package/02-primitives/popover/demo.html +1 -1
- package/02-primitives/popover/popover.js +1 -1
- package/02-primitives/select/select.js +1 -1
- package/03-patterns/accordion/accordion.js +25 -5
- package/03-patterns/drawer/drawer.js +1 -1
- package/03-patterns/dropdown/dropdown.js +1 -1
- package/03-patterns/list/flip.js +1 -1
- package/03-patterns/nav/nav.js +6 -3
- package/03-patterns/nav/toc.js +1 -1
- package/03-patterns/overlay/overlay.js +1 -1
- package/03-patterns/pagination/demo.html +1 -1
- package/03-patterns/pagination/pagination.js +9 -3
- package/03-patterns/reveal/reveal.js +4 -1
- package/03-patterns/tabs/tabs.js +12 -3
- package/03-patterns/tooltip/tooltip.js +1 -1
- package/03-patterns/tree/tree.js +1 -1
- package/04-recipes/report/demo.html +2 -2
- package/09-assets/echarts-adapter/demo.html +5 -5
- package/09-assets/model-viewer/demo.html +2 -2
- package/API.md +37 -3
- package/CHANGELOG.md +221 -0
- package/CONTRIBUTING.md +2 -1
- package/README.zh-CN.md +1 -1
- package/START-HERE.md +5 -5
- package/ai/components.json +8 -4
- package/ai/deprecations.schema.json +2 -2
- package/dist/02-primitives/combobox/combobox.js +1 -1
- package/dist/02-primitives/date-range/date-range.js +1 -1
- package/dist/02-primitives/popover/popover.js +1 -1
- package/dist/02-primitives/select/select.js +1 -1
- package/dist/03-patterns/accordion/accordion.js +10 -4
- package/dist/03-patterns/drawer/drawer.js +1 -1
- package/dist/03-patterns/dropdown/dropdown.js +1 -1
- package/dist/03-patterns/list/flip.js +1 -1
- package/dist/03-patterns/nav/nav.js +4 -3
- package/dist/03-patterns/nav/toc.js +1 -1
- package/dist/03-patterns/overlay/overlay.js +1 -1
- package/dist/03-patterns/pagination/pagination.js +4 -3
- package/dist/03-patterns/reveal/reveal.js +2 -1
- package/dist/03-patterns/tabs/tabs.js +8 -3
- package/dist/03-patterns/tooltip/tooltip.js +1 -1
- package/dist/03-patterns/tree/tree.js +1 -1
- package/dist/COSTS.md +10 -10
- package/docs/ACCESSIBILITY.md +3 -3
- package/docs/DEPRECATIONS.md +128 -0
- package/esm/accordion.mjs +7 -0
- package/esm/combobox.mjs +7 -0
- package/esm/date-range.mjs +7 -0
- package/esm/drawer.mjs +7 -0
- package/esm/dropdown.mjs +7 -0
- package/esm/flip.mjs +7 -0
- package/esm/index.mjs +38 -0
- package/esm/nav.mjs +7 -0
- package/esm/overlay.mjs +7 -0
- package/esm/pagination.mjs +7 -0
- package/esm/popover.mjs +7 -0
- package/esm/reveal.mjs +7 -0
- package/esm/select.mjs +7 -0
- package/esm/tabs.mjs +7 -0
- package/esm/toc.mjs +7 -0
- package/esm/tooltip.mjs +7 -0
- package/esm/tree.mjs +7 -0
- package/index.html +1 -1
- package/package.json +10 -3
- package/types/index.d.ts +131 -1
|
@@ -78,7 +78,7 @@ th { font-weight: 600; }
|
|
|
78
78
|
|
|
79
79
|
<h2>怎么选?</h2>
|
|
80
80
|
<div class="demo">
|
|
81
|
-
<table>
|
|
81
|
+
<table aria-label="tooltip / popover / dialog 三者的选择依据">
|
|
82
82
|
<tr><th>组件</th><th>能放交互内容</th><th>背景是否锁死</th><th>用在哪</th></tr>
|
|
83
83
|
<tr><td><code>tooltip</code></td><td>❌ 只能纯文字</td><td>—</td><td>补充说明、术语解释</td></tr>
|
|
84
84
|
<tr><td><b><code>popover</code></b></td><td>✅</td><td><b>不锁</b></td><td>筛选、快捷设置、补充表单</td></tr>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* 否则造成 "landmark region proliferation"(地标泛滥)。
|
|
29
29
|
* ⇒ 加 .accordion--many 即可关闭。
|
|
30
30
|
*/
|
|
31
|
-
(function () {
|
|
31
|
+
(function (global) {
|
|
32
32
|
'use strict';
|
|
33
33
|
// 🔴 手风琴实例序号(保证 id 全局唯一,见 init 里的说明)
|
|
34
34
|
var uid = 0;
|
|
@@ -60,8 +60,13 @@
|
|
|
60
60
|
|
|
61
61
|
function toArray(x) { return Array.prototype.slice.call(x); }
|
|
62
62
|
|
|
63
|
-
/* requestAnimationFrame 的 ES5 安全版
|
|
64
|
-
|
|
63
|
+
/* requestAnimationFrame 的 ES5 安全版
|
|
64
|
+
⚠️ 必须先判 `window` 存在再摸 `.requestAnimationFrame`:
|
|
65
|
+
`typeof window.requestAnimationFrame` 会**先解引用 window**,
|
|
66
|
+
在 Node / SSR 里直接 ReferenceError(不是返回 'undefined')。
|
|
67
|
+
这条曾经让本文件在 Next.js 里 import 即崩。 */
|
|
68
|
+
var raf = (typeof window !== 'undefined' &&
|
|
69
|
+
typeof window.requestAnimationFrame === 'function')
|
|
65
70
|
? window.requestAnimationFrame.bind(window)
|
|
66
71
|
: function (fn) { return setTimeout(fn, 16); };
|
|
67
72
|
|
|
@@ -85,6 +90,12 @@
|
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
function Accordion(root, opts) {
|
|
93
|
+
/* 🔴 同一 root 只允许一个实例。
|
|
94
|
+
不加这条时 `new Accordion(root)` 两次会留下**两份** click 监听
|
|
95
|
+
(旧实例不会被回收:它的监听器闭包referencing this,还挂在 root 上)
|
|
96
|
+
⇒ 一次点击 toggle 两次,肉眼看到的是"点了没反应"。
|
|
97
|
+
构造器返回对象是 JS 合法行为,会覆盖 `this`,调用方拿到的就是旧实例。 */
|
|
98
|
+
if (root && root.accordionInstance) return root.accordionInstance;
|
|
88
99
|
this.root = root;
|
|
89
100
|
this.opts = opts || {};
|
|
90
101
|
this.items = toArray(root.querySelectorAll('.accordion__item'));
|
|
@@ -351,19 +362,28 @@
|
|
|
351
362
|
// 这是「用原生控件」的又一处收益:**无障碍行为免费且必然正确**。
|
|
352
363
|
};
|
|
353
364
|
|
|
354
|
-
|
|
365
|
+
global.Accordion = Accordion;
|
|
355
366
|
|
|
356
367
|
function init() {
|
|
357
368
|
var nodes = document.querySelectorAll('[data-accordion]');
|
|
358
369
|
for (var i = 0; i < nodes.length; i++) {
|
|
370
|
+
/* 🔴 幂等:已经初始化过就跳过。
|
|
371
|
+
不加守卫的后果是**静默的**:第二次 new 会把 accordionInstance 覆盖成新实例,
|
|
372
|
+
而**旧实例挂在 root 上的 click 监听还在** ⇒ 一次点击 toggle 两次
|
|
373
|
+
(展开又收起,看上去"点了没反应")。
|
|
374
|
+
SPA 路由切换、HMR、重复引入同一份脚本都会触发这条路。 */
|
|
375
|
+
if (nodes[i].accordionInstance) continue;
|
|
359
376
|
nodes[i].accordionInstance = new Accordion(nodes[i]);
|
|
360
377
|
}
|
|
361
378
|
}
|
|
362
379
|
|
|
363
380
|
// @autoinit: [data-accordion] —— 自动初始化;与 API.md「自动初始化」表由 autoinit-gate 双向校验
|
|
381
|
+
// ⚠️ 无 DOM 环境(SSR / 构建期 / Node 里 import)不自动初始化。
|
|
382
|
+
// 之前这里直接摸 document ⇒ Next.js 等 SSR 里 import 即 ReferenceError。
|
|
383
|
+
if (typeof document === 'undefined') return;
|
|
364
384
|
if (document.readyState === 'loading') {
|
|
365
385
|
document.addEventListener('DOMContentLoaded', init);
|
|
366
386
|
} else {
|
|
367
387
|
init();
|
|
368
388
|
}
|
|
369
|
-
})();
|
|
389
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
package/03-patterns/list/flip.js
CHANGED
package/03-patterns/nav/nav.js
CHANGED
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
* 手动:new Nav(rootEl, { labels: { open: '打开菜单', close: '关闭菜单' } })
|
|
60
60
|
* 事件:fl-nav-open / fl-nav-close(detail = { root: <nav> })
|
|
61
61
|
*/
|
|
62
|
-
(function () {
|
|
62
|
+
(function (global) {
|
|
63
63
|
'use strict';
|
|
64
64
|
|
|
65
65
|
/* ==== BEHAVIOR INJECT BEGIN: emit ==== */
|
|
@@ -413,7 +413,7 @@
|
|
|
413
413
|
return root.navInstance;
|
|
414
414
|
};
|
|
415
415
|
|
|
416
|
-
|
|
416
|
+
global.Nav = Nav;
|
|
417
417
|
|
|
418
418
|
function init() {
|
|
419
419
|
each(document.querySelectorAll('[data-nav]'), function (el) {
|
|
@@ -422,9 +422,12 @@
|
|
|
422
422
|
}
|
|
423
423
|
|
|
424
424
|
// @autoinit: [data-nav] —— 扫属性自动建实例(详见 README「自动初始化」)
|
|
425
|
+
// ⚠️ 无 DOM 环境(SSR / 构建期 / Node 里 import)不自动初始化。
|
|
426
|
+
// 之前这里直接摸 document ⇒ Next.js 等 SSR 里 import 即 ReferenceError。
|
|
427
|
+
if (typeof document === 'undefined') return;
|
|
425
428
|
if (document.readyState === 'loading') {
|
|
426
429
|
document.addEventListener('DOMContentLoaded', init);
|
|
427
430
|
} else {
|
|
428
431
|
init();
|
|
429
432
|
}
|
|
430
|
-
})();
|
|
433
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
package/03-patterns/nav/toc.js
CHANGED
|
@@ -69,7 +69,7 @@ th { font-size: var(--fs-xs); color: var(--text-secondary); font-weight: 500; }
|
|
|
69
69
|
</div>
|
|
70
70
|
|
|
71
71
|
<h2 class="rule-top">2 · 结构:六条硬要求</h2>
|
|
72
|
-
<table>
|
|
72
|
+
<table aria-label="分页容器的六条结构要求与理由">
|
|
73
73
|
<tr><th>要求</th><th>为什么</th></tr>
|
|
74
74
|
<tr><td>包在 <code><nav aria-label></code> 里</td>
|
|
75
75
|
<td>页面常有多个 nav(主导航/面包屑/分页),
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* });
|
|
36
36
|
* </script>
|
|
37
37
|
*/
|
|
38
|
-
(function () {
|
|
38
|
+
(function (global) {
|
|
39
39
|
'use strict';
|
|
40
40
|
|
|
41
41
|
/* ==== BEHAVIOR INJECT BEGIN: emit ==== */
|
|
@@ -385,11 +385,17 @@
|
|
|
385
385
|
},
|
|
386
386
|
};
|
|
387
387
|
|
|
388
|
-
|
|
388
|
+
/* global 已在 IIFE 收尾处解析成 window 或 globalThis(无 DOM 环境),
|
|
389
|
+
所以这里**无条件挂**——再套一层 `typeof window !== 'undefined'` 会让
|
|
390
|
+
SSR 里 require 得到 undefined(`esm/` 包装就取不到 API)。 */
|
|
391
|
+
global.Pagination = API;
|
|
389
392
|
// @autoinit: [data-pagination] —— 扫属性自动 update()(详见 API.md「自动初始化」)
|
|
393
|
+
// ⚠️ 无 DOM 环境(SSR / 构建期 / Node 里 import)不自动初始化。
|
|
394
|
+
// 之前这里直接摸 document ⇒ Next.js 等 SSR 里 import 即 ReferenceError。
|
|
395
|
+
if (typeof document === 'undefined') return;
|
|
390
396
|
if (document.readyState === 'loading') {
|
|
391
397
|
document.addEventListener('DOMContentLoaded', function () { API.update(); });
|
|
392
398
|
} else {
|
|
393
399
|
API.update();
|
|
394
400
|
}
|
|
395
|
-
})();
|
|
401
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
|
@@ -164,9 +164,12 @@
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// @autoinit: conditional[data-reveal-auto] —— 只有 <html data-reveal-auto> 才 enable();不写则完全不动
|
|
167
|
+
// ⚠️ 无 DOM 环境(SSR / 构建期 / Node 里 import)不自动初始化。
|
|
168
|
+
// 之前这里直接摸 document ⇒ Next.js 等 SSR 里 import 即 ReferenceError。
|
|
169
|
+
if (typeof document === 'undefined') return;
|
|
167
170
|
if (document.readyState === 'loading') {
|
|
168
171
|
document.addEventListener('DOMContentLoaded', auto, false);
|
|
169
172
|
} else {
|
|
170
173
|
auto();
|
|
171
174
|
}
|
|
172
|
-
}(
|
|
175
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
package/03-patterns/tabs/tabs.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* 只在初始化时设一次是最常见的 bug:用户激活第 3 个 tab 后,
|
|
27
27
|
* Tab 键还是会回到第 1 个。
|
|
28
28
|
*/
|
|
29
|
-
(function () {
|
|
29
|
+
(function (global) {
|
|
30
30
|
'use strict';
|
|
31
31
|
|
|
32
32
|
/* ==== BEHAVIOR INJECT BEGIN: emit ==== */
|
|
@@ -165,6 +165,9 @@
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
function Tabs(root, opts) {
|
|
168
|
+
/* 🔴 同一 root 只允许一个实例 —— 理由同 accordion.js。
|
|
169
|
+
重复构造会让 keydown 监听叠两份:方向键按一次跳两格。 */
|
|
170
|
+
if (root && root.tabsInstance) return root.tabsInstance;
|
|
168
171
|
this.root = root;
|
|
169
172
|
this.opts = opts || {};
|
|
170
173
|
this.list = root.querySelector('[role="tablist"]');
|
|
@@ -281,7 +284,7 @@
|
|
|
281
284
|
};
|
|
282
285
|
|
|
283
286
|
// 暴露
|
|
284
|
-
|
|
287
|
+
global.Tabs = Tabs;
|
|
285
288
|
|
|
286
289
|
// 自动初始化:<div class="tabs" data-tabs>
|
|
287
290
|
//
|
|
@@ -294,14 +297,20 @@
|
|
|
294
297
|
function init() {
|
|
295
298
|
var nodes = document.querySelectorAll('[data-tabs]');
|
|
296
299
|
for (var i = 0; i < nodes.length; i++) {
|
|
300
|
+
/* 🔴 幂等:同 accordion.js 里的理由。重复 new 会让 keydown / click
|
|
301
|
+
监听叠在同一个 root 上 ⇒ 方向键按一次跳两格。 */
|
|
302
|
+
if (nodes[i].tabsInstance) continue;
|
|
297
303
|
nodes[i].tabsInstance = new Tabs(nodes[i], {});
|
|
298
304
|
}
|
|
299
305
|
}
|
|
300
306
|
|
|
301
307
|
// @autoinit: [data-tabs] —— 扫属性自动建实例(详见 API.md「自动初始化」)
|
|
308
|
+
// ⚠️ 无 DOM 环境(SSR / 构建期 / Node 里 import)不自动初始化。
|
|
309
|
+
// 之前这里直接摸 document ⇒ Next.js 等 SSR 里 import 即 ReferenceError。
|
|
310
|
+
if (typeof document === 'undefined') return;
|
|
302
311
|
if (document.readyState === 'loading') {
|
|
303
312
|
document.addEventListener('DOMContentLoaded', init);
|
|
304
313
|
} else {
|
|
305
314
|
init();
|
|
306
315
|
}
|
|
307
|
-
})();
|
|
316
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
package/03-patterns/tree/tree.js
CHANGED
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
写死数字的话,插入一张新图后面全会错位。
|
|
182
182
|
同一句标记放在 financial 版里不会出编号 —— 那是 profile 决定的,不是标记决定的。 -->
|
|
183
183
|
<figure class="rep__fig">
|
|
184
|
-
<div class="table"><table>
|
|
184
|
+
<div class="table"><table aria-label="关键读数:包覆方案与保持率">
|
|
185
185
|
<thead><tr>
|
|
186
186
|
<th scope="col">方案</th>
|
|
187
187
|
<th scope="col">保持率</th>
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
<h3>关键假设</h3>
|
|
249
249
|
<!-- 同一句标记放在 finance 版:没有编号,因为 financial profile 不开 counter -->
|
|
250
250
|
<figure class="rep__fig">
|
|
251
|
-
<div class="table"><table>
|
|
251
|
+
<div class="table"><table aria-label="关键假设:三种情形下的良率与毛利率">
|
|
252
252
|
<thead><tr>
|
|
253
253
|
<th scope="col">情形</th>
|
|
254
254
|
<th scope="col">良率</th>
|
|
@@ -44,7 +44,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
44
44
|
</p>
|
|
45
45
|
|
|
46
46
|
<h2 class="rule-top">0 · 边界:什么该用本库,什么该用 ECharts</h2>
|
|
47
|
-
<table>
|
|
47
|
+
<table aria-label="能力边界:什么场景用本库、什么用 ECharts">
|
|
48
48
|
<tr><th>场景</th><th>用什么</th><th>谁维护</th></tr>
|
|
49
49
|
<tr><td>列表右侧的<strong>迷你趋势</strong>(看走势)</td>
|
|
50
50
|
<td class="ok">本库 <code>sparkline</code>(1.5KB,零依赖)</td><td>我们</td></tr>
|
|
@@ -94,7 +94,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
94
94
|
<div class="flex">
|
|
95
95
|
<div class="box">
|
|
96
96
|
<h3 style="margin-top:0">✅ 规范:柱状图(分类轴从 0)</h3>
|
|
97
|
-
<table>
|
|
97
|
+
<table aria-label="示例数据:柱状图的分季度营收">
|
|
98
98
|
<tr><th>季度</th><th class="num">营收(亿)</th><th class="num">同比</th></tr>
|
|
99
99
|
<tr><td>Q1</td><td class="num">128.4</td><td class="num up">+12.4%</td></tr>
|
|
100
100
|
<tr><td>Q2</td><td class="num">136.1</td><td class="num up">+8.1%</td></tr>
|
|
@@ -109,7 +109,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
109
109
|
|
|
110
110
|
<div class="box">
|
|
111
111
|
<h3 style="margin-top:0">✅ 规范:多系列(≤ 5 条)</h3>
|
|
112
|
-
<table>
|
|
112
|
+
<table aria-label="示例数据:A / B / C 三支股票的逐年对比">
|
|
113
113
|
<tr><th>年份</th>
|
|
114
114
|
<th class="num"><span class="swatch" style="background:var(--accent)"></span>A 股</th>
|
|
115
115
|
<th class="num"><span class="swatch" style="background:var(--danger)"></span>B 股</th>
|
|
@@ -133,7 +133,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
133
133
|
</div>
|
|
134
134
|
|
|
135
135
|
<h2 class="rule-top">3 · 数字格式(已经在用)</h2>
|
|
136
|
-
<table>
|
|
136
|
+
<table aria-label="数字格式规则与例子">
|
|
137
137
|
<tr><th>类型</th><th>规则</th><th>例子</th></tr>
|
|
138
138
|
<tr><td>千分位</td><td>每三位加逗号</td><td class="num">1,234,567</td></tr>
|
|
139
139
|
<tr><td>百分比</td><td>固定 1–2 位小数</td><td class="num">42.6%</td></tr>
|
|
@@ -148,7 +148,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
148
148
|
|
|
149
149
|
<h2 class="rule-top">4 · 明确禁止(这些是"看起来专业但会骗人"的)</h2>
|
|
150
150
|
<div class="box bad" data-claim-skip="这一块是「不要做」清单本身(一张表),不是某个组件的错写法 —— 要给它配正例栏,得先真的渲染一张 3D 图与一张 2D 图做对照,而本页没有图表实例可摆;表格尺寸量出来的是排版,不是观点">
|
|
151
|
-
<table>
|
|
151
|
+
<table aria-label="明确禁止的做法与原因">
|
|
152
152
|
<tr><th>不要做</th><th>为什么</th></tr>
|
|
153
153
|
<tr><td class="no">3D 图表</td><td>透视扭曲会<b>误导读数</b>(Tufte 的核心结论)</td></tr>
|
|
154
154
|
<tr><td class="no">双 Y 轴</td><td>两轴的交叉点可以被随意搬动 ⇒ <b>视觉在说谎</b></td></tr>
|
|
@@ -59,7 +59,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
59
59
|
data-mv-orbit="vendor/OrbitControls.js"></div>
|
|
60
60
|
|
|
61
61
|
<h2 class="rule-top">为什么是这样设计的</h2>
|
|
62
|
-
<table>
|
|
62
|
+
<table aria-label="3D 模型页的设计要求与做法">
|
|
63
63
|
<tr><th>要求</th><th>做法</th></tr>
|
|
64
64
|
<tr><td>首屏要快</td>
|
|
65
65
|
<td>3D 引擎<strong>点击后</strong>才 <code><script></code> 注入,
|
|
@@ -85,7 +85,7 @@ td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabu
|
|
|
85
85
|
</ul>
|
|
86
86
|
|
|
87
87
|
<h2 class="rule-top">体积现状</h2>
|
|
88
|
-
<table>
|
|
88
|
+
<table aria-label="各文件的体积与加载时机">
|
|
89
89
|
<tr><th>文件</th><th class="num">体积</th><th>何时加载</th></tr>
|
|
90
90
|
<tr><td><code>model-viewer.js</code>(本库)</td><td class="num">~9 KB</td><td><span class="ok">首屏</span></td></tr>
|
|
91
91
|
<tr><td><code>models/fox.glb</code></td><td class="num">159 KB</td><td>点击后(可 XHR 显示进度)</td></tr>
|
package/API.md
CHANGED
|
@@ -24,6 +24,30 @@
|
|
|
24
24
|
各有各的调用方式。下表由`05-audit/global-api-probe.js`在真实浏览器里
|
|
25
25
|
探测生成,门禁 `api-doc` 会核对本文与实现是否一致。
|
|
26
26
|
|
|
27
|
+
### 模块化引入(ESM)
|
|
28
|
+
|
|
29
|
+
除了 `<script src>`,16 个交互组件的脚本还有一个 ESM 入口:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
// 只要一个
|
|
33
|
+
import { Accordion } from 'agentcss/esm/accordion.mjs';
|
|
34
|
+
|
|
35
|
+
// 或者一次拿全(体积更大,Vite/Rollup 会按需摇树)
|
|
36
|
+
import { Accordion, Tabs, Select } from 'agentcss/esm';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
三条容易踩的:
|
|
40
|
+
|
|
41
|
+
1. **入口是包装,不是第二份实现**。`esm/*.mjs` 只做
|
|
42
|
+
「导入副作用 + 把全局上那个对象 re-export」,所以
|
|
43
|
+
`Accordion === window.Accordion` 恒成立(门禁 `behavior-api` 断言这一点)。
|
|
44
|
+
它由 `05-audit/gen-esm.py` 生成,改源码后要重新生成,`esm-gen` 门禁会拦住漂移。
|
|
45
|
+
2. **无 DOM 环境可以直接 import**(SSR 安全)。但自动初始化会被跳过 ——
|
|
46
|
+
服务端没有 DOM 可扫,到浏览器里再调 `init()`/构造函数。16 个脚本
|
|
47
|
+
在 Node 里 `require` 全部成功(门禁的判据 A)。
|
|
48
|
+
3. **重复初始化是安全的**。`init()` 与构造函数都做了幂等处理:
|
|
49
|
+
同一 root 只会有一个实例,不会出现「点一次切换两次」。
|
|
50
|
+
|
|
27
51
|
### 四种接入形态
|
|
28
52
|
|
|
29
53
|
| 形态 | 调用方式 | 适合 |
|
|
@@ -327,6 +351,16 @@ python3 05-audit/prefix-build.py --prefix fl
|
|
|
327
351
|
|
|
328
352
|
## 破坏性变更怎么走
|
|
329
353
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
-
|
|
354
|
+
公开**名字**(令牌名 / 类名 / 全局与类型成员 / 事件名)的移除走**登记制**:
|
|
355
|
+
|
|
356
|
+
- 先在 `ai/deprecations.json` 里登记,写清 `deprecatedIn`、`removeIn`、`reason`
|
|
357
|
+
- 迁移窗口**至少跨一个次版本**:`0.7.x` 里标弃用 ⇒ 最早 `0.8.0` 才允许消失
|
|
358
|
+
- 到期才删。**提前删**和**到期不删**都会被门禁拦下(`05-audit/deprecation-gate.py`)
|
|
359
|
+
- 对外说明在 `docs/DEPRECATIONS.md`,那份文档与登记册由门禁**双向**比对,
|
|
360
|
+
漏告知(登记了没写进文档)与假承诺(文档写了、登记册没有)都会红
|
|
361
|
+
|
|
362
|
+
> 🔴 本节此前写的是「只在**大版本**移除」「弃用项先加警告并保留一个完整版本周期」——
|
|
363
|
+
> 两句都是错的:本库在 `0.7.x → 0.8.0` 就删过名字(`state--delayed`),
|
|
364
|
+
> 而且组件脚本从不打印运行时警告(移动端 WebView 里那是纯噪音)。
|
|
365
|
+
> `0.x` 期间按 semver 本就允许破坏性变更,把话说满比说清更伤人。
|
|
366
|
+
> 现在这两句被上面四条取代,覆盖范围与抓不到哪些名字见 `docs/DEPRECATIONS.md`。
|