@yh-ui/hooks 0.1.10 → 0.1.12

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/dist/index.d.cts CHANGED
@@ -73,17 +73,14 @@ type UseZIndexReturn = ReturnType<typeof useZIndex>;
73
73
  declare const getDayjsLocale: (localeCode: string) => string;
74
74
  /**
75
75
  * 动态加载并设置 dayjs locale
76
- * 使用动态导入来按需加载,避免打包所有语言
77
76
  */
78
77
  declare const setDayjsLocale: (localeCode: string) => Promise<void>;
79
78
  /**
80
- * 同步设置 dayjs locale(不推荐,会阻塞)
81
- * 用于需要立即同步的场景
79
+ * 同步设置 dayjs locale(立即生效,异步加载后会更新)
82
80
  */
83
81
  declare const setDayjsLocaleSync: (localeCode: string) => void;
84
82
  /**
85
83
  * 使用自定义月份名称更新 dayjs locale
86
- * 这样可以确保 dayjs 使用我们语言包中定义的月份名称
87
84
  */
88
85
  declare const updateDayjsMonths: (localeCode: string, months: {
89
86
  jan: string;
@@ -149,7 +146,7 @@ interface FormContext {
149
146
  layout?: string;
150
147
  addField: (field: FormItemContext) => void;
151
148
  removeField: (field: FormItemContext) => void;
152
- themeOverrides?: Record<string, unknown>;
149
+ themeOverrides?: Record<string, string | undefined>;
153
150
  }
154
151
  interface FormItemContext {
155
152
  prop: string;
@@ -255,5 +252,334 @@ declare const useConfig: () => {
255
252
  globalLocale: ComputedRef<Language | undefined>;
256
253
  };
257
254
 
258
- export { FormContextKey, FormItemContextKey, configProviderContextKey, createZIndexCounter, defaultNamespace, getDayjsLocale, getNextZIndex, idInjectionKey, namespaceContextKey, resetZIndex, setDayjsLocale, setDayjsLocaleSync, updateDayjsMonths, useCache, useClickOutside, useConfig, useEventListener, useFormItem, useGlobalNamespace, useId, useIdInjection, useLocale, useNamespace, useScrollLock, useVirtualScroll, useZIndex, zIndexContextKey, zIndexCounterKey };
259
- export type { ConfigProviderContext, FormContext, FormItemContext, UseCacheReturn, UseFormItemReturn, UseIdReturn, UseLocaleReturn, UseNamespaceReturn, UseZIndexReturn, VirtualScrollOptions, VirtualScrollReturn };
255
+ type StreamChunkParser = (raw: string) => string | null;
256
+ /**
257
+ * OpenAI / DeepSeek 格式解析器
258
+ * data: {"choices":[{"delta":{"content":"hello"}}]}
259
+ */
260
+ declare const openaiParser: StreamChunkParser;
261
+ /**
262
+ * 文心一言 / ERNIE 格式解析器
263
+ * data: {"result":"hello","is_end":false}
264
+ */
265
+ declare const ernieParser: StreamChunkParser;
266
+ /**
267
+ * 通义千问 / Qwen 格式解析器
268
+ * data: {"output":{"text":"hello"},"finish_reason":null}
269
+ */
270
+ declare const qwenParser: StreamChunkParser;
271
+ /**
272
+ * 纯文本流解析器(AsyncGenerator 输出的原始字符串)
273
+ */
274
+ declare const plainTextParser: StreamChunkParser;
275
+ interface AiStreamOptions {
276
+ /**
277
+ * 请求适配器,返回 AsyncGenerator 或 fetch Response
278
+ */
279
+ request: (query: string, ...args: unknown[]) => Promise<Response | AsyncGenerator<string, void, unknown>> | AsyncGenerator<string, void, unknown>;
280
+ /**
281
+ * 流式块解析器,用于适配不同厂商的格式
282
+ * @default plainTextParser(直接输出原始字符串)
283
+ */
284
+ parser?: StreamChunkParser;
285
+ /**
286
+ * 是否启用打字机平滑节流效果
287
+ * @default true
288
+ */
289
+ typewriter?: boolean;
290
+ /**
291
+ * 每帧渲染的字符数(打字机速度控制)
292
+ * @default 3
293
+ */
294
+ charsPerFrame?: number;
295
+ onUpdate?: (chunk: string, fullContent: string) => void;
296
+ onFinish?: (content: string) => void;
297
+ onError?: (err: Error) => void;
298
+ }
299
+ /**
300
+ * useAiStream - 多厂商兼容流式请求引擎
301
+ *
302
+ * 特性:
303
+ * - 支持 OpenAI / DeepSeek / 文心一言 / 通义千问 等主流格式(Adapter 模式)
304
+ * - 内置 rAF 打字机节流,保证平滑输出体验
305
+ * - 完整的 AbortController 取消支持
306
+ */
307
+ declare function useAiStream(options: AiStreamOptions): {
308
+ isStreaming: vue.Ref<boolean, boolean>;
309
+ currentContent: vue.Ref<string, string>;
310
+ fetchStream: (query: string, ...args: unknown[]) => Promise<void>;
311
+ stop: () => void;
312
+ parsers: {
313
+ openaiParser: StreamChunkParser;
314
+ ernieParser: StreamChunkParser;
315
+ qwenParser: StreamChunkParser;
316
+ plainTextParser: StreamChunkParser;
317
+ };
318
+ };
319
+
320
+ interface AiChatMessage {
321
+ /** 唯一标识,避免使用 index 做 key */
322
+ id: string;
323
+ /** 消息发送方 */
324
+ role: 'user' | 'assistant' | 'system';
325
+ /** 消息内容 */
326
+ content: string;
327
+ /**
328
+ * 消息状态
329
+ * - loading: 初始加载中(占位)
330
+ * - generating: 流式生成中
331
+ * - success: 已成功完成
332
+ * - error: 发生错误
333
+ * - stopped: 被用户中途打断
334
+ */
335
+ status?: 'loading' | 'generating' | 'success' | 'error' | 'stopped';
336
+ /** 消息时间戳(ms) */
337
+ createAt: number;
338
+ /** 用于展示的时间字符串(可选,不传则自动格式化) */
339
+ time?: string;
340
+ /** 扩展字段 */
341
+ [key: string]: unknown;
342
+ }
343
+ interface UseAiChatOptions {
344
+ /** 初始化的消息列表 */
345
+ initialMessages?: AiChatMessage[];
346
+ /** 自定义生成 ID 的函数 */
347
+ idGenerator?: () => string;
348
+ /**
349
+ * 请求适配器
350
+ * 支持:
351
+ * - AsyncGenerator<string>:最原始的字符流,每次 yield 一段字符
352
+ * - Promise<string>:直接返回完整回复
353
+ * - Promise<Response>:SSE 流式响应
354
+ */
355
+ request?: (message: string, history: AiChatMessage[], abortSignal: AbortSignal) => AsyncGenerator<string, void, unknown> | Promise<string | Response>;
356
+ /**
357
+ * SSE / 流式块的解析器(适配不同厂商格式)
358
+ * 传入各厂商对应的 parser(来自 useAiStream 模块)
359
+ * @default plainTextParser
360
+ */
361
+ parser?: StreamChunkParser;
362
+ /**
363
+ * 是否启用打字机平滑输出效果
364
+ * @default true
365
+ */
366
+ typewriter?: boolean;
367
+ /**
368
+ * 打字机每帧输出字符数(越大越快)
369
+ * @default 3
370
+ */
371
+ charsPerFrame?: number;
372
+ /**
373
+ * 系统 Prompt(会自动插入到历史的首位)
374
+ */
375
+ systemPrompt?: string;
376
+ /** 出现错误时的回调 */
377
+ onError?: (err: Error) => void;
378
+ /** 消息发送完成回调 */
379
+ onFinish?: (message: AiChatMessage) => void;
380
+ }
381
+ /**
382
+ * useAiChat - 核心 AI 会话管理 Hook
383
+ *
384
+ * 特性:
385
+ * - 消息列表 CRUD + 状态机管理
386
+ * - 支持流式 / 非流式响应
387
+ * - 内置多厂商适配器接口(通过 parser 选项传入)
388
+ * - rAF 打字机平滑效果(可关闭)
389
+ * - 完整的 AbortController 取消支持
390
+ * - 系统 Prompt 自动注入
391
+ */
392
+ declare function useAiChat(options?: UseAiChatOptions): {
393
+ /** 会话历史 */
394
+ messages: vue.Ref<{
395
+ [x: string]: unknown;
396
+ id: string;
397
+ role: "user" | "assistant" | "system";
398
+ content: string;
399
+ status?: "loading" | "generating" | "success" | "error" | "stopped"
400
+ /** 消息时间戳(ms) */
401
+ | undefined;
402
+ createAt: number;
403
+ time?: string
404
+ /** 扩展字段 */
405
+ | undefined;
406
+ }[], AiChatMessage[] | {
407
+ [x: string]: unknown;
408
+ id: string;
409
+ role: "user" | "assistant" | "system";
410
+ content: string;
411
+ status?: "loading" | "generating" | "success" | "error" | "stopped"
412
+ /** 消息时间戳(ms) */
413
+ | undefined;
414
+ createAt: number;
415
+ time?: string
416
+ /** 扩展字段 */
417
+ | undefined;
418
+ }[]>;
419
+ /** 是否正在生成(等同 isSending,别名友好) */
420
+ isGenerating: vue.Ref<boolean, boolean>;
421
+ /** 同 isGenerating,语义别名 */
422
+ isSending: vue.ComputedRef<boolean>;
423
+ /** 触发发送(自动处理流、打字机) */
424
+ sendMessage: (content: string) => Promise<void>;
425
+ /** 停止/中断当前生成 */
426
+ stop: () => void;
427
+ /** 移除单条消息 */
428
+ removeMessage: (id: string) => void;
429
+ /** 修改单条消息内容 */
430
+ updateMessage: (id: string, patch: Partial<AiChatMessage>) => void;
431
+ /** 重置清空所有会话 */
432
+ clear: () => void;
433
+ };
434
+
435
+ interface AiConversation {
436
+ id: string;
437
+ title: string;
438
+ /**
439
+ * 最近更新时间(时间戳 ms)
440
+ */
441
+ updatedAt: number;
442
+ /**
443
+ * 对话预览/最后一条消息内容
444
+ */
445
+ excerpt?: string;
446
+ /**
447
+ * 是否置顶
448
+ */
449
+ pinned?: boolean;
450
+ /**
451
+ * 自定义数据(例如知识库 ID 等业务数据)
452
+ */
453
+ meta?: Record<string, unknown>;
454
+ }
455
+ interface StorageAdapter {
456
+ getItem(key: string): string | null | Promise<string | null>;
457
+ setItem(key: string, value: string): void | Promise<void>;
458
+ removeItem(key: string): void | Promise<void>;
459
+ }
460
+ /**
461
+ * localStorage 适配器(默认)
462
+ */
463
+ declare const localStorageAdapter: StorageAdapter;
464
+ /**
465
+ * IndexedDB 适配器(适合大量数据持久化)
466
+ */
467
+ declare class IndexedDBAdapter implements StorageAdapter {
468
+ private db;
469
+ private dbName;
470
+ private storeName;
471
+ private ready;
472
+ constructor(dbName?: string);
473
+ private init;
474
+ getItem(key: string): Promise<string | null>;
475
+ setItem(key: string, value: string): Promise<void>;
476
+ removeItem(key: string): Promise<void>;
477
+ }
478
+ type ConversationGroup = {
479
+ label: string;
480
+ items: AiConversation[];
481
+ };
482
+ interface UseAiConversationsOptions {
483
+ /** 初始化数据(或从后端的直出) */
484
+ initialConversations?: AiConversation[];
485
+ /** 自定义生成 ID 的函数 */
486
+ idGenerator?: () => string;
487
+ /**
488
+ * 持久化存储适配器
489
+ * - false: 不持久化(仅内存)
490
+ * - 'localStorage': 使用 localStorage(默认)
491
+ * - 'indexedDB': 使用 IndexedDB
492
+ * - StorageAdapter: 自定义适配器
493
+ */
494
+ storage?: false | 'localStorage' | 'indexedDB' | StorageAdapter;
495
+ /** 持久化 key 前缀 */
496
+ storageKey?: string;
497
+ /**
498
+ * 每次加载的数量(用于分页 / 懒加载)
499
+ * @default 20
500
+ */
501
+ pageSize?: number;
502
+ }
503
+ /**
504
+ * useAiConversations - 会话历史管理 Hook
505
+ *
506
+ * 特性:
507
+ * - 完整的 CRUD + 置顶操作
508
+ * - 可插拔持久化(localStorage / IndexedDB / 自定义)
509
+ * - 按时间自动分组(今天 / 最近 7 天 / 最近 30 天 / 更早)
510
+ * - 分页懒加载
511
+ */
512
+ declare function useAiConversations(options?: UseAiConversationsOptions): {
513
+ /** 完整会话列表 */
514
+ conversations: vue.Ref<{
515
+ id: string;
516
+ title: string;
517
+ updatedAt: number;
518
+ excerpt?: string
519
+ /**
520
+ * 是否置顶
521
+ */
522
+ | undefined;
523
+ pinned?: boolean
524
+ /**
525
+ * 自定义数据(例如知识库 ID 等业务数据)
526
+ */
527
+ | undefined;
528
+ meta?: Record<string, unknown> | undefined;
529
+ }[], AiConversation[] | {
530
+ id: string;
531
+ title: string;
532
+ updatedAt: number;
533
+ excerpt?: string
534
+ /**
535
+ * 是否置顶
536
+ */
537
+ | undefined;
538
+ pinned?: boolean
539
+ /**
540
+ * 自定义数据(例如知识库 ID 等业务数据)
541
+ */
542
+ | undefined;
543
+ meta?: Record<string, unknown> | undefined;
544
+ }[]>;
545
+ /** 按时间分组后的列表(置顶 / 今天 / 最近 7 天 / 更早) */
546
+ groupedConversations: vue.ComputedRef<ConversationGroup[]>;
547
+ /** 分页后的列表 */
548
+ pagedConversations: vue.ComputedRef<{
549
+ id: string;
550
+ title: string;
551
+ updatedAt: number;
552
+ excerpt?: string
553
+ /**
554
+ * 是否置顶
555
+ */
556
+ | undefined;
557
+ pinned?: boolean
558
+ /**
559
+ * 自定义数据(例如知识库 ID 等业务数据)
560
+ */
561
+ | undefined;
562
+ meta?: Record<string, unknown> | undefined;
563
+ }[]>;
564
+ /** 是否还有更多数据 */
565
+ hasMore: vue.ComputedRef<boolean>;
566
+ /** 加载更多 */
567
+ loadMore: () => Promise<void>;
568
+ /** 加载更多状态 */
569
+ isLoadingMore: vue.Ref<boolean, boolean>;
570
+ /** 等待初始化完成(SSR 场景使用) */
571
+ ready: Promise<void>;
572
+ /** 新建会话 */
573
+ createConversation: (title: string, meta?: Record<string, unknown>) => Promise<AiConversation>;
574
+ /** 删除会话 */
575
+ removeConversation: (id: string) => Promise<void>;
576
+ /** 更新会话属性 */
577
+ updateConversation: (id: string, updates: Partial<Omit<AiConversation, "id">>) => Promise<void>;
578
+ /** 置顶/取消置顶 */
579
+ pinConversation: (id: string, pinned?: boolean) => Promise<void>;
580
+ /** 清空全部 */
581
+ clear: () => Promise<void>;
582
+ };
583
+
584
+ export { FormContextKey, FormItemContextKey, IndexedDBAdapter, configProviderContextKey, createZIndexCounter, defaultNamespace, ernieParser, getDayjsLocale, getNextZIndex, idInjectionKey, localStorageAdapter, namespaceContextKey, openaiParser, plainTextParser, qwenParser, resetZIndex, setDayjsLocale, setDayjsLocaleSync, updateDayjsMonths, useAiChat, useAiConversations, useAiStream, useCache, useClickOutside, useConfig, useEventListener, useFormItem, useGlobalNamespace, useId, useIdInjection, useLocale, useNamespace, useScrollLock, useVirtualScroll, useZIndex, zIndexContextKey, zIndexCounterKey };
585
+ export type { AiChatMessage, AiConversation, AiStreamOptions, ConfigProviderContext, ConversationGroup, FormContext, FormItemContext, StorageAdapter, StreamChunkParser, UseAiChatOptions, UseAiConversationsOptions, UseCacheReturn, UseFormItemReturn, UseIdReturn, UseLocaleReturn, UseNamespaceReturn, UseZIndexReturn, VirtualScrollOptions, VirtualScrollReturn };