@chenzy-design/core 0.2.1 → 0.4.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 (283) hide show
  1. package/dist/ai-chat-dialogue.d.ts +300 -0
  2. package/dist/ai-chat-dialogue.d.ts.map +1 -0
  3. package/dist/ai-chat-dialogue.js +699 -0
  4. package/dist/ai-chat-dialogue.js.map +1 -0
  5. package/dist/ai-chat-dialogue.test.d.ts +2 -0
  6. package/dist/ai-chat-dialogue.test.d.ts.map +1 -0
  7. package/dist/ai-chat-dialogue.test.js +338 -0
  8. package/dist/ai-chat-dialogue.test.js.map +1 -0
  9. package/dist/ai-chat-input.d.ts +191 -0
  10. package/dist/ai-chat-input.d.ts.map +1 -0
  11. package/dist/ai-chat-input.js +274 -0
  12. package/dist/ai-chat-input.js.map +1 -0
  13. package/dist/ai-chat-input.test.d.ts +2 -0
  14. package/dist/ai-chat-input.test.d.ts.map +1 -0
  15. package/dist/ai-chat-input.test.js +339 -0
  16. package/dist/ai-chat-input.test.js.map +1 -0
  17. package/dist/audio-player.d.ts +154 -0
  18. package/dist/audio-player.d.ts.map +1 -0
  19. package/dist/audio-player.js +254 -0
  20. package/dist/audio-player.js.map +1 -0
  21. package/dist/audio-player.test.d.ts +2 -0
  22. package/dist/audio-player.test.d.ts.map +1 -0
  23. package/dist/audio-player.test.js +275 -0
  24. package/dist/audio-player.test.js.map +1 -0
  25. package/dist/back-top.d.ts +4 -1
  26. package/dist/back-top.d.ts.map +1 -1
  27. package/dist/back-top.js +5 -2
  28. package/dist/back-top.js.map +1 -1
  29. package/dist/back-top.test.js +3 -2
  30. package/dist/back-top.test.js.map +1 -1
  31. package/dist/calendar.d.ts +132 -44
  32. package/dist/calendar.d.ts.map +1 -1
  33. package/dist/calendar.js +413 -70
  34. package/dist/calendar.js.map +1 -1
  35. package/dist/calendar.test.js +160 -76
  36. package/dist/calendar.test.js.map +1 -1
  37. package/dist/chat.d.ts +172 -0
  38. package/dist/chat.d.ts.map +1 -0
  39. package/dist/chat.js +210 -0
  40. package/dist/chat.js.map +1 -0
  41. package/dist/chat.test.d.ts +2 -0
  42. package/dist/chat.test.d.ts.map +1 -0
  43. package/dist/chat.test.js +181 -0
  44. package/dist/chat.test.js.map +1 -0
  45. package/dist/code-highlight.d.ts +30 -0
  46. package/dist/code-highlight.d.ts.map +1 -0
  47. package/dist/code-highlight.js +37 -0
  48. package/dist/code-highlight.js.map +1 -0
  49. package/dist/code-highlight.test.d.ts +2 -0
  50. package/dist/code-highlight.test.d.ts.map +1 -0
  51. package/dist/code-highlight.test.js +36 -0
  52. package/dist/code-highlight.test.js.map +1 -0
  53. package/dist/collapsible.d.ts +41 -0
  54. package/dist/collapsible.d.ts.map +1 -0
  55. package/dist/collapsible.js +33 -0
  56. package/dist/collapsible.js.map +1 -0
  57. package/dist/collapsible.test.d.ts +2 -0
  58. package/dist/collapsible.test.d.ts.map +1 -0
  59. package/dist/collapsible.test.js +57 -0
  60. package/dist/collapsible.test.js.map +1 -0
  61. package/dist/color-value.d.ts +60 -0
  62. package/dist/color-value.d.ts.map +1 -0
  63. package/dist/color-value.js +165 -0
  64. package/dist/color-value.js.map +1 -0
  65. package/dist/color-value.test.d.ts +2 -0
  66. package/dist/color-value.test.d.ts.map +1 -0
  67. package/dist/color-value.test.js +104 -0
  68. package/dist/color-value.test.js.map +1 -0
  69. package/dist/config-provider.d.ts +76 -37
  70. package/dist/config-provider.d.ts.map +1 -1
  71. package/dist/config-provider.js +107 -32
  72. package/dist/config-provider.js.map +1 -1
  73. package/dist/config-provider.test.js +123 -60
  74. package/dist/config-provider.test.js.map +1 -1
  75. package/dist/cropper.d.ts +164 -0
  76. package/dist/cropper.d.ts.map +1 -0
  77. package/dist/cropper.js +841 -0
  78. package/dist/cropper.js.map +1 -0
  79. package/dist/cropper.test.d.ts +2 -0
  80. package/dist/cropper.test.d.ts.map +1 -0
  81. package/dist/cropper.test.js +259 -0
  82. package/dist/cropper.test.js.map +1 -0
  83. package/dist/drag-move.d.ts +119 -0
  84. package/dist/drag-move.d.ts.map +1 -0
  85. package/dist/drag-move.js +237 -0
  86. package/dist/drag-move.js.map +1 -0
  87. package/dist/drag-move.test.d.ts +2 -0
  88. package/dist/drag-move.test.d.ts.map +1 -0
  89. package/dist/drag-move.test.js +304 -0
  90. package/dist/drag-move.test.js.map +1 -0
  91. package/dist/editable.d.ts +24 -4
  92. package/dist/editable.d.ts.map +1 -1
  93. package/dist/editable.js +18 -0
  94. package/dist/editable.js.map +1 -1
  95. package/dist/editable.test.js +55 -2
  96. package/dist/editable.test.js.map +1 -1
  97. package/dist/ellipsis.d.ts +13 -0
  98. package/dist/ellipsis.d.ts.map +1 -1
  99. package/dist/ellipsis.js +36 -0
  100. package/dist/ellipsis.js.map +1 -1
  101. package/dist/ellipsis.test.js +37 -1
  102. package/dist/ellipsis.test.js.map +1 -1
  103. package/dist/form-path.d.ts +19 -0
  104. package/dist/form-path.d.ts.map +1 -0
  105. package/dist/form-path.js +97 -0
  106. package/dist/form-path.js.map +1 -0
  107. package/dist/form-path.test.d.ts +2 -0
  108. package/dist/form-path.test.d.ts.map +1 -0
  109. package/dist/form-path.test.js +57 -0
  110. package/dist/form-path.test.js.map +1 -0
  111. package/dist/form-validate.d.ts +13 -0
  112. package/dist/form-validate.d.ts.map +1 -0
  113. package/dist/form-validate.js +204 -0
  114. package/dist/form-validate.js.map +1 -0
  115. package/dist/form.d.ts +91 -18
  116. package/dist/form.d.ts.map +1 -1
  117. package/dist/form.js +170 -115
  118. package/dist/form.js.map +1 -1
  119. package/dist/form.test.js +349 -76
  120. package/dist/form.test.js.map +1 -1
  121. package/dist/highlight.d.ts +42 -32
  122. package/dist/highlight.d.ts.map +1 -1
  123. package/dist/highlight.js +67 -41
  124. package/dist/highlight.js.map +1 -1
  125. package/dist/highlight.test.js +73 -32
  126. package/dist/highlight.test.js.map +1 -1
  127. package/dist/hotkeys.d.ts +151 -0
  128. package/dist/hotkeys.d.ts.map +1 -0
  129. package/dist/hotkeys.js +188 -0
  130. package/dist/hotkeys.js.map +1 -0
  131. package/dist/hotkeys.test.d.ts +2 -0
  132. package/dist/hotkeys.test.d.ts.map +1 -0
  133. package/dist/hotkeys.test.js +170 -0
  134. package/dist/hotkeys.test.js.map +1 -0
  135. package/dist/index.d.ts +33 -17
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/index.js +32 -13
  138. package/dist/index.js.map +1 -1
  139. package/dist/input.d.ts +34 -0
  140. package/dist/input.d.ts.map +1 -0
  141. package/dist/input.js +54 -0
  142. package/dist/input.js.map +1 -0
  143. package/dist/input.test.d.ts +2 -0
  144. package/dist/input.test.d.ts.map +1 -0
  145. package/dist/input.test.js +56 -0
  146. package/dist/input.test.js.map +1 -0
  147. package/dist/markdown-render.d.ts +49 -0
  148. package/dist/markdown-render.d.ts.map +1 -0
  149. package/dist/markdown-render.js +61 -0
  150. package/dist/markdown-render.js.map +1 -0
  151. package/dist/markdown-render.test.d.ts +2 -0
  152. package/dist/markdown-render.test.d.ts.map +1 -0
  153. package/dist/markdown-render.test.js +106 -0
  154. package/dist/markdown-render.test.js.map +1 -0
  155. package/dist/notification.d.ts +40 -31
  156. package/dist/notification.d.ts.map +1 -1
  157. package/dist/notification.js +86 -70
  158. package/dist/notification.js.map +1 -1
  159. package/dist/notification.test.js +62 -39
  160. package/dist/notification.test.js.map +1 -1
  161. package/dist/numeral.d.ts +32 -0
  162. package/dist/numeral.d.ts.map +1 -0
  163. package/dist/numeral.js +67 -0
  164. package/dist/numeral.js.map +1 -0
  165. package/dist/numeral.test.d.ts +2 -0
  166. package/dist/numeral.test.d.ts.map +1 -0
  167. package/dist/numeral.test.js +59 -0
  168. package/dist/numeral.test.js.map +1 -0
  169. package/dist/overflow-list.d.ts +9 -40
  170. package/dist/overflow-list.d.ts.map +1 -1
  171. package/dist/overflow-list.js +9 -70
  172. package/dist/overflow-list.js.map +1 -1
  173. package/dist/overflow-list.test.js +1 -122
  174. package/dist/overflow-list.test.js.map +1 -1
  175. package/dist/pagination.d.ts +17 -0
  176. package/dist/pagination.d.ts.map +1 -1
  177. package/dist/pagination.js +48 -0
  178. package/dist/pagination.js.map +1 -1
  179. package/dist/pagination.test.js +40 -1
  180. package/dist/pagination.test.js.map +1 -1
  181. package/dist/pincode.d.ts +79 -0
  182. package/dist/pincode.d.ts.map +1 -0
  183. package/dist/pincode.js +119 -0
  184. package/dist/pincode.js.map +1 -0
  185. package/dist/pincode.test.d.ts +2 -0
  186. package/dist/pincode.test.d.ts.map +1 -0
  187. package/dist/pincode.test.js +151 -0
  188. package/dist/pincode.test.js.map +1 -0
  189. package/dist/progress.d.ts +32 -30
  190. package/dist/progress.d.ts.map +1 -1
  191. package/dist/progress.js +257 -64
  192. package/dist/progress.js.map +1 -1
  193. package/dist/progress.test.js +50 -47
  194. package/dist/progress.test.js.map +1 -1
  195. package/dist/resizable.d.ts +200 -0
  196. package/dist/resizable.d.ts.map +1 -0
  197. package/dist/resizable.js +329 -0
  198. package/dist/resizable.js.map +1 -0
  199. package/dist/resizable.test.d.ts +2 -0
  200. package/dist/resizable.test.d.ts.map +1 -0
  201. package/dist/resizable.test.js +302 -0
  202. package/dist/resizable.test.js.map +1 -0
  203. package/dist/scroll-list.d.ts +69 -62
  204. package/dist/scroll-list.d.ts.map +1 -1
  205. package/dist/scroll-list.js +103 -144
  206. package/dist/scroll-list.js.map +1 -1
  207. package/dist/scroll-list.test.js +100 -110
  208. package/dist/scroll-list.test.js.map +1 -1
  209. package/dist/sidebar.d.ts +46 -0
  210. package/dist/sidebar.d.ts.map +1 -0
  211. package/dist/sidebar.js +65 -0
  212. package/dist/sidebar.js.map +1 -0
  213. package/dist/sidebar.test.d.ts +2 -0
  214. package/dist/sidebar.test.d.ts.map +1 -0
  215. package/dist/sidebar.test.js +88 -0
  216. package/dist/sidebar.test.js.map +1 -0
  217. package/dist/spin.d.ts +5 -5
  218. package/dist/spin.d.ts.map +1 -1
  219. package/dist/spin.js +13 -39
  220. package/dist/spin.js.map +1 -1
  221. package/dist/spin.test.js +2 -26
  222. package/dist/spin.test.js.map +1 -1
  223. package/dist/toast.d.ts +33 -30
  224. package/dist/toast.d.ts.map +1 -1
  225. package/dist/toast.js +77 -72
  226. package/dist/toast.js.map +1 -1
  227. package/dist/toast.test.js +63 -37
  228. package/dist/toast.test.js.map +1 -1
  229. package/dist/tree.d.ts +22 -5
  230. package/dist/tree.d.ts.map +1 -1
  231. package/dist/tree.js +61 -9
  232. package/dist/tree.js.map +1 -1
  233. package/dist/tree.test.js +72 -1
  234. package/dist/tree.test.js.map +1 -1
  235. package/dist/user-guide.d.ts +73 -0
  236. package/dist/user-guide.d.ts.map +1 -0
  237. package/dist/user-guide.js +95 -0
  238. package/dist/user-guide.js.map +1 -0
  239. package/dist/user-guide.test.d.ts +2 -0
  240. package/dist/user-guide.test.d.ts.map +1 -0
  241. package/dist/user-guide.test.js +109 -0
  242. package/dist/user-guide.test.js.map +1 -0
  243. package/dist/video-player.d.ts +196 -0
  244. package/dist/video-player.d.ts.map +1 -0
  245. package/dist/video-player.js +461 -0
  246. package/dist/video-player.js.map +1 -0
  247. package/dist/video-player.test.d.ts +2 -0
  248. package/dist/video-player.test.d.ts.map +1 -0
  249. package/dist/video-player.test.js +435 -0
  250. package/dist/video-player.test.js.map +1 -0
  251. package/package.json +17 -1
  252. package/dist/banner.d.ts +0 -19
  253. package/dist/banner.d.ts.map +0 -1
  254. package/dist/banner.js +0 -20
  255. package/dist/banner.js.map +0 -1
  256. package/dist/banner.test.d.ts +0 -2
  257. package/dist/banner.test.d.ts.map +0 -1
  258. package/dist/banner.test.js +0 -29
  259. package/dist/banner.test.js.map +0 -1
  260. package/dist/breakpoints.d.ts +0 -30
  261. package/dist/breakpoints.d.ts.map +0 -1
  262. package/dist/breakpoints.js +0 -45
  263. package/dist/breakpoints.js.map +0 -1
  264. package/dist/breakpoints.test.d.ts +0 -2
  265. package/dist/breakpoints.test.d.ts.map +0 -1
  266. package/dist/breakpoints.test.js +0 -46
  267. package/dist/breakpoints.test.js.map +0 -1
  268. package/dist/lottie-icon.d.ts +0 -88
  269. package/dist/lottie-icon.d.ts.map +0 -1
  270. package/dist/lottie-icon.js +0 -84
  271. package/dist/lottie-icon.js.map +0 -1
  272. package/dist/lottie-icon.test.d.ts +0 -2
  273. package/dist/lottie-icon.test.d.ts.map +0 -1
  274. package/dist/lottie-icon.test.js +0 -88
  275. package/dist/lottie-icon.test.js.map +0 -1
  276. package/dist/sider.d.ts +0 -26
  277. package/dist/sider.d.ts.map +0 -1
  278. package/dist/sider.js +0 -55
  279. package/dist/sider.js.map +0 -1
  280. package/dist/sider.test.d.ts +0 -2
  281. package/dist/sider.test.d.ts.map +0 -1
  282. package/dist/sider.test.js +0 -29
  283. package/dist/sider.test.js.map +0 -1
