agentcss 0.25.6 → 0.26.0

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 (56) hide show
  1. package/01-tokens/behavior/labels.js +44 -0
  2. package/02-primitives/combobox/combobox.js +26 -3
  3. package/02-primitives/date-range/date-range.js +27 -5
  4. package/02-primitives/popover/popover.js +22 -2
  5. package/02-primitives/select/select.js +23 -2
  6. package/02-primitives/upload/upload.js +50 -17
  7. package/03-patterns/content/content.css +13 -1
  8. package/03-patterns/content/demo.html +1 -1
  9. package/03-patterns/drawer/drawer.js +44 -6
  10. package/03-patterns/dropdown/dropdown.js +21 -1
  11. package/03-patterns/overlay/overlay.js +39 -2
  12. package/03-patterns/pagination/pagination.js +37 -10
  13. package/03-patterns/tooltip/tooltip.js +17 -2
  14. package/03-patterns/tree/tree.js +21 -1
  15. package/04-recipes/analysis-report/demo.html +1 -1
  16. package/04-recipes/data-showcase/demo.html +2 -2
  17. package/04-recipes/longform/content.html +989 -74
  18. package/04-recipes/longform/longform.html +3 -3
  19. package/04-recipes/report/demo.html +1 -1
  20. package/04-recipes/table/README.md +22 -0
  21. package/04-recipes/table/demo.html +6 -6
  22. package/09-assets/bar/bar.js +28 -4
  23. package/09-assets/model-viewer/model-viewer.js +44 -12
  24. package/09-assets/scientific-plot/demo.html +6 -6
  25. package/API.md +32 -0
  26. package/CHANGELOG.md +71 -0
  27. package/README.md +17 -0
  28. package/README.zh-CN.md +16 -0
  29. package/SECURITY.md +16 -4
  30. package/START-HERE.md +14 -14
  31. package/ai/components.json +9 -4
  32. package/ai/pdf.js +50 -8
  33. package/dist/01-tokens/behavior/labels.js +11 -0
  34. package/dist/02-primitives/combobox/combobox.js +25 -3
  35. package/dist/02-primitives/date-range/date-range.js +26 -5
  36. package/dist/02-primitives/popover/popover.js +14 -1
  37. package/dist/02-primitives/select/select.js +22 -2
  38. package/dist/02-primitives/upload/upload.js +47 -17
  39. package/dist/03-patterns/content/content.css +1 -1
  40. package/dist/03-patterns/drawer/drawer.js +32 -4
  41. package/dist/03-patterns/dropdown/dropdown.js +20 -1
  42. package/dist/03-patterns/overlay/overlay.js +25 -1
  43. package/dist/03-patterns/pagination/pagination.js +34 -10
  44. package/dist/03-patterns/tooltip/tooltip.js +14 -2
  45. package/dist/03-patterns/tree/tree.js +20 -1
  46. package/dist/09-assets/bar/bar.js +23 -4
  47. package/dist/09-assets/model-viewer/model-viewer.js +38 -12
  48. package/dist/COSTS.md +14 -14
  49. package/docs/ACCESSIBILITY.md +2 -2
  50. package/docs/L10N.md +92 -0
  51. package/docs/RELEASE-PROCESS.md +7 -1
  52. package/docs/VERIFY-RELEASE.md +7 -2
  53. package/index.html +1 -1
  54. package/llms-full.txt +2 -2
  55. package/package.json +3 -2
  56. package/types/index.d.ts +218 -13
@@ -61,12 +61,36 @@ if (total > 1) out.push(total);
61
61
  return out;
62
62
  }
63
63
 
