@jboltai/tokui 0.1.2 → 0.1.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jboltai/tokui",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "TokUI — Zero-dependency streaming UI description & rendering framework for AI chat. Describe UI with a tiny DSL, stream over SSE, render to real DOM incrementally.",
5
5
  "keywords": [
6
6
  "tokui",
@@ -89,7 +89,7 @@
89
89
  "typecheck": "tsc",
90
90
  "coverage": "c8 --include='src/**/*.js' --exclude='src/server/**' npm run test:all",
91
91
  "server": "node demo/server/sse-server.js",
92
- "demo:sync": "npm run build && cp dist/tokui.umd.js dist/tokui.css demo/lib/",
92
+ "demo:sync": "npm run build && cp dist/tokui.umd.js dist/tokui.css demo/lib/ && perl -i -ne 'print unless m{^//# sourceMappingURL=}' demo/lib/tokui.umd.js && cp src/server/tokui-builder.js demo/server/tokui-builder.js",
93
93
  "dev": "vite",
94
94
  "build": "vite build --mode lib",
95
95
  "build:lib": "vite build --mode lib",
package/src/index.d.ts CHANGED
@@ -25,6 +25,13 @@ export interface TokUIOptions {
25
25
  container?: string | HTMLElement | null;
26
26
  /** 主题名称,如 'default' / 'dark',默认 'default' */
27
27
  theme?: string;
28
+ /**
29
+ * 界面语言(组件骨架级文案:aria-label / placeholder / 空态 / 默认按钮字等)。
30
+ * 接受 'zh-CN' / 'en-US' / 'en' / 'zh' 等,自动规整;缺省按
31
+ * documentElement.lang → navigator.language → 'zh-CN' 自动探测。
32
+ * 注:业务 DSL 文案(tt:/l:/tx:/opt: 等)不归此管,需后端按 locale 发不同 DSL。
33
+ */
34
+ locale?: string;
28
35
  /** 是否启用流式渲染模式,默认 true */
29
36
  streaming?: boolean;
30
37
  /** 事件回调,如接收到 ('streamEnd', {}) */
@@ -58,6 +65,12 @@ export class TokUI {
58
65
  /** 一次性渲染完整 DSL 文本到容器 */
59
66
  render(tokuiString: string, targetContainer?: HTMLElement): void;
60
67
 
68
+ /**
69
+ * 用当前 locale / theme 就地重画最近一次渲染的内容(清容器 + 重新 render 缓存的 DSL)。
70
+ * 典型用途:setLocale() 后刷新已渲染 DOM 的 chrome 文案。无缓存内容或无容器返回 false。
71
+ */
72
+ rerender(targetContainer?: HTMLElement): boolean;
73
+
61
74
  /** 开始流式渲染(初始化流式解析器) */
62
75
  startStream(targetContainer?: HTMLElement): void;
63
76
 
@@ -90,6 +103,23 @@ export declare function setTheme(themeName: string): void;
90
103
  /** 获取当前主题名称 */
91
104
  export declare function getTheme(): string;
92
105
 
106
+ /**
107
+ * 设置当前界面语言(组件骨架级文案)。已渲染的 DOM 不会自动更新,
108
+ * 需重新渲染或应用层自行刷新。接受 'zh-CN' / 'en-US' / 'en' / 'zh' 等,自动规整。
109
+ * @returns 规整后实际生效的 locale(如传 'en' 返回 'en-US')
110
+ */
111
+ export declare function setLocale(locale: string): string;
112
+
113
+ /** 获取当前界面语言(规整后的 locale,如 'zh-CN' / 'en-US') */
114
+ export declare function getLocale(): string;
115
+
116
+ /**
117
+ * 注册/合并新语种字典(内置仅 zh-CN + en-US,其余语种由此注入)。
118
+ * @param locale - 语种 key,如 'ja-JP'
119
+ * @param dict - key→译文 映射,可仅传部分 key(增量合并)
120
+ */
121
+ export declare function registerLocale(locale: string, dict: Record<string, string>): void;
122
+
93
123
  /**
94
124
  * DOM 创建快捷方法
95
125
  * @param tag - 标签名
@@ -109,6 +139,9 @@ export interface TokUINamespace {
109
139
  removeHandler: typeof removeHandler;
110
140
  setTheme: typeof setTheme;
111
141
  getTheme: typeof getTheme;
142
+ setLocale: typeof setLocale;
143
+ getLocale: typeof getLocale;
144
+ registerLocale: typeof registerLocale;
112
145
  el: typeof el;
113
146
  }
114
147
 
@@ -36,8 +36,9 @@ class TokUIBuilder {
36
36
  let val = String(v);
37
37
  // 转义值中的双引号
38
38
  val = val.replace(/"/g, '\\"');
39
- // 值含空格、引号、换行符或 ] 时用双引号包裹
40
- if (val.includes(' ') || val.includes('"') || val.includes('\n') || val.includes(']')) {
39
+ // opt 简写值含 : ; 分隔符,必须强制双引号(parser 引号感知整串作字面值);
40
+ // 其余含空格/引号/换行/] 的值同样需引号
41
+ if (k === 'opt' || val.includes(' ') || val.includes('"') || val.includes('\n') || val.includes(']')) {
41
42
  return `${k}:"${val}"`;
42
43
  }
43
44
  return `${k}:${val}`;
@@ -228,13 +229,26 @@ class TokUIBuilder {
228
229
  /** 自定义选择器 */
229
230
  picker(attrs) { return this._open('picker', attrs); }
230
231
  /** 下拉选择框 */
231
- select(attrs) { return this._open('select', attrs); }
232
+ select(attrs) {
233
+ return attrs && attrs.opt
234
+ ? this._selfClosing('select', null, attrs)
235
+ : this._open('select', attrs);
236
+ }
232
237
  /** 选项 */
233
238
  opt(attrs) { return this._selfClosing('opt', null, attrs); }
234
239
  /** 单选按钮组 */
235
- radio(attrs) { return this._open('radio', attrs); }
240
+ radio(attrs) {
241
+ return attrs && attrs.opt
242
+ ? this._selfClosing('radio', null, attrs)
243
+ : this._open('radio', attrs);
244
+ }
236
245
  /** 复选框 */
237
- checkbox(attrs) { return this._selfClosing('checkbox', null, attrs); }
246
+ checkbox(attrs) {
247
+ // 简写 opt:"..." → 自闭合;多选容器 multi → _open;单布尔 → 自闭合
248
+ if (attrs && attrs.opt) return this._selfClosing('checkbox', null, attrs);
249
+ if (attrs && attrs.multi !== undefined) return this._open('checkbox', attrs);
250
+ return this._selfClosing('checkbox', null, attrs);
251
+ }
238
252
  /** 开关组件(方法名 switcher 避开 JS 关键字) */
239
253
  switcher(attrs) { return this._selfClosing('switch', null, attrs); }
240
254
  /** 多行文本框 */
@@ -355,6 +369,10 @@ class TokUIBuilder {
355
369
 
356
370
  /** Empty 空状态(自闭合) */
357
371
  empty(attrs) { return this._selfClosing('empty', null, attrs); }
372
+ /** Code128 条形码:tx 数据 / l 标签 / s 尺寸(sm/md/lg) */
373
+ barcode(attrs) { return this._selfClosing('barcode', null, attrs); }
374
+ /** QR 二维码:tx 数据 / l 标签 / s 尺寸 / ec 纠错级(L/M/Q/H) */
375
+ qrcode(attrs) { return this._selfClosing('qrcode', null, attrs); }
358
376
  /** Result 结果页(自闭合) */
359
377
  result(attrs) { return this._selfClosing('result', null, attrs); }
360
378
  /** Stat 统计数值(自闭合) */
@@ -407,8 +425,21 @@ class TokUIBuilder {
407
425
 
408
426
  // ========== 动态更新 ==========
409
427
 
410
- /** Upd 异步更新指令(自闭合),推送状态更新到已有组件 */
411
- upd(attrs) { return this._selfClosing('upd', null, attrs); }
428
+ /** Upd 异步更新指令(自闭合),推送状态更新到已有组件
429
+ * 注意:serializeAttrs 默认跳过 false 值(初始渲染 [input dis:false] 会被 parser
430
+ * 读成字符串 'false' 误判为 truthy → 反而禁用,故 false 必须省略)。
431
+ * 但 upd 的 dis:false / ro:false / chk:false 是「主动关闭」语义,渲染端 _update
432
+ * 专门判 === 'false'。故此处把 false 预规范成 'false' 字符串再序列化,让 toggle-off 生效。*/
433
+ upd(attrs) {
434
+ if (attrs && typeof attrs === 'object') {
435
+ const norm = {};
436
+ for (const [k, v] of Object.entries(attrs)) {
437
+ norm[k] = v === false ? 'false' : v;
438
+ }
439
+ return this._selfClosing('upd', null, norm);
440
+ }
441
+ return this._selfClosing('upd', null, attrs);
442
+ }
412
443
 
413
444
  // ========== 交互组件 ==========
414
445