package/dist/chat.js ADDED
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Chat headless — framework-agnostic logic ported from Semi Design `ChatFoundation`
3
+ * (semi-foundation/chat). Pure helpers + a small adapter-driven controller; the
4
+ * svelte layer owns DOM (scroll container, wheel/resize listeners, upload widget).
5
+ *
6
+ * 严格对齐 Semi:
7
+ * - 常量 ROLE / CHAT_ALIGN / MESSAGE_STATUS / MODE / SEND_HOT_KEY / SHOW_SCROLL_GAP=100 / SCROLL_ANIMATION_TIME=300。
8
+ * - back-bottom 显隐阈值:scrollHeight - scrollTop - clientHeight <= SHOW_SCROLL_GAP → 隐藏。
9
+ * - enableUpload 三态判定 getUploadProps(boolean → 三态同值;对象 → 缺省各 true;其它 → 全 true)。
10
+ * - sendHotKey 判定 shouldSendOnEnter(enter:无 shift 才发;shift+enter:有 shift 才发)。
11
+ * - onMessageSend 组装 content(无附件 → 纯文本 string;有附件 → Content[] 图片/文件分流)。
12
+ * - clearContext 追加 divider(末尾已是 divider 则跳过)。
13
+ * - delete/like/dislike/reset 的 chats 变换。
14
+ *
15
+ * See specs/components/show/Chat.spec.md §3 + semi-foundation/lib/es/chat/foundation.js。
16
+ */
17
+ // ---------------------------------------------------------------------------
18
+ // 常量(对齐 Semi chat.constants)
19
+ // ---------------------------------------------------------------------------
20
+ /** 消息角色。 */
21
+ export const CHAT_ROLE = {
22
+ USER: 'user',
23
+ ASSISTANT: 'assistant',
24
+ SYSTEM: 'system',
25
+ DIVIDER: 'divider',
26
+ };
27
+ /** 布局对齐。 */
28
+ export const CHAT_ALIGN = {
29
+ LEFT_RIGHT: 'leftRight',
30
+ LEFT_ALIGN: 'leftAlign',
31
+ };
32
+ /** 气泡模式。 */
33
+ export const CHAT_MODE = {
34
+ BUBBLE: 'bubble',
35
+ NO_BUBBLE: 'noBubble',
36
+ USER_BUBBLE: 'userBubble',
37
+ };
38
+ /** 消息状态。 */
39
+ export const MESSAGE_STATUS = {
40
+ LOADING: 'loading',
41
+ INCOMPLETE: 'incomplete',
42
+ COMPLETE: 'complete',
43
+ ERROR: 'error',
44
+ };
45
+ /** 发送快捷键。 */
46
+ export const SEND_HOT_KEY = {
47
+ ENTER: 'enter',
48
+ SHIFT_PLUS_ENTER: 'shift+enter',
49
+ };
50
+ /** 图片后缀与前缀(用于 onMessageSend 附件图片/文件分流)。 */
51
+ export const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];
52
+ export const PIC_PREFIX = 'image/';
53
+ /** 返回底部按钮显隐阈值(px)。 */
54
+ export const SHOW_SCROLL_GAP = 100;
55
+ /** 滚动到底动画时长(ms)。 */
56
+ export const SCROLL_ANIMATION_TIME = 300;
57
+ // ---------------------------------------------------------------------------
58
+ // 纯函数(无副作用,直接单测)
59
+ // ---------------------------------------------------------------------------
60
+ /**
61
+ * back-bottom 按钮是否应可见。
62
+ * 对齐 Semi getScroll:距底部(scrollHeight - scrollTop - clientHeight)> SHOW_SCROLL_GAP → 显示。
63
+ */
64
+ export function shouldShowBackBottom(scrollHeight, scrollTop, clientHeight, gap = SHOW_SCROLL_GAP) {
65
+ return scrollHeight - scrollTop - clientHeight > gap;
66
+ }
67
+ /**
68
+ * enableUpload 三态归一(对齐 Semi getUploadProps)。
69
+ * - boolean → 三态同值。
70
+ * - 对象 → 缺省字段各默认 true。
71
+ * - 其它(undefined 等)→ 全 true。
72
+ */
73
+ export function resolveEnableUpload(enableUpload) {
74
+ if (enableUpload !== null &&
75
+ typeof enableUpload === 'object' &&
76
+ Object.prototype.toString.call(enableUpload) === '[object Object]') {
77
+ const { dragUpload = true, clickUpload = true, pasteUpload = true } = enableUpload;
78
+ return { dragUpload, clickUpload, pasteUpload };
79
+ }
80
+ if (typeof enableUpload === 'boolean') {
81
+ return {
82
+ dragUpload: enableUpload,
83
+ clickUpload: enableUpload,
84
+ pasteUpload: enableUpload,
85
+ };
86
+ }
87
+ return { dragUpload: true, clickUpload: true, pasteUpload: true };
88
+ }
89
+ /**
90
+ * 按 sendHotKey 判定一次 Enter 是否应触发发送(对齐 Semi onEnterPress)。
91
+ * - `'enter'`:按下 Shift 时不发送(换行)。
92
+ * - `'shift+enter'`:未按 Shift 时不发送(换行)。
93
+ */
94
+ export function shouldSendOnEnter(sendHotKey, shiftKey) {
95
+ if (sendHotKey === SEND_HOT_KEY.SHIFT_PLUS_ENTER && shiftKey === false) {
96
+ return false;
97
+ }
98
+ if (sendHotKey === SEND_HOT_KEY.ENTER && shiftKey === true) {
99
+ return false;
100
+ }
101
+ return true;
102
+ }
103
+ /** 附件是否为图片(对齐 Semi:MIME 前缀 image/ 或后缀命中图片集)。 */
104
+ export function isImageAttachment(item) {
105
+ const name = typeof item.name === 'string' ? item.name : '';
106
+ const suffix = name.split('.').pop()?.toLowerCase() ?? '';
107
+ const mime = item.fileInstance && typeof item.fileInstance.type === 'string'
108
+ ? item.fileInstance.type
109
+ : '';
110
+ return mime.startsWith(PIC_PREFIX) || PIC_SUFFIX_ARRAY.includes(suffix);
111
+ }
112
+ /**
113
+ * 组装一条发送消息的 content(对齐 Semi onMessageSend)。
114
+ * - 无附件(attachment 为空数组)→ 返回纯文本 string。
115
+ * - 有附件 → 返回 Content[]:先文本(若有),再各附件按图片/文件分流。
116
+ */
117
+ export function buildSendContent(input, attachment) {
118
+ if (Boolean(attachment) && attachment.length === 0) {
119
+ return input;
120
+ }
121
+ const content = [];
122
+ if (input) {
123
+ content.push({ type: 'text', text: input });
124
+ }
125
+ for (const item of attachment ?? []) {
126
+ const { name = '', url = '', size } = item;
127
+ if (isImageAttachment(item)) {
128
+ content.push({ type: 'image_url', image_url: { url } });
129
+ }
130
+ else {
131
+ const fileType = item.fileInstance && typeof item.fileInstance.type === 'string'
132
+ ? item.fileInstance.type
133
+ : undefined;
134
+ const file_url = { url, name };
135
+ if (size !== undefined)
136
+ file_url.size = size;
137
+ if (fileType !== undefined)
138
+ file_url.type = fileType;
139
+ content.push({ type: 'file_url', file_url });
140
+ }
141
+ }
142
+ return content;
143
+ }
144
+ /**
145
+ * clearContext:末尾追加一条 divider 消息(对齐 Semi clearContext)。
146
+ * 若末尾已是 divider,则原样返回(不重复追加)。
147
+ * id / createAt 由调用方注入(保持核心纯净、可测)。
148
+ */
149
+ export function appendDivider(chats, makeId, now = Date.now) {
150
+ const last = chats[chats.length - 1];
151
+ if (last && last.role === CHAT_ROLE.DIVIDER) {
152
+ return chats;
153
+ }
154
+ return [...chats, { role: CHAT_ROLE.DIVIDER, id: makeId(), createAt: now() }];
155
+ }
156
+ /** 构造一条 user 消息(对齐 Semi onMessageSend / onHintClick 的 newMessage)。 */
157
+ export function makeUserMessage(content, makeId, now = Date.now) {
158
+ return {
159
+ role: CHAT_ROLE.USER,
160
+ id: makeId(),
161
+ createAt: now(),
162
+ content,
163
+ };
164
+ }
165
+ /** 删除指定 id 的消息(对齐 Semi deleteMessage)。 */
166
+ export function deleteMessageFrom(chats, target) {
167
+ return chats.filter((item) => item.id !== target.id);
168
+ }
169
+ /**
170
+ * 切换 like(对齐 Semi likeMessage):目标消息 like 取反、dislike 置 false,其余不变。
171
+ */
172
+ export function toggleLike(chats, target) {
173
+ const index = chats.findIndex((item) => item.id === target.id);
174
+ if (index === -1)
175
+ return chats;
176
+ const current = chats[index];
177
+ const next = [...chats];
178
+ next[index] = { ...current, like: !current.like, dislike: false };
179
+ return next;
180
+ }
181
+ /**
182
+ * 切换 dislike(对齐 Semi dislikeMessage):目标消息 dislike 取反、like 置 false,其余不变。
183
+ */
184
+ export function toggleDislike(chats, target) {
185
+ const index = chats.findIndex((item) => item.id === target.id);
186
+ if (index === -1)
187
+ return chats;
188
+ const current = chats[index];
189
+ const next = [...chats];
190
+ next[index] = { ...current, like: false, dislike: !current.dislike };
191
+ return next;
192
+ }
193
+ /**
194
+ * 重置最后一条消息为 loading(对齐 Semi resetMessage):
195
+ * 复制末条并置 status=loading / content='' / 新 id / 新 createAt,替换末条。
196
+ */
197
+ export function resetLastMessage(chats, makeId, now = Date.now) {
198
+ if (chats.length === 0)
199
+ return chats;
200
+ const last = chats[chats.length - 1];
201
+ const reset = {
202
+ ...last,
203
+ status: MESSAGE_STATUS.LOADING,
204
+ content: '',
205
+ id: makeId(),
206
+ createAt: now(),
207
+ };
208
+ return chats.slice(0, -1).concat(reset);
209
+ }
210
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chat.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.test.d.ts","sourceRoot":"","sources":["../src/chat.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,181 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { CHAT_ROLE, MESSAGE_STATUS, SEND_HOT_KEY, SHOW_SCROLL_GAP, SCROLL_ANIMATION_TIME, shouldShowBackBottom, resolveEnableUpload, shouldSendOnEnter, isImageAttachment, buildSendContent, appendDivider, makeUserMessage, deleteMessageFrom, toggleLike, toggleDislike, resetLastMessage, } from './chat.js';
3
+ describe('chat constants', () => {
4
+ it('exposes Semi-aligned constants', () => {
5
+ expect(SHOW_SCROLL_GAP).toBe(100);
6
+ expect(SCROLL_ANIMATION_TIME).toBe(300);
7
+ expect(CHAT_ROLE.DIVIDER).toBe('divider');
8
+ expect(MESSAGE_STATUS.LOADING).toBe('loading');
9
+ expect(SEND_HOT_KEY.SHIFT_PLUS_ENTER).toBe('shift+enter');
10
+ });
11
+ });
12
+ describe('shouldShowBackBottom', () => {
13
+ it('hides within gap of the bottom', () => {
14
+ // distance = 1000 - 950 - 50 = 0 <= 100 → hidden
15
+ expect(shouldShowBackBottom(1000, 950, 50)).toBe(false);
16
+ });
17
+ it('shows when scrolled up beyond gap', () => {
18
+ // distance = 1000 - 300 - 50 = 650 > 100 → visible
19
+ expect(shouldShowBackBottom(1000, 300, 50)).toBe(true);
20
+ });
21
+ it('boundary: exactly gap → hidden', () => {
22
+ // distance = 1000 - 850 - 50 = 100, not > 100 → hidden
23
+ expect(shouldShowBackBottom(1000, 850, 50)).toBe(false);
24
+ });
25
+ it('boundary: one px beyond gap → visible', () => {
26
+ expect(shouldShowBackBottom(1000, 849, 50)).toBe(true);
27
+ });
28
+ });
29
+ describe('resolveEnableUpload (三态)', () => {
30
+ it('undefined → all true', () => {
31
+ expect(resolveEnableUpload(undefined)).toEqual({
32
+ dragUpload: true,
33
+ clickUpload: true,
34
+ pasteUpload: true,
35
+ });
36
+ });
37
+ it('boolean true → all true', () => {
38
+ expect(resolveEnableUpload(true)).toEqual({
39
+ dragUpload: true,
40
+ clickUpload: true,
41
+ pasteUpload: true,
42
+ });
43
+ });
44
+ it('boolean false → all false', () => {
45
+ expect(resolveEnableUpload(false)).toEqual({
46
+ dragUpload: false,
47
+ clickUpload: false,
48
+ pasteUpload: false,
49
+ });
50
+ });
51
+ it('object → per-field, missing defaults true', () => {
52
+ expect(resolveEnableUpload({ clickUpload: false })).toEqual({
53
+ dragUpload: true,
54
+ clickUpload: false,
55
+ pasteUpload: true,
56
+ });
57
+ });
58
+ it('object all false', () => {
59
+ expect(resolveEnableUpload({ clickUpload: false, dragUpload: false, pasteUpload: false })).toEqual({ dragUpload: false, clickUpload: false, pasteUpload: false });
60
+ });
61
+ });
62
+ describe('shouldSendOnEnter', () => {
63
+ it('enter: plain Enter sends', () => {
64
+ expect(shouldSendOnEnter('enter', false)).toBe(true);
65
+ });
66
+ it('enter: Shift+Enter does not send (newline)', () => {
67
+ expect(shouldSendOnEnter('enter', true)).toBe(false);
68
+ });
69
+ it('shift+enter: plain Enter does not send (newline)', () => {
70
+ expect(shouldSendOnEnter('shift+enter', false)).toBe(false);
71
+ });
72
+ it('shift+enter: Shift+Enter sends', () => {
73
+ expect(shouldSendOnEnter('shift+enter', true)).toBe(true);
74
+ });
75
+ });
76
+ describe('isImageAttachment', () => {
77
+ it('detects by MIME prefix', () => {
78
+ expect(isImageAttachment({ name: 'x', fileInstance: { type: 'image/png' } })).toBe(true);
79
+ });
80
+ it('detects by suffix', () => {
81
+ expect(isImageAttachment({ name: 'photo.JPEG' })).toBe(true);
82
+ });
83
+ it('non-image file', () => {
84
+ expect(isImageAttachment({ name: 'doc.pdf', fileInstance: { type: 'application/pdf' } })).toBe(false);
85
+ });
86
+ });
87
+ describe('buildSendContent', () => {
88
+ it('no attachment → plain text string', () => {
89
+ expect(buildSendContent('hello', [])).toBe('hello');
90
+ });
91
+ it('text + image + file → Content[]', () => {
92
+ const attachment = [
93
+ { name: 'a.png', url: 'blob:img', fileInstance: { type: 'image/png' } },
94
+ { name: 'b.pdf', url: 'blob:pdf', size: 10, fileInstance: { type: 'application/pdf' } },
95
+ ];
96
+ const content = buildSendContent('hi', attachment);
97
+ expect(content[0]).toEqual({ type: 'text', text: 'hi' });
98
+ expect(content[1]).toEqual({ type: 'image_url', image_url: { url: 'blob:img' } });
99
+ expect(content[2]).toEqual({
100
+ type: 'file_url',
101
+ file_url: { url: 'blob:pdf', name: 'b.pdf', size: 10, type: 'application/pdf' },
102
+ });
103
+ });
104
+ it('empty text with attachment → no leading text node', () => {
105
+ const content = buildSendContent('', [
106
+ { name: 'a.png', url: 'u', fileInstance: { type: 'image/png' } },
107
+ ]);
108
+ expect(content).toHaveLength(1);
109
+ expect(content[0].type).toBe('image_url');
110
+ });
111
+ });
112
+ describe('appendDivider (clearContext)', () => {
113
+ const makeId = () => 'id-div';
114
+ it('appends a divider message', () => {
115
+ const chats = [{ id: '1', role: 'user', content: 'x' }];
116
+ const next = appendDivider(chats, makeId, () => 1000);
117
+ expect(next).toHaveLength(2);
118
+ expect(next[1]).toEqual({ role: CHAT_ROLE.DIVIDER, id: 'id-div', createAt: 1000 });
119
+ });
120
+ it('skips when last already divider', () => {
121
+ const chats = [{ id: 'd', role: CHAT_ROLE.DIVIDER }];
122
+ expect(appendDivider(chats, makeId)).toBe(chats);
123
+ });
124
+ });
125
+ describe('makeUserMessage', () => {
126
+ it('builds a user message', () => {
127
+ const m = makeUserMessage('hi', () => 'uid', () => 42);
128
+ expect(m).toEqual({ role: CHAT_ROLE.USER, id: 'uid', createAt: 42, content: 'hi' });
129
+ });
130
+ });
131
+ describe('delete / like / dislike / reset', () => {
132
+ const base = [
133
+ { id: '1', role: 'user', content: 'a' },
134
+ { id: '2', role: 'assistant', content: 'b' },
135
+ ];
136
+ it('deleteMessageFrom removes by id', () => {
137
+ const next = deleteMessageFrom(base, { id: '1' });
138
+ expect(next).toHaveLength(1);
139
+ expect(next[0].id).toBe('2');
140
+ });
141
+ it('toggleLike sets like true, dislike false', () => {
142
+ const next = toggleLike(base, { id: '2' });
143
+ expect(next[1].like).toBe(true);
144
+ expect(next[1].dislike).toBe(false);
145
+ // untouched message unchanged
146
+ expect(next[0]).toBe(base[0]);
147
+ });
148
+ it('toggleLike is a toggle', () => {
149
+ const liked = toggleLike(base, { id: '2' });
150
+ const unliked = toggleLike(liked, { id: '2' });
151
+ expect(unliked[1].like).toBe(false);
152
+ });
153
+ it('toggleDislike sets dislike true, like false', () => {
154
+ const next = toggleDislike(base, { id: '2' });
155
+ expect(next[1].dislike).toBe(true);
156
+ expect(next[1].like).toBe(false);
157
+ });
158
+ it('like then dislike clears like', () => {
159
+ const liked = toggleLike(base, { id: '2' });
160
+ const disliked = toggleDislike(liked, { id: '2' });
161
+ expect(disliked[1].like).toBe(false);
162
+ expect(disliked[1].dislike).toBe(true);
163
+ });
164
+ it('resetLastMessage resets tail to loading', () => {
165
+ const next = resetLastMessage(base, () => 'new', () => 99);
166
+ expect(next[1]).toEqual({
167
+ id: 'new',
168
+ role: 'assistant',
169
+ content: '',
170
+ status: MESSAGE_STATUS.LOADING,
171
+ createAt: 99,
172
+ });
173
+ // previous untouched
174
+ expect(next[0]).toBe(base[0]);
175
+ });
176
+ it('missing target id is a no-op', () => {
177
+ expect(toggleLike(base, { id: 'nope' })).toBe(base);
178
+ expect(toggleDislike(base, { id: 'nope' })).toBe(base);
179
+ });
180
+ });
181
+ //# sourceMappingURL=chat.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.test.js","sourceRoot":"","sources":["../src/chat.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * CodeHighlight helpers — framework-agnostic class-name resolution for a
3
+ * Prism-highlighted `<code>` element. Pure functions only; the render layer
4
+ * (svelte runes) owns the DOM effect that calls Prism.highlightElement.
5
+ *
6
+ * Mirrors Semi Design (semi-foundation/codeHighlight): the `<code>` element
7
+ * gets `language-<lang>` and, when line numbers are on, `line-numbers`.
8
+ * We keep Prism itself out of core so this package stays library-agnostic.
9
+ */
10
+ export interface ResolveCodeClassNameOptions {
11
+ /** Prism language id, e.g. 'js' | 'ts' | 'css' | 'markup'. */
12
+ language: string;
13
+ /** When true, add Prism's `line-numbers` plugin class. */
14
+ lineNumber?: boolean;
15
+ }
16
+ /**
17
+ * Resolve the class string for the `<code>` element Prism highlights.
18
+ *
19
+ * Aligns with Semi: if a `language-*` class already exists on the element we
20
+ * do NOT add another (avoids duplicate/conflicting language classes across
21
+ * re-highlights); the required `line-numbers` class is added/kept when
22
+ * `lineNumber` is on and removed when off.
23
+ *
24
+ * @param currentClassName the code element's existing className (may be empty)
25
+ * @param language Prism language id
26
+ * @param lineNumber whether to enable the line-numbers plugin
27
+ * @returns the deduplicated, space-joined class string
28
+ */
29
+ export declare function resolveCodeClassName(currentClassName: string, language: string, lineNumber?: boolean): string;
30
+ //# sourceMappingURL=code-highlight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-highlight.d.ts","sourceRoot":"","sources":["../src/code-highlight.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,UAAO,GAChB,MAAM,CAeR"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * CodeHighlight helpers — framework-agnostic class-name resolution for a
3
+ * Prism-highlighted `<code>` element. Pure functions only; the render layer
4
+ * (svelte runes) owns the DOM effect that calls Prism.highlightElement.
5
+ *
6
+ * Mirrors Semi Design (semi-foundation/codeHighlight): the `<code>` element
7
+ * gets `language-<lang>` and, when line numbers are on, `line-numbers`.
8
+ * We keep Prism itself out of core so this package stays library-agnostic.
9
+ */
10
+ const LANGUAGE_CLASS_RE = /(^|\s)language-\S+/;
11
+ /**
12
+ * Resolve the class string for the `<code>` element Prism highlights.
13
+ *
14
+ * Aligns with Semi: if a `language-*` class already exists on the element we
15
+ * do NOT add another (avoids duplicate/conflicting language classes across
16
+ * re-highlights); the required `line-numbers` class is added/kept when
17
+ * `lineNumber` is on and removed when off.
18
+ *
19
+ * @param currentClassName the code element's existing className (may be empty)
20
+ * @param language Prism language id
21
+ * @param lineNumber whether to enable the line-numbers plugin
22
+ * @returns the deduplicated, space-joined class string
23
+ */
24
+ export function resolveCodeClassName(currentClassName, language, lineNumber = true) {
25
+ const classes = (currentClassName ?? '')
26
+ .split(/\s+/)
27
+ .filter((c) => c && c !== 'line-numbers');
28
+ const hasLanguage = LANGUAGE_CLASS_RE.test(currentClassName ?? '');
29
+ if (!hasLanguage && language) {
30
+ classes.push(`language-${language}`);
31
+ }
32
+ if (lineNumber) {
33
+ classes.push('line-numbers');
34
+ }
35
+ return classes.join(' ');
36
+ }
37
+ //# sourceMappingURL=code-highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-highlight.js","sourceRoot":"","sources":["../src/code-highlight.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAE/C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAClC,gBAAwB,EACxB,QAAgB,EAChB,UAAU,GAAG,IAAI;IAEjB,MAAM,OAAO,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;SACrC,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=code-highlight.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-highlight.test.d.ts","sourceRoot":"","sources":["../src/code-highlight.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { resolveCodeClassName } from './code-highlight.js';
3
+ describe('resolveCodeClassName', () => {
4
+ it('adds language-<lang> when empty', () => {
5
+ expect(resolveCodeClassName('', 'js', false)).toBe('language-js');
6
+ });
7
+ it('adds line-numbers when lineNumber on', () => {
8
+ expect(resolveCodeClassName('', 'ts', true)).toBe('language-ts line-numbers');
9
+ });
10
+ it('defaults lineNumber to true', () => {
11
+ expect(resolveCodeClassName('', 'css')).toBe('language-css line-numbers');
12
+ });
13
+ it('does not duplicate an existing language class', () => {
14
+ expect(resolveCodeClassName('language-js', 'js', false)).toBe('language-js');
15
+ });
16
+ it('keeps an existing (different) language class and does not add a new one', () => {
17
+ // aligns with Semi: presence of any language-* short-circuits adding
18
+ expect(resolveCodeClassName('language-python', 'js', false)).toBe('language-python');
19
+ });
20
+ it('preserves unrelated existing classes', () => {
21
+ expect(resolveCodeClassName('foo bar', 'js', false)).toBe('foo bar language-js');
22
+ });
23
+ it('removes line-numbers when lineNumber is off', () => {
24
+ expect(resolveCodeClassName('language-js line-numbers', 'js', false)).toBe('language-js');
25
+ });
26
+ it('does not duplicate line-numbers when already present and on', () => {
27
+ expect(resolveCodeClassName('language-js line-numbers', 'js', true)).toBe('language-js line-numbers');
28
+ });
29
+ it('omits language class when language is empty', () => {
30
+ expect(resolveCodeClassName('', '', false)).toBe('');
31
+ });
32
+ it('handles extra whitespace in the incoming className', () => {
33
+ expect(resolveCodeClassName(' foo ', 'js', false)).toBe('foo language-js');
34
+ });
35
+ });
36
+ //# sourceMappingURL=code-highlight.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-highlight.test.js","sourceRoot":"","sources":["../src/code-highlight.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,oBAAoB,CAAC,aAAa,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,qEAAqE;QACrE,MAAM,CAAC,oBAAoB,CAAC,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,oBAAoB,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,oBAAoB,CAAC,0BAA0B,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,oBAAoB,CAAC,0BAA0B,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CACvE,0BAA0B,CAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,oBAAoB,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Collapsible headless — 折叠容器原语的渲染/可见性派生逻辑。
3
+ * 无 DOM 依赖的纯函数,供 Collapsible.svelte 与单测复用。
4
+ *
5
+ * 对齐 Semi collapsible foundation:
6
+ * - visible:内容当前是否「视觉可见」(展开中或展开完成);折叠过渡结束后置 false。
7
+ * - shouldRender:内容 DOM 是否应挂载(keepDOM × lazyRender × isOpen × collapseHeight 组合)。
8
+ */
9
+ export interface CollapsibleRenderInput {
10
+ /** 是否展开 */
11
+ isOpen: boolean;
12
+ /** 折叠时是否保留 DOM(false 则完全折叠后卸载内容) */
13
+ keepDOM: boolean;
14
+ /** 首次展开前不渲染(配合 keepDOM 的首帧惰性) */
15
+ lazyRender: boolean;
16
+ /** 折叠时保留的高度(>0 时内容常驻以呈现「展开更多」截断) */
17
+ collapseHeight: number;
18
+ /** 内容当前视觉可见(展开中/展开完成,折叠过渡结束前仍为 true) */
19
+ visible: boolean;
20
+ /** 内容此前是否已被渲染过(lazyRender 用;普通簿记,非响应式) */
21
+ hasBeenRendered: boolean;
22
+ }
23
+ /**
24
+ * 是否应把内容挂载到 DOM。对齐 Semi:
25
+ * keepDOM && (lazyRender ? hasBeenRendered : true)
26
+ * || collapseHeight !== 0
27
+ * || visible
28
+ * || isOpen
29
+ *
30
+ * - keepDOM 且非 lazyRender:内容常驻。
31
+ * - keepDOM 且 lazyRender:首次展开(hasBeenRendered)后才常驻。
32
+ * - collapseHeight>0:折叠仍保留部分高度,故内容必须挂载。
33
+ * - 其余:展开中/展开完成(visible)或正在展开(isOpen)时挂载,完全折叠后卸载。
34
+ */
35
+ export declare function collapsibleShouldRender(input: CollapsibleRenderInput): boolean;
36
+ /**
37
+ * 折叠态实际保留高度:collapseHeightAdaptive 时不超过实测内容高度,
38
+ * 否则直接用 collapseHeight。domHeight 为已测内容高度(无测量时传 0)。
39
+ */
40
+ export declare function collapsibleCollapsedHeight(collapseHeight: number, collapseHeightAdaptive: boolean, domHeight: number): number;
41
+ //# sourceMappingURL=collapsible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../src/collapsible.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,sBAAsB;IACrC,WAAW;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAI9E;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,MAAM,EACtB,sBAAsB,EAAE,OAAO,EAC/B,SAAS,EAAE,MAAM,GAChB,MAAM,CAER"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Collapsible headless — 折叠容器原语的渲染/可见性派生逻辑。
3
+ * 无 DOM 依赖的纯函数,供 Collapsible.svelte 与单测复用。
4
+ *
5
+ * 对齐 Semi collapsible foundation:
6
+ * - visible:内容当前是否「视觉可见」(展开中或展开完成);折叠过渡结束后置 false。
7
+ * - shouldRender:内容 DOM 是否应挂载(keepDOM × lazyRender × isOpen × collapseHeight 组合)。
8
+ */
9
+ /**
10
+ * 是否应把内容挂载到 DOM。对齐 Semi:
11
+ * keepDOM && (lazyRender ? hasBeenRendered : true)
12
+ * || collapseHeight !== 0
13
+ * || visible
14
+ * || isOpen
15
+ *
16
+ * - keepDOM 且非 lazyRender:内容常驻。
17
+ * - keepDOM 且 lazyRender:首次展开(hasBeenRendered)后才常驻。
18
+ * - collapseHeight>0:折叠仍保留部分高度,故内容必须挂载。
19
+ * - 其余:展开中/展开完成(visible)或正在展开(isOpen)时挂载,完全折叠后卸载。
20
+ */
21
+ export function collapsibleShouldRender(input) {
22
+ const { isOpen, keepDOM, lazyRender, collapseHeight, visible, hasBeenRendered } = input;
23
+ const keptByDOM = keepDOM && (lazyRender ? hasBeenRendered : true);
24
+ return keptByDOM || collapseHeight !== 0 || visible || isOpen;
25
+ }
26
+ /**
27
+ * 折叠态实际保留高度:collapseHeightAdaptive 时不超过实测内容高度,
28
+ * 否则直接用 collapseHeight。domHeight 为已测内容高度(无测量时传 0)。
29
+ */
30
+ export function collapsibleCollapsedHeight(collapseHeight, collapseHeightAdaptive, domHeight) {
31
+ return collapseHeightAdaptive ? Math.min(domHeight, collapseHeight) : collapseHeight;
32
+ }
33
+ //# sourceMappingURL=collapsible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../src/collapsible.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAA6B;IACnE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IACxF,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnE,OAAO,SAAS,IAAI,cAAc,KAAK,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,cAAsB,EACtB,sBAA+B,EAC/B,SAAiB;IAEjB,OAAO,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;AACvF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=collapsible.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collapsible.test.d.ts","sourceRoot":"","sources":["../src/collapsible.test.ts"],"names":[],"mappings":""}