64
- function Pagination(node) {
64
+ var DEFAULT_LABELS = {
65
+ nav: '分页',
66
+ prev: '上一页',
67
+ next: '下一页',
68
+ page: function (p, isCurrent) {
69
+ return '第 ' + p + ' 页' + (isCurrent ? '(当前页)' : '');
70
+ },
71
+ status: function (page, pages) { return '第 ' + page + ' 页 / 共 ' + pages + ' 页'; },
72
+ live: function (page, pages) { return '第 ' + page + ' 页,共 ' + pages + ' 页'; }
73
+ };
74
+
75
+ var flLabels = function (defaults, src) {
76
+ src = src || {};
77
+ var out = {};
78
+ var k;
79
+ for (k in defaults) {
80
+ if (Object.prototype.hasOwnProperty.call(defaults, k)) {
81
+ out[k] = (src[k] === undefined || src[k] === null) ? defaults[k] : src[k];
82
+ }
83
+ }
84
+ return out;
85
+ };
86
+
87
+ function Pagination(node, opts) {
65
88
  this.node = node;
89
+ this.labels = flLabels(DEFAULT_LABELS, opts && opts.labels);
66
90
  this.total = Math.max(1, parseInt(node.getAttribute('data-total') || '1', 10));
67
91
  this.size = Math.max(1, parseInt(node.getAttribute('data-page-size') || '20', 10));
68
92
  this.page = Math.max(1, parseInt(node.getAttribute('data-page') || '1', 10));
69
- this.label = node.getAttribute('aria-label') || '分页';
93
+ this.label = node.getAttribute('aria-label') || this.labels.nav;
70
94
  this.pages = Math.max(1, Math.ceil(this.total / this.size));
71
95
  this.onChange = null;
72
96
 
@@ -186,7 +210,7 @@ if (cur && cur.focus) cur.focus();
186
210
 
187
211
  Pagination.prototype.announce = function () {
188
212
  if (!this.liveNode) return;
189
- this.liveNode.textContent = '第 ' + this.page + ' 页,共 ' + this.pages + ' 页';
213
+ this.liveNode.textContent = this.labels.live(this.page, this.pages);
190
214
  };
191
215
 
192
216
  Pagination.prototype.render = function () {
@@ -194,6 +218,7 @@ if (!this.listNode) return;
194
218
  var L = this.listNode;
195
219
  while (L.firstChild) L.removeChild(L.firstChild);
196
220
  var self = this;
221
+ var T = this.labels;
197
222
 
198
223
  function addBtn(text, ariaLabel, goto, disabled) {
199
224
  var li = el('li', 'pagination__item');
@@ -208,7 +233,7 @@ L.appendChild(li);
208
233
  return b;
209
234
  }
210
235
 
211
- addBtn('‹', '上一页', 'prev', self.page <= 1);
236
+ addBtn('‹', T.prev, 'prev', self.page <= 1);
212
237
 
213
238
  var win = pageWindow(self.page, self.pages, SLOTS);
214
239
  for (var i = 0; i < win.length; i++) {
@@ -227,7 +252,7 @@ var li2 = el('li', 'pagination__item');
227
252
  var b2 = el('button', 'pagination__link', String(p));
228
253
  b2.type = 'button';
229
254
  b2.setAttribute('data-goto', String(p));
230
- b2.setAttribute('aria-label', '第 ' + p + ' 页' + (isCur ? '(当前页)' : ''));
255
+ b2.setAttribute('aria-label', T.page(p, isCur));
231
256
  if (isCur) {
232
257
  b2.setAttribute('aria-current', 'page');
233
258
  b2.setAttribute('aria-disabled', 'true');
@@ -236,20 +261,19 @@ li2.appendChild(b2);
236
261
  L.appendChild(li2);
237
262
  }
238
263
 
239
- addBtn('›', '下一页', 'next', self.page >= self.pages);
264
+ addBtn('›', T.next, 'next', self.page >= self.pages);
240
265
 
241
266
  if (this.statusNode) {
242
- this.statusNode.textContent =
243
- '第 '+ self.page + ' 页 / 共 ' + self.pages + ' 页';
267
+ this.statusNode.textContent = T.status(self.page, self.pages);
244
268
  }
245
269
  };
246
270
 
247
271
  var API = {
248
272
 
249
- create: function (node) {
273
+ create: function (node, opts) {
250
274
  if (!node) return null;
251
275
  if (node.__pg) return node.__pg;
252
- node.__pg = new Pagination(node);
276
+ node.__pg = new Pagination(node, opts);
253
277
  return node.__pg;
254
278
  },
255
279
 
@@ -99,6 +99,18 @@ if (k >= 0) shared.stack.splice(k, 1);
99
99
 
100
100
  var uid = 0;
101
101
 
102
+ var LABELS = { region: '组件提示' };
103
+
104
+ function setLabels(patch) {
105
+ if (!patch) return;
106
+ for (var k in LABELS) {
107
+ if (Object.prototype.hasOwnProperty.call(LABELS, k)
108
+ && patch[k] !== undefined && patch[k] !== null) {
109
+ LABELS[k] = patch[k];
110
+ }
111
+ }
112
+ }
113
+
102
114
  function ensureStyle() {
103
115
  if (document.getElementById('tooltip-css')) return;
104
116
 
@@ -115,7 +127,7 @@ r.setAttribute('role', 'tooltip');
115
127
  r.setAttribute('aria-live', 'polite');
116
128
  r.setAttribute('aria-atomic', 'true');
117
129
 
118
- r.setAttribute('aria-label', '组件提示');
130
+ r.setAttribute('aria-label', LABELS.region);
119
131
  r.style.cssText =
120
132
  'position:absolute;width:1px;height:1px;padding:0;margin:-1px;'+
121
133
  'overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0';
@@ -211,5 +223,5 @@ el.setAttribute('aria-describedby', cur ? (cur + ' ' + id) : id);
211
223
  el.setAttribute('data-tooltip', text);
212
224
  }
213
225
 
214
- global.Tooltip = { attach: attach };
226
+ global.Tooltip = { attach: attach, setLabels: setLabels };
215
227
  })(typeof window !== 'undefined' ? window : globalThis);
@@ -196,11 +196,30 @@ return true;
196
196
  var uid = 0;
197
197
 
198
198
  function create(root, opt) {
199
+
200
+ var DEFAULT_LABELS = {
201
+ tree: '树形视图'
202
+ };
203
+
204
+ var flLabels = function (defaults, src) {
205
+ src = src || {};
206
+ var out = {};
207
+ var k;
208
+ for (k in defaults) {
209
+ if (Object.prototype.hasOwnProperty.call(defaults, k)) {
210
+ out[k] = (src[k] === undefined || src[k] === null) ? defaults[k] : src[k];
211
+ }
212
+ }
213
+ return out;
214
+ };
215
+
216
+ var L = flLabels(DEFAULT_LABELS, opt && opt.labels);
217
+
199
218
  opt = opt || {};
200
219
  root.classList.add('tree');
201
220
  if (!root.getAttribute('role')) root.setAttribute('role', 'tree');
202
221
  if (!root.getAttribute('aria-label') && !root.getAttribute('aria-labelledby')) {
203
- root.setAttribute('aria-label', opt.label || '树形视图');
222
+ root.setAttribute('aria-label', opt.label || L.tree);
204
223
  }
205
224
 
206
225
  var items = [];
@@ -27,9 +27,30 @@ e.setAttribute(k, String(attrs[k]));
27
27
  return e;
28
28
  }
29
29
 
30
+ var DEFAULT_TEXT = {
31
+ series: function (i) { return '系列 ' + i; },
32
+ clipped: function (n, isStack, max) {
33
+ return '有 ' + n + ' 个' + (isStack ? '类目的合计' : '数据')
34
+ + '超出量程(上限 ' + max + '),已按上限截断显示。';
35
+ }
36
+ };
37
+
38
+ var flLabels = function (defaults, src) {
39
+ src = src || {};
40
+ var out = {};
41
+ var k;
42
+ for (k in defaults) {
43
+ if (Object.prototype.hasOwnProperty.call(defaults, k)) {
44
+ out[k] = (src[k] === undefined || src[k] === null) ? defaults[k] : src[k];
45
+ }
46
+ }
47
+ return out;
48
+ };
49
+
30
50
  function draw(opt) {
31
51
  opt = opt || {};
32
52
  var host = opt.host;
53
+ var T = flLabels(DEFAULT_TEXT, opt && opt.text);
33
54
  if (!host) throw new Error('bar.draw: 缺少 host');
34
55
  if (opt.max === undefined || opt.max === null) {
35
56
 
@@ -187,7 +208,7 @@ sw.className = 'bar__legend-swatch ' + SERIES_CLS[si % SERIES_STYLES] +
187
208
 
188
209
  li.appendChild(sw);
189
210
  var tx = document.createElement('span');
190
- tx.textContent = se.name || ('系列 ' + (si + 1));
211
+ tx.textContent = se.name || T.series(si + 1);
191
212
  li.appendChild(tx);
192
213
  legendEl.appendChild(li);
193
214
  });
@@ -202,9 +223,7 @@ host.appendChild(p);
202
223
  } else if (clipped.length) {
203
224
  var p2 = document.createElement('p');
204
225
  p2.className = 'bar__note';
205
- p2.textContent = '有 ' + clipped.length + ' 个' +
206
- (mode === 'stack' ? '类目的合计' : '数据') +
207
- '超出量程(上限 '+ max + '),已按上限截断显示。';
226
+ p2.textContent = T.clipped(clipped.length, mode === 'stack', max);
208
227
  host.appendChild(p2);
209
228
  }
210
229
 
@@ -62,7 +62,7 @@ this.ui = el('div', 'mv__ui');
62
62
  this.ui.appendChild(this.makeIdle());
63
63
  n.appendChild(this.ui);
64
64
 
65
- this.btn = el('button', 'mv__btn', '加载 3D 模型');
65
+ this.btn = el('button', 'mv__btn', LABELS.load);
66
66
  this.btn.type = 'button';
67
67
  this.btn.addEventListener('click', function () { self.load(); });
68
68
  this.ui.appendChild(this.btn);
@@ -70,23 +70,23 @@ this.ui.appendChild(this.btn);
70
70
  this.hint = el('p', 'mv__hint');
71
71
 
72
72
  var fname = el('code', null, this.src.split('/').pop() || '—');
73
- var strong = el('b', null, '点击后才下载');
74
- this.hint.appendChild(document.createTextNode('模型 '));
73
+ var strong = el('b', null, LABELS.hintStrong);
74
+ this.hint.appendChild(document.createTextNode(LABELS.hintBefore));
75
75
  this.hint.appendChild(fname);
76
- this.hint.appendChild(document.createTextNode(' 会'));
76
+ this.hint.appendChild(document.createTextNode(LABELS.hintBetween));
77
77
  this.hint.appendChild(strong);
78
- this.hint.appendChild(document.createTextNode(',首屏不占流量。'));
78
+ this.hint.appendChild(document.createTextNode(LABELS.hintTail));
79
79
  this.ui.appendChild(this.hint);
80
80
 
81
81
  if (!hasWebGL()) {
82
- this.fail('这台设备的浏览器不支持 WebGL,无法显示 3D 模型。');
82
+ this.fail(LABELS.noWebGL);
83
83
  this.btn.disabled = true;
84
84
  }
85
85
  };
86
86
 
87
87
  Viewer.prototype.makeIdle = function () {
88
88
  var box = el('div', 'mv__stage');
89
- box.appendChild(el('div', 'mv__ph', '3D 模型'));
89
+ box.appendChild(el('div', 'mv__ph', LABELS.placeholder));
90
90
  return box;
91
91
  };
92
92
 
@@ -95,14 +95,14 @@ if (this.timer) { clearTimeout(this.timer); this.timer = null; }
95
95
  this.state = 'error';
96
96
  this.ui.innerHTML = '';
97
97
  var s = el('div', 'mv__stage mv__stage--err');
98
- s.appendChild(el('div', 'mv__ph', '3D 模型'));
98
+ s.appendChild(el('div', 'mv__ph', LABELS.placeholder));
99
99
  var p = el('p', 'mv__err', msg);
100
100
  s.appendChild(p);
101
101
  this.ui.appendChild(s);
102
102
  if (this.btn) this.ui.appendChild(this.btn);
103
103
  if (this.btn) {
104
104
  this.btn.disabled = false;
105
- this.btn.textContent = '重试';
105
+ this.btn.textContent = LABELS.retry;
106
106
  }
107
107
  };
