@plumeai/plugin-sdk 0.0.0-stage → 0.1.3

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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/bin/plume-plugin.mjs +70 -0
  3. package/dist/client/styles/src/index.d.ts +123 -0
  4. package/dist/client/ui/src/avatar/AgentAvatar.d.ts +42 -0
  5. package/dist/client/ui/src/avatar/AvatarPile.d.ts +36 -0
  6. package/dist/client/ui/src/avatar/AvatarStack.d.ts +26 -0
  7. package/dist/client/ui/src/avatar/art.d.ts +32 -0
  8. package/dist/client/ui/src/fileIcon.d.ts +33 -0
  9. package/dist/client/ui/src/hooks/useCopied.d.ts +16 -0
  10. package/dist/client/ui/src/hooks/useLiveRefresh.d.ts +22 -0
  11. package/dist/client/ui/src/hooks/useNarrow.d.ts +16 -0
  12. package/dist/client/ui/src/i18n/context.d.ts +17 -0
  13. package/dist/client/ui/src/i18n/index.d.ts +2 -0
  14. package/dist/client/ui/src/i18n/list.d.ts +20 -0
  15. package/dist/client/ui/src/i18n/locales.d.ts +10 -0
  16. package/dist/client/ui/src/i18n/messages/en.d.ts +1418 -0
  17. package/dist/client/ui/src/i18n/messages/index.d.ts +6 -0
  18. package/dist/client/ui/src/i18n/messages/zh-CN.d.ts +1263 -0
  19. package/dist/client/ui/src/i18n/plural.d.ts +16 -0
  20. package/dist/client/ui/src/i18n/translate.d.ts +43 -0
  21. package/dist/client/ui/src/icons/index.d.ts +5 -0
  22. package/dist/client/ui/src/image/AnnotateCanvas.d.ts +29 -0
  23. package/dist/client/ui/src/image/AnnotateToolbar.d.ts +73 -0
  24. package/dist/client/ui/src/image/Annotator.d.ts +154 -0
  25. package/dist/client/ui/src/image/annotate.d.ts +227 -0
  26. package/dist/client/ui/src/image/paint.d.ts +35 -0
  27. package/dist/client/ui/src/image/screenshot-geometry.d.ts +112 -0
  28. package/dist/client/ui/src/image/useBarDrag.d.ts +31 -0
  29. package/dist/client/ui/src/image/useMovableBar.d.ts +26 -0
  30. package/dist/client/ui/src/image/useToolbarPlacement.d.ts +42 -0
  31. package/dist/client/ui/src/index.d.ts +140 -0
  32. package/dist/client/ui/src/inputs/ColorField.d.ts +9 -0
  33. package/dist/client/ui/src/inputs/ComposerToggle.d.ts +23 -0
  34. package/dist/client/ui/src/inputs/DateRangeField.d.ts +25 -0
  35. package/dist/client/ui/src/inputs/NativeField.d.ts +5 -0
  36. package/dist/client/ui/src/inputs/SearchField.d.ts +21 -0
  37. package/dist/client/ui/src/inputs/Segmented.d.ts +23 -0
  38. package/dist/client/ui/src/inputs/Select.d.ts +32 -0
  39. package/dist/client/ui/src/inputs/ShortcutRecorder.d.ts +8 -0
  40. package/dist/client/ui/src/inputs/Slider.d.ts +13 -0
  41. package/dist/client/ui/src/inputs/TextArea.d.ts +30 -0
  42. package/dist/client/ui/src/inputs/Toggle.d.ts +10 -0
  43. package/dist/client/ui/src/inputs/WorktreeToggle.d.ts +19 -0
  44. package/dist/client/ui/src/inputs/day-range.d.ts +57 -0
  45. package/dist/client/ui/src/inputs/pickers.d.ts +40 -0
  46. package/dist/client/ui/src/inputs/useFieldFade.d.ts +1 -0
  47. package/dist/client/ui/src/keyboard.d.ts +21 -0
  48. package/dist/client/ui/src/layout/ApprovalFrame.d.ts +33 -0
  49. package/dist/client/ui/src/layout/Collapse.d.ts +9 -0
  50. package/dist/client/ui/src/layout/CopyMark.d.ts +19 -0
  51. package/dist/client/ui/src/layout/Disclosure.d.ts +66 -0
  52. package/dist/client/ui/src/layout/ErrorBoundary.d.ts +26 -0
  53. package/dist/client/ui/src/layout/PageTopRow.d.ts +19 -0
  54. package/dist/client/ui/src/layout/PanelEmpty.d.ts +17 -0
  55. package/dist/client/ui/src/layout/ResizeHandle.d.ts +24 -0
  56. package/dist/client/ui/src/layout/RetainedViews.d.ts +32 -0
  57. package/dist/client/ui/src/layout/Settings.d.ts +41 -0
  58. package/dist/client/ui/src/layout/Splitter.d.ts +25 -0
  59. package/dist/client/ui/src/lib/agent-avatar.d.ts +58 -0
  60. package/dist/client/ui/src/lib/code/font-stack.d.ts +12 -0
  61. package/dist/client/ui/src/lib/code/themes.d.ts +35 -0
  62. package/dist/client/ui/src/lib/date-format.d.ts +8 -0
  63. package/dist/client/ui/src/lib/dispatches.d.ts +8 -0
  64. package/dist/client/ui/src/lib/hour-style.d.ts +13 -0
  65. package/dist/client/ui/src/lib/number-draft.d.ts +24 -0
  66. package/dist/client/ui/src/lib/relative-time.d.ts +18 -0
  67. package/dist/client/ui/src/lib/tiling.d.ts +89 -0
  68. package/dist/client/ui/src/lib/typing.d.ts +19 -0
  69. package/dist/client/ui/src/motion/RollWords.d.ts +26 -0
  70. package/dist/client/ui/src/motion/RollingText.d.ts +43 -0
  71. package/dist/client/ui/src/motion/TypedText.d.ts +9 -0
  72. package/dist/client/ui/src/motion/freeze.d.ts +22 -0
  73. package/dist/client/ui/src/motion/held.d.ts +17 -0
  74. package/dist/client/ui/src/motion/loaders.d.ts +65 -0
  75. package/dist/client/ui/src/motion/reduced.d.ts +13 -0
  76. package/dist/client/ui/src/motion/ticked.d.ts +24 -0
  77. package/dist/client/ui/src/motion/ticker.d.ts +31 -0
  78. package/dist/client/ui/src/motion/tokens.d.ts +29 -0
  79. package/dist/client/ui/src/motion/useNow.d.ts +6 -0
  80. package/dist/client/ui/src/overlay/Confirm.d.ts +96 -0
  81. package/dist/client/ui/src/overlay/ContextMenu.d.ts +40 -0
  82. package/dist/client/ui/src/overlay/Dialog.d.ts +60 -0
  83. package/dist/client/ui/src/overlay/Menu.d.ts +90 -0
  84. package/dist/client/ui/src/overlay/Overlay.d.ts +17 -0
  85. package/dist/client/ui/src/overlay/Popover.d.ts +127 -0
  86. package/dist/client/ui/src/overlay/Tooltip.d.ts +14 -0
  87. package/dist/client/ui/src/overlay/afterimage.d.ts +20 -0
  88. package/dist/client/ui/src/overlay/chrome-top.d.ts +8 -0
  89. package/dist/client/ui/src/overlay/hover-layers.d.ts +41 -0
  90. package/dist/client/ui/src/overlay/portal.d.ts +21 -0
  91. package/dist/client/ui/src/overlay/scrims.d.ts +20 -0
  92. package/dist/client/ui/src/overlay/tooltip-attribute.d.ts +62 -0
  93. package/dist/client/ui/src/primitives/Button.d.ts +64 -0
  94. package/dist/client/ui/src/primitives/Caret.d.ts +25 -0
  95. package/dist/client/ui/src/primitives/ChoiceMark.d.ts +12 -0
  96. package/dist/client/ui/src/primitives/ClosableTab.d.ts +23 -0
  97. package/dist/client/ui/src/primitives/CountUp.d.ts +21 -0
  98. package/dist/client/ui/src/primitives/GitHubMark.d.ts +12 -0
  99. package/dist/client/ui/src/primitives/IconButton.d.ts +55 -0
  100. package/dist/client/ui/src/primitives/MarkNumber.d.ts +12 -0
  101. package/dist/client/ui/src/primitives/RowDeleteButton.d.ts +6 -0
  102. package/dist/client/ui/src/primitives/Skeleton.d.ts +36 -0
  103. package/dist/client/ui/src/primitives/TabStrip.d.ts +29 -0
  104. package/dist/client/ui/src/primitives/Text.d.ts +341 -0
  105. package/dist/client/ui/src/primitives/TimeAgo.d.ts +13 -0
  106. package/dist/client/ui/src/primitives/useCountUp.d.ts +23 -0
  107. package/dist/client/ui/src/row/FlowRow.d.ts +31 -0
  108. package/dist/client/ui/src/row/HoverRow.d.ts +28 -0
  109. package/dist/client/ui/src/scroll/BackToLatest.d.ts +19 -0
  110. package/dist/client/ui/src/scroll/OverlayScrollbar.d.ts +9 -0
  111. package/dist/client/ui/src/scroll/ScrollText.d.ts +24 -0
  112. package/dist/client/ui/src/scroll/Scroller.d.ts +66 -0
  113. package/dist/client/ui/src/scroll/Sideways.d.ts +30 -0
  114. package/dist/client/ui/src/scroll/fade.d.ts +2 -0
  115. package/dist/client/ui/src/scroll/follow.d.ts +157 -0
  116. package/dist/client/ui/src/scroll/measure-batch.d.ts +13 -0
  117. package/dist/client/ui/src/scroll/memory.d.ts +22 -0
  118. package/dist/client/ui/src/scroll/signature.d.ts +24 -0
  119. package/dist/client/ui/src/scroll/useFollowBottom.d.ts +80 -0
  120. package/dist/client/ui/src/scroll/useSideways.d.ts +29 -0
  121. package/dist/contract/src/app.d.ts +16 -0
  122. package/dist/contract/src/changes.d.ts +50 -0
  123. package/dist/contract/src/diagnostics.d.ts +86 -0
  124. package/dist/contract/src/index.d.ts +18 -0
  125. package/dist/contract/src/plugin.d.ts +1391 -0
  126. package/dist/contract/src/resources.d.ts +79 -0
  127. package/dist/contract/src/service.d.ts +806 -0
  128. package/dist/contract/src/ui.d.ts +1039 -0
  129. package/dist/contract/src/usage.d.ts +102 -0
  130. package/dist/core/llm/ai/anthropic-messages-request.d.ts +82 -0
  131. package/dist/core/llm/ai/anthropic-messages.d.ts +43 -0
  132. package/dist/core/llm/ai/cache-routing.d.ts +53 -0
  133. package/dist/core/llm/ai/chat-delta.d.ts +107 -0
  134. package/dist/core/llm/ai/compat-key.d.ts +19 -0
  135. package/dist/core/llm/ai/endpoint.d.ts +57 -0
  136. package/dist/core/llm/ai/failure.d.ts +181 -0
  137. package/dist/core/llm/ai/index.d.ts +16 -0
  138. package/dist/core/llm/ai/openai-chat-completions-request.d.ts +49 -0
  139. package/dist/core/llm/ai/openai-chat-completions.d.ts +37 -0
  140. package/dist/core/llm/ai/openai-responses-request.d.ts +63 -0
  141. package/dist/core/llm/ai/openai-responses.d.ts +11 -0
  142. package/dist/core/llm/ai/prefix-fingerprint.d.ts +20 -0
  143. package/dist/core/llm/ai/reasoning-compat.d.ts +69 -0
  144. package/dist/core/llm/ai/request-params-compat.d.ts +39 -0
  145. package/dist/core/llm/ai/retry.d.ts +130 -0
  146. package/dist/core/llm/ai/sanitize-history.d.ts +23 -0
  147. package/dist/core/llm/ai/think-tag.d.ts +37 -0
  148. package/dist/core/llm/ai/thinking-options.d.ts +35 -0
  149. package/dist/core/llm/ai/tool-names.d.ts +17 -0
  150. package/dist/core/llm/ai/tool-pairing-compat.d.ts +53 -0
  151. package/dist/core/llm/ai/tool-result-images-compat.d.ts +24 -0
  152. package/dist/core/llm/ai/tool-schema.d.ts +20 -0
  153. package/dist/core/llm/ai/usage-fields.d.ts +30 -0
  154. package/dist/core/llm/ai/vendors/index.d.ts +20 -0
  155. package/dist/core/llm/ai/vendors/thinking.d.ts +39 -0
  156. package/dist/core/llm/ai/vendors/types.d.ts +47 -0
  157. package/dist/core/llm/config/image-models.d.ts +34 -0
  158. package/dist/core/llm/config/retry-policy.d.ts +35 -0
  159. package/dist/core/llm/images/chat-images.d.ts +11 -0
  160. package/dist/core/llm/images/dimensions.d.ts +15 -0
  161. package/dist/core/llm/images/generate.d.ts +15 -0
  162. package/dist/core/llm/images/openai-images.d.ts +11 -0
  163. package/dist/core/llm/images/quota.d.ts +9 -0
  164. package/dist/core/llm/images/shape.d.ts +44 -0
  165. package/dist/core/llm/images/types.d.ts +118 -0
  166. package/dist/core/llm/model-catalog-format.d.ts +50 -0
  167. package/dist/core/llm/model-catalog.d.ts +51 -0
  168. package/dist/core/llm/types/message.d.ts +450 -0
  169. package/dist/core/llm/types/provider.d.ts +169 -0
  170. package/dist/core/llm/types/tool.d.ts +23 -0
  171. package/dist/core/llm/types.d.ts +10 -0
  172. package/dist/core/llm/utils/pricing.d.ts +18 -0
  173. package/dist/core/llm/utils/record.d.ts +2 -0
  174. package/dist/core/llm/utils/sse.d.ts +69 -0
  175. package/dist/infra/rpc/src/endpoint.d.ts +36 -0
  176. package/dist/infra/rpc/src/index.d.ts +2 -0
  177. package/dist/infra/rpc/src/rpc.d.ts +54 -0
  178. package/dist/theme.css +336 -0
  179. package/dist/ui.d.ts +2 -0
  180. package/lib/build.mjs +143 -0
  181. package/lib/check.mjs +23 -0
  182. package/lib/dev.mjs +52 -0
  183. package/lib/icons.mjs +2 -0
  184. package/lib/init.mjs +109 -0
  185. package/lib/install.mjs +80 -0
  186. package/lib/link.mjs +44 -0
  187. package/lib/lint/i18n.mjs +149 -0
  188. package/lib/lint/imports.mjs +83 -0
  189. package/lib/lint/index.mjs +54 -0
  190. package/lib/lint/styles.mjs +160 -0
  191. package/lib/manifest.d.mts +9 -0
  192. package/lib/manifest.mjs +99 -0
  193. package/lib/targets.mjs +60 -0
  194. package/package.json +34 -4
  195. package/skill/SKILL.md +150 -0
  196. package/skill/references/components.md +2830 -0
  197. package/skill/references/logic.md +526 -0
  198. package/skill/references/style-i18n.md +70 -0
  199. package/skill/references/ui.md +532 -0
  200. package/template/AGENTS.md +17 -0
  201. package/template/CLAUDE.md +1 -0
  202. package/template/README.md +12 -0
  203. package/template/gitignore +2 -0
  204. package/template/src/index.ts +28 -0
  205. package/template/src/messages.ts +16 -0
  206. package/template/src/types.ts +8 -0
  207. package/template/src/ui.tsx +30 -0
  208. package/template/tsconfig.json +7 -0
  209. package/tsconfig.json +25 -0
  210. package/README.md +0 -3
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 平铺树的几何:几棵平铺树(停靠面板、对话分屏)共用的那一半。
3
+ *
4
+ * 两棵树叶子不同——一个是面板种类,一个是会话——但分支长得一样:方向、每个孩子的份额、孩子。
5
+ * 分隔条在哪、拖到某个像素时近侧该占多少,只看分支,所以只写一份。叶子怎么排
6
+ * 各自留在自己的域里,那部分才真的不同。
7
+ */
8
+ export type Axis = "row" | "col";
9
+ /**
10
+ * 容器里的一个矩形,两个轴都按 0 到 1 的比例算。
11
+ *
12
+ * 用比例不用像素,这里才能保持纯函数:不要元素、不要测量、不要排版,首帧之前和之后算出来一样。
13
+ * 百分比直接写到元素上,窗口缩放由浏览器处理,这里不用重算。
14
+ */
15
+ export interface Box {
16
+ left: number;
17
+ top: number;
18
+ width: number;
19
+ height: number;
20
+ }
21
+ /** 两棵树共有的形状:只要分支,叶子长什么样这里不关心。 */
22
+ type Tiling = {
23
+ type: "leaf";
24
+ } | {
25
+ type: "split";
26
+ dir: Axis;
27
+ sizes: readonly number[];
28
+ children: readonly Tiling[];
29
+ };
30
+ /**
31
+ * 两个窗格之间一条能拖的边界。
32
+ *
33
+ * 用它所属的分支和近侧的那个孩子来标识,这正是每棵树的 `resize` 要的参数——分隔条可以直接动手,
34
+ * 中间不用有谁再去推算它是「哪条边」的分隔条。
35
+ */
36
+ export interface SplitterBox extends Box {
37
+ path: number[];
38
+ index: number;
39
+ dir: Axis;
40
+ /** 近侧窗格现在的份额,拖动从分隔条实际所在的地方开始。 */
41
+ share: number;
42
+ /** 两侧窗格份额之和,也就是这条分隔条能拖动的范围。 */
43
+ pair: number;
44
+ /**
45
+ * 这条分隔条所分开的那个分支的框。
46
+ *
47
+ * 带在这里而不是之后再查:拖这条分隔条时就是在这个参照系里量的,而产出分隔条的那一刻它已经知道了。
48
+ */
49
+ split: Box;
50
+ }
51
+ export declare const FULL: Box;
52
+ /**
53
+ * 分隔条的抓取区,跨在两个窗格的边界上。
54
+ *
55
+ * 和侧栏的 `ResizeHandle` 一样是 9px,理由也一样:能稳稳点中、又不至于成为一条看得见的边框的最窄宽度。
56
+ */
57
+ export declare const SPLITTER_HIT = 9;
58
+ /** 键盘每按一下调多少,按份额算。按住 Shift 翻倍。 */
59
+ export declare const SPLITTER_STEP = 0.02;
60
+ /** 分隔条上那段握把多长:够长才读得出是握把,够短才不像边框。 */
61
+ export declare const GRIP_SPAN = 30;
62
+ /**
63
+ * 比例转成 CSS。
64
+ *
65
+ * 要取整,但故意不取到整百分比。框是按精确的比例算的,正好铺满;低精度写进 CSS 会把算术刚合上的
66
+ * 两格之间的缝又撑开,窗格旁边露出一道亚像素宽的窗口底色。六位小数远超任何屏幕的分辨率,又短到
67
+ * 帧与帧之间字符串不变——这一点要紧:每帧都变的样式字符串会打断它本该在过渡的那个过渡。
68
+ */
69
+ export declare const pct: (fraction: number) => string;
70
+ /** 给定在轴上从哪开始、占多少,从父框里切出孩子的框。 */
71
+ export declare function slice(rect: Box, dir: Axis, offset: number, share: number): Box;
72
+ /**
73
+ * 所有能拖的边界。
74
+ *
75
+ * n 个孩子的分支有 n−1 条——分支的外沿是包着它的东西的边,不是两个窗格之间的边界。
76
+ *
77
+ * 每条都画成零厚度的线;抓取区由组件加,只有组件知道九个像素是多宽。
78
+ */
79
+ export declare function layoutSplitters(tree: Tiling, within?: Box): SplitterBox[];
80
+ /**
81
+ * 把指针位置换算成分隔条近侧窗格该占的份额。
82
+ *
83
+ * 参照系是分支自己的框,不是容器的。嵌套分支里的分隔条在**那个**分支的长度里移动,按整个窗口量的话
84
+ * 速度就不对——窄列里拖不动,宽列里两头都冲出去。
85
+ *
86
+ * `position` 是拖动轴上的客户区坐标:横向分支是 `clientX`,纵向是 `clientY`。
87
+ */
88
+ export declare function shareFromPointer(handle: SplitterBox, position: number, container: Box): number;
89
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 一个字符串一个字一个字地改写成另一个。
3
+ *
4
+ * 一段对话在运行时读完第一条消息之前,标题是「新对话」,之后真标题才落下来。一帧之内直接替换,是侧栏里
5
+ * 唯一一处「行变了,却和你刚做的事无关」的时刻;硬切的话读起来像列表在指针底下自己重排了一次。改写一遍
6
+ * 传达的是同一件事,只是成了一个看得见过程的事件。
7
+ *
8
+ * 共同前缀保留不删,于是「查一下依赖」→「查一下依赖为什么装不上」不会先退回到空,而是只打出尾巴。
9
+ * 这种情况很常见:存下的标题是从提示词里取的,它和替换它的那个往往开头一样。
10
+ *
11
+ * 按码点而不是 UTF-16 单元:`[...text]` 让 emoji 和其他星际字符保持完整,`slice` 会把代理对切成两半,
12
+ * 有一帧画出替换字形。
13
+ */
14
+ /**
15
+ * `from` 到 `to` 之间的每个中间字符串,按顺序,最后一个是 `to`。
16
+ *
17
+ * 没什么可演的时候是空的——两个字符串相同,或者原来没有值、第一个值刚到——调用方读作「不演,直接画」。
18
+ */
19
+ export declare function typingFrames(from: string, to: string, maxFrames?: number): string[];
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * 一行流水行里换掉的那句话:新的从一道缝里落进来,词框的宽度跟着平滑地变。
4
+ *
5
+ * 只滚字、不管宽的话,一句短的换成一句长的那一帧,后面的箭头、+N -M 直接被顶出去一截——字在滚,
6
+ * 行尾在跳,看上去比不滚还生硬。宽度在换的那一下钉成像素:量出新宽,先钉回旧宽、再设新宽,过渡走完
7
+ * 就放回 auto。一直钉着的话,网页字体晚到、改字号之后词框还是旧的宽度,字会被截掉。
8
+ *
9
+ * 扫光(`glide`)挂在字自己身上,不挂在外层:滚进来的那层带着 transform 被单独合成,外层的
10
+ * `background-clip: text` 裁不到它,滚动那一下字会整个消失。所以用它的行,外层不要再挂一道扫光。
11
+ *
12
+ * 只是往后长的一句(`text` 变了、`rollKey` 没变)不滚,只缓宽度:前面的字原地不动,新接上的那截随着框
13
+ * 变宽从句尾露出来。
14
+ */
15
+ export declare function RollWords({ rollKey, text, from, glide, enter, children, }: {
16
+ /** 换了它才算换了一句;同一句里参数还在流进来,不重新滚。 */
17
+ rollKey: string;
18
+ /** 这句话现在的字。给了它,字变了也缓宽度,但不滚。 */
19
+ text?: string;
20
+ /** 挂上时从这个宽度缓过来:这一行接替了原地另一行的字(比如一列步骤里后一步接替前一步那一行)。 */
21
+ from?: number;
22
+ glide?: boolean;
23
+ /** 挂上的时候也滚:这一行接替了原地的另一行。 */
24
+ enter?: boolean;
25
+ children: ReactNode;
26
+ }): import("react").JSX.Element;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 装着值的那个框——滚动的是它,溢出的也是它。
3
+ *
4
+ * 导出是因为要截断的父元素得找得到它:外层的宽度受它的父元素约束,所以外层永远不溢出,任何要量「这个是不是
5
+ * 被截了」的东西都得去问里面这个框。
6
+ */
7
+ export declare const ROLL_VALUE = "plume-roll-value";
8
+ /**
9
+ * 一个值替换另一个值,不管发生在哪里。
10
+ *
11
+ * 原地变化的字——输入框里的推理强度、刚选的模型、权限模式、「展开显示」变成「收起」——不滚的话,眼睛除了
12
+ * 字形不同以外收不到任何「发生了什么」的信号:在正拖着的控件上读起来像渲染瑕疵,在刚点过的控件上读起来像
13
+ * 那一下点了没用。
14
+ *
15
+ * 动作是 `ui/motion.css` 里的 `.plume-roll`——总是往下,一连串的变化读起来是一个东西在被拨动,而不是字在闪。
16
+ * 有了这个组件,用上它就是选对元素的事,而不必记住一个两步的写法(`key={value}` 加 `plume-roll`)。
17
+ *
18
+ * 给标签用,不给读数用。会跳的数——token 数、计时器、百分比——是在连续变化而不是被替换,每跳一下滚一次,
19
+ * 一块安静的仪表就成了整轮里一直在余光里动的东西。那些用 `tabular-nums` 定住。
20
+ */
21
+ export declare function RollingText({ children, className, rollKey, }: {
22
+ children: string | number;
23
+ /** 落在外层元素上,它默认是 `inline`——需要的地方给它 `block`。 */
24
+ className?: string;
25
+ /** 改写什么算「换了一个值」,给带着一段总在变的部分的文字用。 */
26
+ rollKey?: string | number;
27
+ }): import("react").JSX.Element;
28
+ /**
29
+ * 这个值是否被替换过——首次绘制时是 false,从第一次变化起是 true。
30
+ *
31
+ * 有两件事靠它做对,而它们往相反的方向拉。
32
+ *
33
+ * 首次绘制不能动。挂上就滚的话,菜单一打开每个标签都落进位,叠在菜单自己的进场上——两个不同方向的动作,
34
+ * 读起来像面板在你面前被拼起来。
35
+ *
36
+ * 可类也不能来来去去,这一点更隐蔽:给元素加上 `animation` 就会**开始**那个动画。一个在下一次无关渲染时
37
+ * 退回 false 的标记,会在再下一次渲染时把类加回来,于是输入框里任何一个标签一变,所有标签都滚一遍。所以它
38
+ * 是锁存的:一旦为 true 就一直是 true,此后动画完全由 `key` 变化引起的重新挂载来驱动。
39
+ *
40
+ * 在渲染期间调整状态,是从一个变了的 prop 推导状态的官方做法——React 丢掉这一遍、立刻重跑组件,于是类和新
41
+ * key 落在同一次提交里,元素挂上时就已经在动。
42
+ */
43
+ export declare function useRolled(value: string | number): boolean;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 一个字符串一个字一个字地改写成下一个。
3
+ *
4
+ * 返回这一帧该显示的东西。第一个值不演——原来那里什么都没有,谈不上替换——关掉动效时的任何变化也不演。
5
+ *
6
+ * 做成 hook 而不是组件,因为这段字通常另有去处:侧栏把它交给 `ScrollText`,由它量字符串决定这一行悬停时
7
+ * 滚不滚。交给它一个渲染好的元素,就是在量一个正在动的目标。
8
+ */
9
+ export declare function useTypedText(text: string): string;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * 拖动期间一动不动。
3
+ *
4
+ * 有几个元素会缓动到新的几何位置上,布局自己变的时候这是对的,指针在拖边界的时候就错了:每一帧开始的
5
+ * 过渡都被下一帧盖掉,窗格追着指针跑而不是跟着它,永远落不稳。
6
+ *
7
+ * 冻结原先是 `<html>` 上的一个标记加上以它为键的规则——`:root[data-resizing] *`。读起来顺,却是拖动时
8
+ * 最贵的一件事。在一个 8,948 条消息、屏上 8,585 个元素的真实会话里量的:
9
+ *
10
+ * 设 data-dock-dragging 94ms (通配选择器)
11
+ * 设 data-dock-dragging 44ms (收窄到 `:root[data-…] .plume-dock-pane` 之后)
12
+ * 设一个无关属性 0ms (对照)
13
+ *
14
+ * 收窄选择器不够,中间那行就是原因。祖先上的属性仍然要对它下面的整棵子树求一遍,所以根上的标记是对整份
15
+ * 文档提的问题,不管答案最后多具体——而一次拖动进出各要翻两三个这样的标记。抓住东西那一刻的卡顿就是它:
16
+ * 不是布局,不是 React,是一个属性。
17
+ *
18
+ * 所以改成点名。`.plume-freeze` 标出拖动真正会改变几何的那些元素——窗格、侧栏所在的框、高度跟着放得下
19
+ * 多少走的折叠组——这里只给它们加标记,样式引擎经类索引就能找到,不用遍历任何东西。
20
+ */
21
+ export declare function freezeMotion(): () => void;
22
+ export declare function inertPanes(): () => void;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 一句话至少挂多久才换下一句。
3
+ *
4
+ * 一段探索里 read、grep 常常一两百毫秒就来一次,来一次换一句的话,字还没读完就滚走了,整行一直在抖。
5
+ * 650ms 是 OpenClaude Desktop(照官方 Claude 桌面端)的取值。它必须比滚进来的那段动画(`DURATION.slow`)
6
+ * 长,否则上一句还没落定下一句就开始滚。
7
+ */
8
+ export declare const HOLD_MS = 650;
9
+ /**
10
+ * `key` 换了之后,返回的那个至少要在屏幕上待满 `ms` 才跟着换。
11
+ *
12
+ * 待满以前新来的几个 key 不排队:到点时直接换成那一刻最新的那个,中间的跳过。要的是每一句都读得完,
13
+ * 不是每一句都出现过。
14
+ *
15
+ * 用布局副作用换,不用普通副作用:已经待满的那一下当场换掉,不先把旧的那句再画一帧。
16
+ */
17
+ export declare function useHeldKey(key: string, ms?: number): string;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 「正在忙」的三个记号,以及它们各管哪里。
3
+ *
4
+ * 分成两个而不是一个,是因为「正在忙」其实是两句话:
5
+ *
6
+ * `StatusSpinner` 说的是**这一条正在跑**。它是某个对象的状态值,出现在一列同族状态记号中间
7
+ * ——上下左右是 ✓、✗、时钟、待办圆点——同屏可能好几个在跑,你是旁观者。任务清单的每一步、
8
+ * 流水线的每一行、工具卡的运行中都是它。
9
+ *
10
+ * `ActionSpinner` 说的是**你按的那下正在回来**。它顶替的是一个刚被按下的动作图标(刷新、保存、
11
+ * 下载、发布),或者填在一个刚被清空的角标位上;同屏通常只有一个,你在等它。按钮上的忙碌
12
+ * 都是它。
13
+ *
14
+ * 判据是可以机械执行的:把这个记号删掉,原地会出现什么。是状态图标就用 `StatusSpinner`,是
15
+ * 一个可点的动作图标(或一个计数)就用 `ActionSpinner`。
16
+ *
17
+ * `BreatheLoader` 只说「这个会话在跑」:侧栏的会话行,和替一个会话报状态的地方(定时任务卡片上那次运行),
18
+ * 那一处问的不是同一个问题,见它自己的注释。
19
+ *
20
+ * 前两个都是 r=10 的描边圆,和 lucide 的 `CheckCircle2`、`XCircle`、`Clock` 精确重合——它们
21
+ * 就是那一列里的邻居。换成星芒之类的别的形状,一列圆里混一个星,每次都会从队列里跳出来一次。
22
+ * 几何和那些数字怎么定的,写在 `@plume/styles` 的 `ui/motion.css` 的加载记号一节。
23
+ */
24
+ /**
25
+ * 一圈虚线,匀速转。
26
+ *
27
+ * 六段等分,所以转过 60° 就回到自身:没有可追踪的端点,眼睛抓不到锚点。这是它敢转、而一段
28
+ * 弧不敢的原因——一段弧有头,十几个同时在屏幕上,每一个都在自己的相位上把视线勾一下。
29
+ *
30
+ * 颜色走 `currentColor`,默认跟着周围的文字走。要它说话大声一点的地方(任务清单里正在跑的
31
+ * 那一步、流水线里排队的那一条)自己传 `text-accent`、`text-warning`。
32
+ */
33
+ export declare function StatusSpinner({ size, className }: {
34
+ size?: number;
35
+ className?: string;
36
+ }): import("react").JSX.Element;
37
+ /**
38
+ * 一段亮弧沿着一圈淡轨道跑。
39
+ *
40
+ * 轨道是这个记号的重点,不是装饰:亮弧单独转的话,图形的轮廓跟着弧一起走,在按钮那个方寸
41
+ * 之间会读成「有东西在里面甩」。垫一圈淡的,形状就恒定是一个完整的圆,动的只有亮处。
42
+ *
43
+ * 轨道浓度走 `--plume-track`,默认 0.18。实心底的按钮(`bg-ink`、`bg-accent`)上 `currentColor`
44
+ * 是底色的反色,0.18 基本看不见,那几处传 `onFill`——见 `ui/motion.css` 里那一档的注释。
45
+ */
46
+ export declare function ActionSpinner({ size, className, onFill, }: {
47
+ size?: number;
48
+ className?: string;
49
+ /** 画在实心底的按钮上(`bg-ink` / `bg-accent`),轨道要更浓才看得见。 */
50
+ onFill?: boolean;
51
+ }): import("react").JSX.Element;
52
+ /**
53
+ * 一圈波纹离开静止的中心,颜色一路走过调色板。
54
+ *
55
+ * 给侧栏的会话行(替一个会话报状态的地方也用它,同一个会话在两处是同一个记号)。那一列可能同时有好几行在跑,而你还要用它读标题——所以这里连「亮处在走」都不
56
+ * 要:什么都不旋转、什么都不位移,余光里它只是缓缓涨落的一团。换成上面那两个的话,一列里并排
57
+ * 三四个各自明灭,读标题时总有东西在旁边闪。
58
+ *
59
+ * 颜色走完 accent → violet 的那 2.4 秒,是它说「跑了多久」的方式:扫一眼知道它活着,
60
+ * 多看一会儿知道它**还**活着,而没有任何东西变快或变响。
61
+ */
62
+ export declare function BreatheLoader({ size, className }: {
63
+ size?: number;
64
+ className?: string;
65
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 动效该不该停住。
3
+ *
4
+ * 放在这里而不是和主题放在一起,因为这是**动画**要问的事,而动画都在 `motion` 里。它只读文档,不读别的——
5
+ * 没有 store、没有设置模块——所以 `@plume/ui` 里的组件用它不必伸手到某个功能里去。
6
+ *
7
+ * 给 CSS 表达不了的那些动画问的:此刻是不是关掉了动效。
8
+ *
9
+ * 样式表自己的动画由全局的 `:root[data-reduce-motion]` 规则管,可一段一步步走过中间字符串的改写是状态,
10
+ * 不是样式——没有时长可以压短,只有帧可以不跑。在要用的那一刻读,不订阅:这些都是一次性的动画,已经开始的
11
+ * 那个可以跑完。
12
+ */
13
+ export declare function motionReduced(): boolean;
@@ -0,0 +1,24 @@
1
+ import { type RefObject } from "react";
2
+ /** 运行行上扫过摘要的那道光,见 `ui/motion.css` 的 `.plume-glide`。 */
3
+ export declare const GLIDE: ReadonlySet<string>;
4
+ /**
5
+ * 没有终点的装饰动画(侧栏的呼吸点、运行行上的扫光)改成按拍走:关键帧和曲线还在 CSS 里,只是
6
+ * 不再由浏览器每帧推,而是暂停住、每拍把 `currentTime` 往前拨一次(`ticker.ts`)。
7
+ *
8
+ * 为什么不留给浏览器:呼吸点动 `border-color` / `background`、扫光动 `background-position`,都只能
9
+ * 在主线程逐帧重绘;120Hz 屏上只要一个会话在跑,整页就每秒重画 120 次,哪怕正文一个字没动。量过:
10
+ * 模型还没出字时 GPU 进程 34%、渲染进程 25%,单关呼吸点降到 25% / 18%,两样都在才降不下去——
11
+ * 和正文那边是同一回事,见 `ticker.ts`。`steps()` 也救不了:浏览器对不能合成的动画每帧都要服务一次,
12
+ * 不看曲线是不是阶梯。
13
+ *
14
+ * 改成只动透明度和缩放、交给合成器也试过(变色换成叠一层 violet 淡入淡出):主线程是不管了,可
15
+ * 合成器照样每个 vsync 出一帧,模型挂住时 GPU 进程 22.6%、渲染进程 11.2%,按拍走是 11.9% / 10.4%。
16
+ * 一秒 120 帧再便宜,也比 30 帧贵。
17
+ *
18
+ * 窗口最小化时停在原处,失焦时照走(跟着拍子降到每秒 10 次)。不在失焦时停:并排摆着的窗口人还看得见,
19
+ * 扫光一定住就像这一轮卡死了。最小化才是真没人看——而主窗口关了 `backgroundThrottling`,页面自己
20
+ * 察觉不到(`visibilityState` 仍是 visible,rAF 照跑 120 帧),只能由主进程告诉它,见 `windowMinimized`。
21
+ *
22
+ * 只认 `names` 里点名的:同一个元素上可能还有要跟手的动画(摘要悬停时的滚动),那些照常逐帧。
23
+ */
24
+ export declare function useTickedAnimations(ref: RefObject<HTMLElement | null>, names: ReadonlySet<string>, active?: boolean): void;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 流式输出期间会动的东西共用的一拍:放字、淡入、数字爬升、思考球。用法和
3
+ * `requestAnimationFrame` 一样,只是回调不在每一帧来,而是约 30 次每秒(窗口最小化时 10 次)、
4
+ * 并且同一拍里的全部一起来。
5
+ *
6
+ * 为什么要一拍:120Hz 屏上,这几样东西各开一个 rAF,只要其中一个这一帧改了页面,整条样式、布局、
7
+ * 绘制、合成就得为这一帧跑一遍。正文其实每秒只长三四十次,剩下的帧全是这几个循环各自撑起来的。
8
+ * 量过:主会话加三个侧边聊天同时输出,渲染进程 105–114%、GPU 53%;把 rAF 合到 30Hz 并停掉
9
+ * CSS 动画后 44% / 17%。只做其中一样只降两成——另一样还在每帧弄脏页面。
10
+ *
11
+ * 同一拍一起跑也是要点:几个面板各自放字、各自淡入,挤进同一个 rAF 回调里,React 把它们的
12
+ * setState 合成一次提交,页面也只脏这一帧。
13
+ *
14
+ * 用户直接操作的动画(拖动、点「回到底部」的那一下滑行)不走这里,它们要跟手。贴底跟随的弹簧也不走:
15
+ * 试过按拍走,视口每四帧才挪一次,量到相邻帧速度差 p95 从 1px 涨到 10.5px,
16
+ * 就是 `useFollowBottom` 专门要避开的那种「一顿一顿」。正文按拍长、视口逐帧追,台阶由弹簧抹平。
17
+ * 折中成最多 60Hz 也试过:每秒只省下约 28ms 主线程(滚动位置更新加悬停命中测试),速度差 p95 照样
18
+ * 涨到 8.5px,不值。
19
+ */
20
+ /** 一拍多长。 */
21
+ export declare const TICK_MS: number;
22
+ /**
23
+ * 窗口是不是最小化了。页面自己察觉不到(`visibilityState` 仍是 visible、rAF 照跑),由产品接主进程的
24
+ * 最小化通知,经 `setWindowMinimized` 喂进来。最小化时拍子放慢,`ticked.ts` 的装饰动画停住,
25
+ * 贴底跟随不滑。
26
+ */
27
+ export declare function windowMinimized(): boolean;
28
+ export declare function setWindowMinimized(value: boolean): void;
29
+ /** 下一拍调用 `callback`,参数和 rAF 一样是帧时间戳。隔了一阵没人要拍时,第一拍就在下一帧。 */
30
+ export declare function requestTick(callback: (now: number) => void): number;
31
+ export declare function cancelTick(id: number): void;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 时长和曲线,给读不到 CSS 变量的代码用。
3
+ *
4
+ * 以 CSS 为准——`@plume/styles` 的 theme.css 定义它们,每张样式表都读那里。这个文件是给少数几个由
5
+ * JavaScript 驱动的动画的:一个要比过渡活得久的 `setTimeout`,一次要缓动字符串的 Web Animations 调用。
6
+ *
7
+ * 一个数写两份恰恰是最会漂开的安排,所以改了一处,另一处必须一起改。
8
+ *
9
+ * 档位按**什么在动**分,不按它有多重要:
10
+ *
11
+ * quick 一个状态,不是一个位置——悬停、按下、手指底下变的颜色
12
+ * base 在移动或改变大小的东西:一个窗格、滑块的把手、一列让出宽度
13
+ * slow 原来不在、现在到来的东西——一段展开
14
+ *
15
+ * 曲线说的是东西往哪个方向去。`out` 减速落定,到来的东西看上去是停稳了而不是被卡住;`in` 是它的镜像,
16
+ * 给离开的东西。
17
+ */
18
+ /** 毫秒。和 `--plume-t-*` 同一组数。 */
19
+ export declare const DURATION: {
20
+ readonly quick: 150;
21
+ readonly base: 220;
22
+ readonly slow: 340;
23
+ };
24
+ /** 和 `--plume-e-*` 同一组字符串。 */
25
+ export declare const EASING: {
26
+ readonly out: "cubic-bezier(0.22, 1, 0.36, 1)";
27
+ readonly in: "cubic-bezier(0.55, 0, 1, 0.45)";
28
+ readonly soft: "cubic-bezier(0.4, 0, 0.2, 1)";
29
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 此刻的时间,`active` 时每 `every` 毫秒重画一次:给秒表、倒计时这类在走的读数用,不走的时候一次也不重画。
3
+ *
4
+ * 变成 `active` 的那一下先对一次表:不对的话,挂上以后过了很久才开始走的读数,头一拍显示的是挂上那一刻。
5
+ */
6
+ export declare function useNow(active: boolean, every: number): number;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * 在拿不回来的事情之前先问一句。
3
+ *
4
+ * 应用里很多东西一次点击就删掉了——插件的目录、模型、MCP 服务、文件、整个会话——而每一个都离你本来
5
+ * 就要点的某个控件只有一次点击的距离。
6
+ *
7
+ * 它们共用一个样子,居中在窗口上、压着遮罩。如果锚在弹出它的控件上(理由是按钮和问题之间的联系值得
8
+ * 保留),实际会在应用的每个角落得到不同的答案:这里是挂在菜单上的卡片,那里是指针旁的卡片,在全屏
9
+ * 打开的面板里,问题出现在那一行碰巧在的位置而不是你正看着的地方。一个让一切停下来的问题就该长成
10
+ * 那个样子,而模态框只有一个该在的地方。
11
+ *
12
+ * 两个入口,一个样子,一个位置:
13
+ *
14
+ * - `useConfirmer()` 给满是删除按钮的页面——包住处理函数,`element` 渲染一次;
15
+ * - `useConfirmGate()` 给要在循环里等回答的地方。
16
+ *
17
+ * 只用于撤销不了的事。归档、停用、取消置顶都能自己放回去,在这些上面确认,等于教人对真正要紧的那些
18
+ * 也一路点过去。
19
+ */
20
+ export interface ConfirmOptions {
21
+ /** 问题,说出是哪个东西。「卸载 Chrome?」——而不是「确定吗?」。 */
22
+ title: string;
23
+ /** 代价是什么,一行。标题已经说全了就省掉。 */
24
+ detail?: React.ReactNode;
25
+ /** 动词,写在做这件事的按钮上。 */
26
+ confirmLabel: string;
27
+ /** 取消按钮上的字,默认「取消」。 */
28
+ cancelLabel?: string;
29
+ /**
30
+ * `danger` 是默认,因为这个东西本来是给删除用的。
31
+ *
32
+ * `normal` 留给另一类问题:不是「这个删了拿不回来」,而是「以后要不要自动做这件事」。
33
+ * 两种都该停下一切来问,但只有前一种该是红的——把每个问题都画成危险,等于没画过危险。
34
+ */
35
+ tone?: "danger" | "normal";
36
+ onConfirm: () => void;
37
+ /**
38
+ * 取消也要做点什么的时候。
39
+ *
40
+ * 绝大多数确认框的取消就是「什么都别发生」,所以这是可选的。但有一种问题不是这样:
41
+ * 「以后要不要自动做这件事」——那里的取消是一个回答(不要),把它当成没问过,
42
+ * 意思就是下次还问。
43
+ */
44
+ onCancel?: () => void;
45
+ /**
46
+ * 同一个动词的另一种做法,比如「删除此会话」旁边的「删除 3 个会话」。
47
+ *
48
+ * 画成次要按钮,放在主按钮左边;有它的时候「取消」挪到最左,三颗按钮不挤成一排。
49
+ */
50
+ alternate?: {
51
+ label: string;
52
+ onConfirm: () => void;
53
+ };
54
+ /** 说明和按钮之间的那一块,比如「不再询问」。大多数问题用不着。 */
55
+ children?: React.ReactNode;
56
+ }
57
+ /**
58
+ * 问题,和两条出路。
59
+ *
60
+ * 焦点特意放在取消上:这个面之所以存在,是因为一件不可逆的事只差一次点击,把键盘放在不可逆的那一半上
61
+ * 等于把问题原样还回去。
62
+ */
63
+ export declare function ConfirmBody({ title, detail, confirmLabel, cancelLabel, tone, onConfirm, onCancel, alternate, children, }: ConfirmOptions & {
64
+ onCancel: () => void;
65
+ }): import("react").JSX.Element;
66
+ /**
67
+ * 放在应用模态面上的问题:居中、压着遮罩、Escape 或点遮罩关掉。
68
+ *
69
+ * 这三样都由 `Overlay` 提供,而且和应用里其它对话框拿到的方式一样——这正是通过它来问、而不是在每个
70
+ * 调用处各拼一个的意义。
71
+ */
72
+ export declare function Confirm({ onCancel, ...options }: ConfirmOptions & {
73
+ onCancel: () => void;
74
+ }): import("react").JSX.Element;
75
+ /**
76
+ * 给满是删除按钮的页面用的一个确认。
77
+ *
78
+ * 每颗按钮交出自己的问题和自己的后果;面、两颗按钮的措辞、取消是安全的那个,这些在这里定。否则一个
79
+ * 有六行可删除内容的页面要带着同一份状态的六个副本。
80
+ */
81
+ export declare function useConfirmer(): {
82
+ /** 从会删除东西的那颗按钮的点击处理里调用。 */
83
+ ask: (options: ConfirmOptions) => void;
84
+ /** 在组件里任意位置渲染一次。 */
85
+ element: import("react").JSX.Element | null;
86
+ };
87
+ /**
88
+ * 同一个问题,可以 await。
89
+ *
90
+ * 给在循环里问的调用方——粘贴五个文件,其中两个重名——回答得先回来,下一步才能定。写成 promise,
91
+ * 读起来就是普通的顺序代码,而不是每个分支一个回调。
92
+ */
93
+ export declare function useConfirmGate(): {
94
+ ask: (options: Omit<ConfirmOptions, "onConfirm">) => Promise<boolean>;
95
+ element: import("react").JSX.Element | null;
96
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 在右键的位置打开的菜单。
3
+ *
4
+ * Electron 没有默认的右键菜单,没有这个的话,在应用里任何地方右键都什么也不发生——文件上、编辑器里、
5
+ * 输入框里都是。`Popover` 已经会把面挂在一个点上而不是元素上;缺的是围绕它的一点约定:菜单是关于
6
+ * 哪个目标的,以及选中任何一行都会关掉它。在这里写一次,文件树、编辑器和普通输入框就不会各走各的。
7
+ */
8
+ import { type PopoverWidth } from "./Popover.tsx";
9
+ /**
10
+ * 记下一次右键:发生的位置,和发生在什么东西上。
11
+ *
12
+ * 目标跟着一起记,因为右键菜单几乎总是关于某一行的,而之后再从事件里读出「哪一行」是不可能的——
13
+ * 菜单渲染时指针早就移走了。带类型,菜单就不会为错误种类的东西搭起来。
14
+ */
15
+ export declare function useContextMenu<T = void>(): {
16
+ anchor: {
17
+ x: number;
18
+ y: number;
19
+ } | null;
20
+ /** 右键之前是 null;渲染菜单前先用它收窄类型。 */
21
+ target: T | null;
22
+ open: boolean;
23
+ show: (event: React.MouseEvent, target: T) => void;
24
+ close: () => void;
25
+ };
26
+ /**
27
+ * 面本身。
28
+ *
29
+ * 每一行都会关掉它,在这里处理而不是每一项各自记得:右键菜单里没有不是动作的行,点完还开着的那个会是
30
+ * 应用里唯一这样的菜单。监听在冒泡阶段,所以行自己的处理已经先运行了。
31
+ */
32
+ export declare function ContextMenu({ anchor, onClose, width, children, }: {
33
+ anchor: {
34
+ x: number;
35
+ y: number;
36
+ } | null;
37
+ onClose: () => void;
38
+ width?: PopoverWidth;
39
+ children: React.ReactNode;
40
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 居中对话框的里面:标题、可选的状态、两端渐隐的正文、按钮。
3
+ *
4
+ * 卡片归 Overlay 管——圆角、遮罩、Escape。各功能自己重搭一遍的话,会发明第二种圆角,在标题和按钮之间
5
+ * 画一道细线,两者读起来就不再是一家。这里只有内边距和几个槽位,不画分隔线。这里的边界是留白。
6
+ */
7
+ import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from "react";
8
+ import { type Dismiss } from "./Overlay.tsx";
9
+ /**
10
+ * 对话框底下的那一颗按钮。上面写着它会做的那件事。
11
+ *
12
+ * **写字,不画图标。** 这些按钮曾经有好几处只放一个 ✕ 和一个 ✓,名字挂在 tooltip 上。工具栏
13
+ * 里的图标按钮可以这么省——周围一排东西替它说明它属于哪一类;对话框底下这两颗没有这个周围,
14
+ * 它们是这次操作的结论本身,一个要说清按下去会发生什么,另一个要说清不按会怎样。一个勾在
15
+ * 「删除会话」「卸载插件」「导入 33 个模型」上长得一模一样,而读出区别的唯一办法是把鼠标停
16
+ * 上去等一个 tooltip——这正是一个「停下一切来问」的界面最不该要求的动作。
17
+ *
18
+ * `label` 留着,但只当 tooltip 用:可见的字已经是它的名字了。
19
+ */
20
+ export declare function DialogAction({ children, onClick, tone, disabled, autoFocus, label, className, ...rest }: {
21
+ children: ReactNode;
22
+ onClick?: () => void;
23
+ tone?: "secondary" | "primary" | "danger";
24
+ disabled?: boolean;
25
+ autoFocus?: boolean;
26
+ /** 只当悬停提示。可见的字已经是按钮的名字。 */
27
+ label?: string;
28
+ className?: string;
29
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "onClick" | "type">): import("react").JSX.Element;
30
+ export declare function DialogFrame({ title, icon, detail, status, children, actions, height, bodyClassName, className, ...rest }: {
31
+ title: ReactNode;
32
+ icon?: ReactNode;
33
+ detail?: ReactNode;
34
+ /** 放在正文里、滚动区上方——进度、警告,任何不能被滚走的东西。 */
35
+ status?: ReactNode;
36
+ children?: ReactNode;
37
+ actions: ReactNode;
38
+ height?: number;
39
+ /**
40
+ * 滚动的正文最高能长到多高。只给是表单而不是问题的对话框用——默认值按一段话加一个列表定的,
41
+ * 设置表单放在它下面一次只能滚出三个字段。
42
+ */
43
+ bodyClassName?: string;
44
+ className?: string;
45
+ } & Omit<HTMLAttributes<HTMLDivElement>, "title" | "children">): import("react").JSX.Element;
46
+ /**
47
+ * 里面放着 `DialogFrame` 的 `Overlay`。
48
+ *
49
+ * `actions` 和 `children` 可以是 `dismiss` 的函数,关对话框的按钮应该用它:`dismiss()` 播完退场再运行
50
+ * `onClose`,`dismiss(after)` 改为运行 `after`。按钮直接调用 `onClose` 会在那一帧卸掉对话框——那样
51
+ * 只有 Escape 和点遮罩是怎么来的就怎么走。
52
+ */
53
+ export declare function Dialog({ onClose, width, label, returnFocus, actions, children, ...frame }: {
54
+ onClose: () => void;
55
+ width?: number;
56
+ label?: string;
57
+ returnFocus?: HTMLElement;
58
+ actions: ReactNode | ((dismiss: Dismiss) => ReactNode);
59
+ children?: ReactNode | ((dismiss: Dismiss) => ReactNode);
60
+ } & Omit<Parameters<typeof DialogFrame>[0], "actions" | "children">): import("react").JSX.Element;