108
108
 
@@ -117,12 +117,12 @@ this.state = 'loading';
117
117
 
118
118
  this.ui.innerHTML = '';
119
119
  var stage = el('div', 'mv__stage');
120
- this.statusNode = el('p', 'mv__status', '正在准备…');
120
+ this.statusNode = el('p', 'mv__status', LABELS.preparing);
121
121
  stage.appendChild(this.statusNode);
122
122
  this.ui.appendChild(stage);
123
123
 
124
124
  var t0 = (window.performance && performance.now) ? performance.now() : Date.now();
125
- this.status('正在准备 3D 引擎…');
125
+ this.status(LABELS.preparingEngine);
126
126
  this.boot(null, t0, 0);
127
127
 
128
128
  var self0 = this;
@@ -205,7 +205,7 @@ xhr.open('GET', this.src, true);
205
205
  xhr.onprogress = function (e) {
206
206
  if (e.lengthComputable && e.total) {
207
207
  self1.lastBytes = e.total;
208
- self1.status('正在下载模型 ' + Math.round(e.loaded / e.total * 100) + '%');
208
+ self1.status(LABELS.downloading(Math.round(e.loaded / e.total * 100)));
209
209
  }
210
210
  };
211
211
  xhr.onload = function () {
@@ -292,6 +292,30 @@ self.fail('模型加载失败:' + msg + '。请确认 ' + self.src + ' 已部
292
292
  }
293
293
  };
294
294
 
295
+ var LABELS = {
296
+ load: '加载 3D 模型',
297
+ placeholder: '3D 模型',
298
+ retry: '重试',
299
+ preparing: '正在准备…',
300
+ preparingEngine: '正在准备 3D 引擎…',
301
+ hintBefore: '模型 ',
302
+ hintBetween: ' 会',
303
+ hintStrong: '点击后才下载',
304
+ hintTail: ',首屏不占流量。',
305
+ downloading: function (pct) { return '正在下载模型 ' + pct + '%'; },
306
+ noWebGL: '这台设备的浏览器不支持 WebGL,无法显示 3D 模型。'
307
+ };
308
+
309
+ function setLabels(patch) {
310
+ if (!patch) return;
311
+ for (var k in LABELS) {
312
+ if (Object.prototype.hasOwnProperty.call(LABELS, k)
313
+ && patch[k] !== undefined && patch[k] !== null) {
314
+ LABELS[k] = patch[k];
315
+ }
316
+ }
317
+ }
318
+
295
319
  var ModelViewer = {
296
320
 
297
321
  update: function (root) {
@@ -317,6 +341,8 @@ list[i].__mv = new Viewer(list[i]);
317
341
  },
318
342
  };
319
343
 
344
+ ModelViewer.setLabels = setLabels;
345
+
320
346
  if (typeof window !== 'undefined') window.ModelViewer = ModelViewer;
321
347
 
322
348
  if (document.readyState === 'loading') {
package/dist/COSTS.md CHANGED
@@ -22,38 +22,38 @@
22
22
  | primitive | `button` | 2.9 KB | 1.0 KB | — | **3.9 KB** | 28.3 KB | −24.4 KB |
23
23
  | primitive | `card` | 2.9 KB | 0.9 KB | — | **3.9 KB** | 26.0 KB | −22.1 KB |
24
24
  | primitive | `choice` | 2.9 KB | 1.1 KB | — | **4.1 KB** | 28.1 KB | −24.0 KB |
25
- | primitive | `combobox` | 2.9 KB | 1.0 KB | 5.5 KB | **9.4 KB** | 31.5 KB | −22.1 KB |
26
- | primitive | `date-range` | 2.9 KB | 0.8 KB | 2.6 KB | **6.3 KB** | 28.6 KB | −22.3 KB |
25
+ | primitive | `combobox` | 2.9 KB | 1.0 KB | 5.7 KB | **9.6 KB** | 31.8 KB | −22.2 KB |
26
+ | primitive | `date-range` | 2.9 KB | 0.8 KB | 2.8 KB | **6.6 KB** | 28.9 KB | −22.4 KB |
27
27
  | primitive | `delta` | 2.9 KB | 0.3 KB | — | **3.2 KB** | 24.7 KB | −21.5 KB |
28
28
  | primitive | `input` | 2.9 KB | 1.0 KB | — | **4.0 KB** | 25.8 KB | −21.9 KB |
29
29
  | primitive | `metric` | 2.9 KB | 0.5 KB | — | **3.4 KB** | 25.1 KB | −21.7 KB |
30
- | primitive | `popover` | 2.9 KB | 0.8 KB | 2.2 KB | **5.9 KB** | 29.3 KB | −23.4 KB |
30
+ | primitive | `popover` | 2.9 KB | 0.8 KB | 2.3 KB | **6.1 KB** | 29.7 KB | −23.7 KB |
31
31
  | primitive | `progress` | 2.9 KB | 0.8 KB | — | **3.7 KB** | 26.2 KB | −22.5 KB |
32
- | primitive | `select` | 2.9 KB | 0.8 KB | 4.1 KB | **7.9 KB** | 32.9 KB | −24.9 KB |
32
+ | primitive | `select` | 2.9 KB | 0.8 KB | 4.3 KB | **8.1 KB** | 33.1 KB | −25.0 KB |
33
33
  | primitive | `separator` | 2.9 KB | 0.2 KB | — | **3.2 KB** | 23.2 KB | −20.0 KB |
34
34
  | primitive | `skeleton` | 2.9 KB | 0.5 KB | — | **3.4 KB** | 23.8 KB | −20.4 KB |
35
35
  | primitive | `switch` | 2.9 KB | 0.8 KB | — | **3.7 KB** | 30.3 KB | −26.5 KB |
36
36
  | primitive | `timeline` | 2.9 KB | 0.5 KB | — | **3.4 KB** | 25.2 KB | −21.7 KB |
37
- | primitive | `upload` | 2.9 KB | 1.4 KB | 4.2 KB | **8.5 KB** | 39.3 KB | −30.8 KB |
37
+ | primitive | `upload` | 2.9 KB | 1.4 KB | 4.5 KB | **8.8 KB** | 39.7 KB | −30.9 KB |
38
38
  | pattern | `accordion` | 2.9 KB | 1.3 KB | 1.8 KB | **6.0 KB** | 36.4 KB | −30.4 KB |
39
- | pattern | `content` | 2.9 KB | 1.0 KB | — | **4.0 KB** | 26.5 KB | −22.5 KB |
40
- | pattern | `drawer` | 2.9 KB | 0.8 KB | 2.6 KB | **6.3 KB** | 30.2 KB | −23.9 KB |
41
- | pattern | `dropdown` | 2.9 KB | 0.8 KB | 3.5 KB | **7.2 KB** | 31.6 KB | −24.4 KB |
39
+ | pattern | `content` | 2.9 KB | 1.0 KB | — | **4.0 KB** | 26.8 KB | −22.9 KB |
40
+ | pattern | `drawer` | 2.9 KB | 0.8 KB | 2.8 KB | **6.6 KB** | 30.8 KB | −24.3 KB |
41
+ | pattern | `dropdown` | 2.9 KB | 0.8 KB | 3.6 KB | **7.3 KB** | 31.8 KB | −24.5 KB |
42
42
  | pattern | `form-validation` | 2.9 KB | 0.8 KB | — | **3.7 KB** | 26.8 KB | −23.1 KB |
43
43
  | pattern | `list` | 2.9 KB | 0.6 KB | — | **3.5 KB** | 24.3 KB | −20.8 KB |
44
44
  | pattern | `nav` | 2.9 KB | 1.2 KB | 2.6 KB | **6.8 KB** | 33.0 KB | −26.2 KB |
45
- | pattern | `overlay` | 2.9 KB | 1.2 KB | 3.6 KB | **7.7 KB** | 38.5 KB | −30.8 KB |
46
- | pattern | `pagination` | 2.9 KB | 0.8 KB | 2.6 KB | **6.3 KB** | 32.4 KB | −26.1 KB |
45
+ | pattern | `overlay` | 2.9 KB | 1.2 KB | 3.8 KB | **7.9 KB** | 39.3 KB | −31.3 KB |
46
+ | pattern | `pagination` | 2.9 KB | 0.8 KB | 2.8 KB | **6.5 KB** | 32.8 KB | −26.3 KB |
47
47
  | pattern | `reveal` | 2.9 KB | 0.3 KB | 1.2 KB | **4.4 KB** | 26.5 KB | −22.0 KB |
48
48
  | pattern | `states` | 2.9 KB | 0.9 KB | — | **3.8 KB** | 26.3 KB | −22.5 KB |
49
49
  | pattern | `tabs` | 2.9 KB | 0.7 KB | 2.0 KB | **5.6 KB** | 29.1 KB | −23.5 KB |
50
- | pattern | `tooltip` | 2.9 KB | 0.5 KB | 1.9 KB | **5.3 KB** | 28.5 KB | −23.2 KB |
51
- | pattern | `tree` | 2.9 KB | 0.6 KB | 2.9 KB | **6.5 KB** | 30.1 KB | −23.6 KB |
50
+ | pattern | `tooltip` | 2.9 KB | 0.5 KB | 2.0 KB | **5.4 KB** | 28.7 KB | −23.3 KB |
51
+ | pattern | `tree` | 2.9 KB | 0.6 KB | 3.1 KB | **6.6 KB** | 30.3 KB | −23.7 KB |
52
52
 
53
53
  ## 三、全库
54
54
 
55
- - 全部组件都用上(min,含 tokens 一份):**70.6 KB**
56
- - 源码版(带注释)全库 gzip:380.1 KB
55
+ - 全部组件都用上(min,含 tokens 一份):**72.6 KB**
56
+ - 源码版(带注释)全库 gzip:386.4 KB
57
57
 
58
58
  > ⚠️ 源码版那个数字**不是**要付的钱:它包含我们的注释(全库 CSS 有 69% 是注释,字节口径)。
59
59
  > 它的用途只有一个 —— 让人看清"dist 到底省了多少"。
@@ -5,7 +5,7 @@
5
5
 
6
6
  | 项目 | 值 |
7
7
  |---|---|
8
- | 声明适用版本 | agentcss `0.25.6` |
8
+ | 声明适用版本 | agentcss `0.26.0` |
9
9
  | 声明日期 | 2026-11-04 |
10
10
  | 复核节奏 | 每次发版前重跑(`npm run gate` 内含全部证据) |
11
11
  | 范围 | 本库交付的 CSS / JS、全部 `demo.html`(组件页 + 图表页 + 组合页)、以及文档站生成的页面 |
@@ -39,7 +39,7 @@
39
39
  | 1.4.11 | 非文本对比度 | ✅ | 控件边框 / 焦点环 / 图表色阶单独实算 |
40
40
  | 1.4.12 | 文本间距 | ◐ | 组件不写死行高与段距(都用令牌),但**未**按"行高 1.5 倍 / 段距 2 倍"的极端注入逐组件验证 |
41
41
  | 1.4.13 | 内容悬停或聚焦 | ◐ | tooltip 可 Esc 关闭、可悬停保持;**未**验证"可选中提示内文字"这一分支 |
42
- | 2.1.1 | 键盘 | ✅ | `keyboard-nav.js`:Tab 顺序、Enter/Space、Esc 关闭 |
42
+ | 2.1.1 | 键盘 | ✅ | `keyboard-nav.js`:Tab 顺序、Enter/Space、Esc 关闭;**滚动容器**(`.table` / `<pre>` / 图框)在 320px 下可 Tab 进入 —— `table-check` ⑮ + `a11y-scan` 的 320px `scrollable-region-focusable` 补扫 |
43
43
  | 2.1.2 | 无键盘陷阱 | ✅ | `keyboard-nav.js`:浮层关闭后焦点可继续移动,不困在层内 |
44
44
  | 2.1.4 | 字符快捷键 | — | 库不注册单字符快捷键 |
45
45
  | 2.2.1 | 计时可调 | ◐ | toast 自动消失时长可配但有上限;**未**提供"暂停计时"控件 |
package/docs/L10N.md ADDED
@@ -0,0 +1,92 @@
1
+ # 本地化(L10N)文案覆盖
2
+
3
+ > **一句话**:库默认输出中文;把 `labels` 传进去就能换掉**用户看得见、读屏会念到**的文案。
4
+ > 不传时输出与 0.25.x **逐字相同** —— 升级不会静默改变界面文字。
5
+
6
+ ```html
7
+ <script src="03-patterns/pagination/pagination.js"></script>
8
+ <script>
9
+ Pagination.create(document.querySelector('[data-pagination]'), {
10
+ labels: { prev: 'Previous', next: 'Next',
11
+ page: function (p, cur) { return 'Page ' + p + (cur ? ' (current)' : ''); } }
12
+ });
13
+ </script>
14
+ ```
15
+
16
+ 值可以是字符串,也可以是函数(动态量用函数,例如页码、百分比)。
17
+
18
+ ---
19
+
20
+ ## 一、哪些文案**在**覆盖范围内
21
+
22
+ | 组件 | 入口 | 键 |
23
+ |---|---|---|
24
+ | `overlay` | `Overlay.toast({ labels })` | `closeToast` |
25
+ | `drawer` | `Drawer.open({ labels })` | `dialog`(无标题时的名字)、`close` |
26
+ | `pagination` | `Pagination.create(node, { labels })` | `nav`、`prev`、`next`、`page(p, isCurrent)`、`status(page, pages)`、`live(page, pages)` |
27
+ | `upload` | `new Upload(root, { labels })` | `pending`、`done`、`error`、`remove(name)`、`uploading(pct)`、`countMax(n)`、`sizeMax(limit)`、`type`、`folder`、`none(reason)`、`noDrop`、`noDropShort`、`summary(added,total,rejected)`、`removed(name,rest)` |
28
+ | `select` | `Select.create(root, { labels })` | `option`、`placeholder` |
29
+ | `combobox` | `Combobox.create(root, { labels })` | `suggest`、`input`、`noMatch(query)`、`empty` |
30
+ | `date-range` | `DateRange.create(root, { labels })` | `requiredEnd`、`requiredStart`、`order(from,to)`、`min(min)`、`max(max)` |
31
+ | `dropdown` | `Dropdown.create(root, { labels })` | `menu` |
32
+ | `tree` | `Tree.create(root, { labels })` | `tree` |
33
+ | `nav` | `Nav.attach(root, { labels })` | `open`、`close` |
34
+ | `tooltip` | `Tooltip.setLabels({ region })` | `region` |
35
+ | `model-viewer` | `ModelViewer.setLabels({ … })` | `load`、`placeholder`、`retry`、`preparing`、`preparingEngine`、`hintBefore`、`hintBetween`、`hintStrong`、`hintTail`、`downloading(pct)`、`noWebGL` |
36
+ | `bar` | `Bar.draw({ text })` ⚠️ | `series(i)`、`clipped(n, isStack, max)` |
37
+
38
+ `label` / `ariaLabel` 这类**单值**参数仍然有效,且优先于 `labels` ——
39
+ 它们是既有 API,不为统一而破坏兼容。
40
+
41
+ ### ⚠️ `bar` 为什么叫 `text` 而不是 `labels`
42
+
43
+ `bar.draw` 的 `labels` **早就是「X 轴标签」这个数据参数**(`labels: string[]`)。
44
+ 把同一个名字改成文案对象是破坏性变更,所以这里的文案覆盖用 `text`。
45
+ 全库只此一处例外,`types/index.d.ts` 里 `BarText` 有同样的注释。
46
+
47
+ ### 没有逐实例入口的组件
48
+
49
+ `tooltip` 与 `model-viewer` 由属性自动初始化(`data-tooltip` / `data-mv`),
50
+ 没有"传 opts 的地方",所以用**模块级**的 `setLabels()`。
51
+ 设置一次影响该页面上后续创建的所有实例;已经创建的不受影响。
52
+
53
+ ---
54
+
55
+ ## 二、哪些**不在**覆盖范围内(不假装已做完)
56
+
57
+ 1. **开发期错误信息**:`throw new Error('upload: 缺少 .upload__input …')`。
58
+ 它们面向调用方(写代码的人),不经过 UI,也不该由终端用户看到。
59
+ 要统一英文请改源码 —— 这不属于 L10N。
60
+ 2. **`model-viewer` 的失败说明与底部说明句**:
61
+ `fail()` 的几条错误文案、`mv__cap` 里的「引擎就绪耗时 … ms」。
62
+ 它们含 `<b>` 结构与多个动态量,要安全本地化得先改成节点拼装,
63
+ 属独立改造,**当前仍是中文**。
64
+ 3. **`echarts-adapter` 的控制台提示**:`[frontend-lib] 系列数 …`,
65
+ 属开发者提示,同上。
66
+
67
+ 这份清单由 `05-audit/i18n-labels-gate.js` 守着:库代码里再出现
68
+ 「中文字面量直接进 `aria-label` / `textContent` / `el()` 文本位」就红,
69
+ 要新增必须先回答"用户会看到吗"。
70
+
71
+ ---
72
+
73
+ ## 三、为什么默认不改英文
74
+
75
+ - **不制造惊喜**:升级补丁版本就换掉界面语言,是比"没本地化"更糟的破坏。
76
+ - **不猜语言环境**:`navigator.language` 在 SSR、WebView、隐私模式下都不可靠,
77
+ 自动切换会让同一份代码在不同机器上显示不同语言,问题极难复现。
78
+ - **真要做多语言**,正确做法是调用方在启动时按自己的语言包调 `setLabels` /
79
+ 传 `labels` —— 词汇表由产品决定,不由组件库猜。
80
+
81
+ ---
82
+
83
+ ## 四、门禁
84
+
85
+ | 门禁 | 判什么 |
86
+ |---|---|
87
+ | `i18n-labels` | 静态:库代码 0 处硬编码用户文案(注释与 `throw` 不在视野) |
88
+ | `i18n-labels`(运行时) | 真浏览器里传 `labels` ⇒ DOM 真的变了;不传 ⇒ 仍是各组件的中文默认值 |
89
+ | `i18n-labels-rev` | 判据自检:三种写法都要抓到;变量/注释/`throw` 不误报;元反向 |
90
+
91
+ 运行时那半条**必须先看默认值**:只断言"覆盖后等于测试串"是不够的 ——
92
+ 如果把测试串直接写进源码,那条断言照样绿。
@@ -264,7 +264,13 @@ npm 与 Release 都是 absent ⇒ 删 tag、修夹具、在同一提交树上重
264
264
 
265
265
  ### 7.3 下一次真实发布要验的六条(提前固定,不许事后放宽)
266
266
 
267
- 回执的重试逻辑还没被真实发布走过。下一次打 tag 时,按这张表逐条判定:
267
+ `0.25.6` 的真实发布走通了**第 2 条**:`npm publish` 成功后 registry 索引延迟,
268
+ 回执对 `absent` 连续重试 13 次(每次约 10 秒)后拿到
269
+ `npm=present provenance=ok release=present`,退出码 0;既没误入
270
+ `unreadable` 分支,也没把重试次数用尽。这是这条修复第一次被真实发布走过。
271
+
272
+ 其余五条**仍只有 `release-run.sh --selftest` 的合成用例**,没有真实样本 ——
273
+ "没被触发过"不等于"验过了"。后续打 tag 继续按这张表逐条判定:
268
274
 
269
275
  | # | 场景 | 通过条件 |
270
276
  |---|---|---|
@@ -110,12 +110,17 @@ gh api 'repos/{owner}/{repo}/deployments?environment=github-pages&per_page=1' \
110
110
  |---|---|---|---|
111
111
  | L0 声明 | 「我声明它来自 X」 | 文档、CHANGELOG、tag 消息 | 声明是否为真 |
112
112
  | L1 抽样 | 「我抽查了 N 个文件,都与 X 一致」 | 有人做过小样本抽查 | 未抽查的文件是否一致 |
113
- | L2 全量 | 「每一个文件都与 X 的对应文件一致」 | **不存在** | 构建过程是否被污染 |
113
+ | L2 全量 | 「每一个文件都与 X 的对应文件一致」 | `0.25.6` 起:npm 包的 335 个文件与提交树逐字节比对,0 处不一致;**站点全量仍未做** | 构建过程是否被污染 |
114
114
  | L3 密码学 | 「这个 tarball 由这条 workflow、这个提交构建」 | npm provenance(SLSA provenance v1) | 仓库之外的东西 |
115
115
 
116
116
  三条必须说清的话:
117
117
 
118
- 1. **没有 L2。** 既没有逐个文件比对过 tarball 与提交,也没有比对过站点全量。因此「包内每个文件都来自该提交」这句话目前**说不出口**。
118
+ 1. **L2 只覆盖 npm 包,而且锚定在版本快照上。** `0.25.6` 发布后把真 tarball
119
+ 的 335 个文件逐个与 `0668838…` 提交树比对,0 处不一致 ⇒ 对**那一版**
120
+ 可以说「包内每个文件都来自该提交」。两个边界必须一起说清:
121
+ ① 站点全量从来没有比过;② 主分支后续的文档修正属于滚动更新,
122
+ 不改变已发布快照,也不让这句结论自动延伸到以后的版本。
123
+ 每次发布都要重新做一次全量比对,不能拿上一次的结果顶。
119
124
  2. **站点不是 npm 包的镜像。** 两个渠道发布的文件集本来就不同(包里有 `dist/`、没有 `guide/`;站点有 `guide/` 与演示页、没有构建清单)。
120
125
  3. **同一版本号不保证同一内容。** 历史上出现过一次,见下一节。
121
126
 
package/index.html CHANGED
@@ -97,7 +97,7 @@ li a:active { background: var(--surface-sunken); }
97
97
  </p>
98
98
  </main>
99
99
  <footer class="wrap">
100
- <p class="note">0.25.6 · 零第三方运行时依赖</p>
100
+ <p class="note">0.26.0 · 零第三方运行时依赖</p>
101
101
  </footer>
102
102
  </body>
103
103
  </html>
package/llms-full.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # agentcss — full reference (one file)
2
2
 
3
- > Generated from `ai/components.json` + `ai/pitfalls*.json` + `ai/behaviors.json` at version **0.25.6**.
3
+ > Generated from `ai/components.json` + `ai/pitfalls*.json` + `ai/behaviors.json` at version **0.26.0**.
4
4
  > Do not edit by hand: run `python 05-audit/gen-llms.py` (freshness is gated).
5
5
  > Short version: `llms.txt`. Machine contract: `ai/*.json`.
6
6
 
@@ -32,7 +32,7 @@ Every subcommand accepts `--json`; failures print `{"ok":false,...}` and exit no
32
32
  | `scientific-plot` | `splot` | asset | stable | 3.9 KB | `scientific-plot.js` | 二维科学绘图:折线/区间带/对数轴,纯令牌驱动、零依赖 | `chart-multiline-label` |
33
33
  | `sparkline` | `sparkline` | asset | stable | 7.2 KB | `sparkline.js` | 迷你趋势图:无坐标轴、纯形状,适合表格内嵌的一行走势 | `chart-multiline-label` |
34
34
  | `accordion` | `accordion` | pattern | stable | 18.0 KB | `accordion.js` | 可折叠分组 | — |
35
- | `content` | `prose` | pattern | stable | 11.1 KB | — | 长文排版容器(标题/段落/列表/引用/代码) | `single-scroll-container` `line-height-constant-sync` |
35
+ | `content` | `prose` | pattern | stable | 11.9 KB | — | 长文排版容器(标题/段落/列表/引用/代码) | `single-scroll-container` `line-height-constant-sync` |
36
36
  | `drawer` | `drawer` | pattern | stable | 5.9 KB | `drawer.js` | 侧边抽屉,含遮罩 | `fixed-element-inventory` |
37
37
  | `dropdown` | `dd` | pattern | stable | 3.9 KB | `dropdown.js` | 下拉菜单 | `popover-measure-after-render` |
38
38
  | `form-validation` | `form` | pattern | stable | 11.8 KB | — | 表单校验反馈与错误汇总 | — |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentcss",
3
- "version": "0.25.6",
3
+ "version": "0.26.0",
4
4
  "description": "移动 Web 组件库:CSS + 可选行为脚本,零第三方运行时依赖。样式用 bundler 引入,交互行为用 script 标签引入。",
5
5
  "keywords": [
6
6
  "css",
@@ -20,6 +20,7 @@
20
20
  "exports": {
21
21
  ".": {
22
22
  "types": "./types/index.d.ts",
23
+ "import": "./esm/index.mjs",
23
24
  "default": "./esm/index.mjs"
24
25
  },
25
26
  "./tokens.css": "./dist/01-tokens/tokens.css",
@@ -116,7 +117,7 @@
116
117
  "pixelmatch": "^5.3.0",
117
118
  "playwright": "^1.49.1",
118
119
  "pngjs": "^7.0.0",
119
- "puppeteer-core": "^23.11.1",
120
+ "puppeteer-core": "^25.16.0",
120
121
  "typescript": "^5.9.3",
121
122
  "yaml": "^2.9.1"
122
123
  },