@plumeai/plugin-sdk 0.0.0-stage → 0.1.2
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/LICENSE +21 -0
- package/bin/plume-plugin.mjs +70 -0
- package/dist/client/styles/src/index.d.ts +123 -0
- package/dist/client/ui/src/avatar/AgentAvatar.d.ts +42 -0
- package/dist/client/ui/src/avatar/AvatarPile.d.ts +36 -0
- package/dist/client/ui/src/avatar/AvatarStack.d.ts +26 -0
- package/dist/client/ui/src/avatar/art.d.ts +32 -0
- package/dist/client/ui/src/fileIcon.d.ts +33 -0
- package/dist/client/ui/src/hooks/useCopied.d.ts +16 -0
- package/dist/client/ui/src/hooks/useLiveRefresh.d.ts +22 -0
- package/dist/client/ui/src/hooks/useNarrow.d.ts +16 -0
- package/dist/client/ui/src/i18n/context.d.ts +17 -0
- package/dist/client/ui/src/i18n/index.d.ts +2 -0
- package/dist/client/ui/src/i18n/list.d.ts +20 -0
- package/dist/client/ui/src/i18n/locales.d.ts +10 -0
- package/dist/client/ui/src/i18n/messages/en.d.ts +1418 -0
- package/dist/client/ui/src/i18n/messages/index.d.ts +6 -0
- package/dist/client/ui/src/i18n/messages/zh-CN.d.ts +1263 -0
- package/dist/client/ui/src/i18n/plural.d.ts +16 -0
- package/dist/client/ui/src/i18n/translate.d.ts +43 -0
- package/dist/client/ui/src/icons/index.d.ts +5 -0
- package/dist/client/ui/src/image/AnnotateCanvas.d.ts +29 -0
- package/dist/client/ui/src/image/AnnotateToolbar.d.ts +73 -0
- package/dist/client/ui/src/image/Annotator.d.ts +154 -0
- package/dist/client/ui/src/image/annotate.d.ts +227 -0
- package/dist/client/ui/src/image/paint.d.ts +35 -0
- package/dist/client/ui/src/image/screenshot-geometry.d.ts +112 -0
- package/dist/client/ui/src/image/useBarDrag.d.ts +31 -0
- package/dist/client/ui/src/image/useMovableBar.d.ts +26 -0
- package/dist/client/ui/src/image/useToolbarPlacement.d.ts +42 -0
- package/dist/client/ui/src/index.d.ts +140 -0
- package/dist/client/ui/src/inputs/ColorField.d.ts +9 -0
- package/dist/client/ui/src/inputs/ComposerToggle.d.ts +23 -0
- package/dist/client/ui/src/inputs/DateRangeField.d.ts +25 -0
- package/dist/client/ui/src/inputs/NativeField.d.ts +5 -0
- package/dist/client/ui/src/inputs/SearchField.d.ts +21 -0
- package/dist/client/ui/src/inputs/Segmented.d.ts +23 -0
- package/dist/client/ui/src/inputs/Select.d.ts +32 -0
- package/dist/client/ui/src/inputs/ShortcutRecorder.d.ts +8 -0
- package/dist/client/ui/src/inputs/Slider.d.ts +13 -0
- package/dist/client/ui/src/inputs/TextArea.d.ts +30 -0
- package/dist/client/ui/src/inputs/Toggle.d.ts +10 -0
- package/dist/client/ui/src/inputs/WorktreeToggle.d.ts +19 -0
- package/dist/client/ui/src/inputs/day-range.d.ts +57 -0
- package/dist/client/ui/src/inputs/pickers.d.ts +40 -0
- package/dist/client/ui/src/inputs/useFieldFade.d.ts +1 -0
- package/dist/client/ui/src/keyboard.d.ts +21 -0
- package/dist/client/ui/src/layout/ApprovalFrame.d.ts +33 -0
- package/dist/client/ui/src/layout/Collapse.d.ts +9 -0
- package/dist/client/ui/src/layout/CopyMark.d.ts +19 -0
- package/dist/client/ui/src/layout/Disclosure.d.ts +66 -0
- package/dist/client/ui/src/layout/ErrorBoundary.d.ts +26 -0
- package/dist/client/ui/src/layout/PageTopRow.d.ts +19 -0
- package/dist/client/ui/src/layout/PanelEmpty.d.ts +17 -0
- package/dist/client/ui/src/layout/ResizeHandle.d.ts +24 -0
- package/dist/client/ui/src/layout/RetainedViews.d.ts +32 -0
- package/dist/client/ui/src/layout/Settings.d.ts +41 -0
- package/dist/client/ui/src/layout/Splitter.d.ts +25 -0
- package/dist/client/ui/src/lib/agent-avatar.d.ts +58 -0
- package/dist/client/ui/src/lib/code/font-stack.d.ts +12 -0
- package/dist/client/ui/src/lib/code/themes.d.ts +35 -0
- package/dist/client/ui/src/lib/date-format.d.ts +8 -0
- package/dist/client/ui/src/lib/dispatches.d.ts +8 -0
- package/dist/client/ui/src/lib/hour-style.d.ts +13 -0
- package/dist/client/ui/src/lib/number-draft.d.ts +24 -0
- package/dist/client/ui/src/lib/relative-time.d.ts +18 -0
- package/dist/client/ui/src/lib/tiling.d.ts +89 -0
- package/dist/client/ui/src/lib/typing.d.ts +19 -0
- package/dist/client/ui/src/motion/RollWords.d.ts +26 -0
- package/dist/client/ui/src/motion/RollingText.d.ts +43 -0
- package/dist/client/ui/src/motion/TypedText.d.ts +9 -0
- package/dist/client/ui/src/motion/freeze.d.ts +22 -0
- package/dist/client/ui/src/motion/held.d.ts +17 -0
- package/dist/client/ui/src/motion/loaders.d.ts +65 -0
- package/dist/client/ui/src/motion/reduced.d.ts +13 -0
- package/dist/client/ui/src/motion/ticked.d.ts +24 -0
- package/dist/client/ui/src/motion/ticker.d.ts +31 -0
- package/dist/client/ui/src/motion/tokens.d.ts +29 -0
- package/dist/client/ui/src/motion/useNow.d.ts +6 -0
- package/dist/client/ui/src/overlay/Confirm.d.ts +96 -0
- package/dist/client/ui/src/overlay/ContextMenu.d.ts +40 -0
- package/dist/client/ui/src/overlay/Dialog.d.ts +60 -0
- package/dist/client/ui/src/overlay/Menu.d.ts +90 -0
- package/dist/client/ui/src/overlay/Overlay.d.ts +17 -0
- package/dist/client/ui/src/overlay/Popover.d.ts +127 -0
- package/dist/client/ui/src/overlay/Tooltip.d.ts +14 -0
- package/dist/client/ui/src/overlay/afterimage.d.ts +20 -0
- package/dist/client/ui/src/overlay/chrome-top.d.ts +8 -0
- package/dist/client/ui/src/overlay/hover-layers.d.ts +41 -0
- package/dist/client/ui/src/overlay/portal.d.ts +21 -0
- package/dist/client/ui/src/overlay/scrims.d.ts +20 -0
- package/dist/client/ui/src/overlay/tooltip-attribute.d.ts +62 -0
- package/dist/client/ui/src/primitives/Button.d.ts +64 -0
- package/dist/client/ui/src/primitives/Caret.d.ts +25 -0
- package/dist/client/ui/src/primitives/ChoiceMark.d.ts +12 -0
- package/dist/client/ui/src/primitives/ClosableTab.d.ts +23 -0
- package/dist/client/ui/src/primitives/CountUp.d.ts +21 -0
- package/dist/client/ui/src/primitives/GitHubMark.d.ts +12 -0
- package/dist/client/ui/src/primitives/IconButton.d.ts +55 -0
- package/dist/client/ui/src/primitives/MarkNumber.d.ts +12 -0
- package/dist/client/ui/src/primitives/RowDeleteButton.d.ts +6 -0
- package/dist/client/ui/src/primitives/Skeleton.d.ts +36 -0
- package/dist/client/ui/src/primitives/TabStrip.d.ts +29 -0
- package/dist/client/ui/src/primitives/Text.d.ts +341 -0
- package/dist/client/ui/src/primitives/TimeAgo.d.ts +13 -0
- package/dist/client/ui/src/primitives/useCountUp.d.ts +23 -0
- package/dist/client/ui/src/row/FlowRow.d.ts +31 -0
- package/dist/client/ui/src/row/HoverRow.d.ts +28 -0
- package/dist/client/ui/src/scroll/BackToLatest.d.ts +19 -0
- package/dist/client/ui/src/scroll/OverlayScrollbar.d.ts +9 -0
- package/dist/client/ui/src/scroll/ScrollText.d.ts +24 -0
- package/dist/client/ui/src/scroll/Scroller.d.ts +66 -0
- package/dist/client/ui/src/scroll/Sideways.d.ts +30 -0
- package/dist/client/ui/src/scroll/fade.d.ts +2 -0
- package/dist/client/ui/src/scroll/follow.d.ts +157 -0
- package/dist/client/ui/src/scroll/measure-batch.d.ts +13 -0
- package/dist/client/ui/src/scroll/memory.d.ts +22 -0
- package/dist/client/ui/src/scroll/signature.d.ts +24 -0
- package/dist/client/ui/src/scroll/useFollowBottom.d.ts +80 -0
- package/dist/client/ui/src/scroll/useSideways.d.ts +29 -0
- package/dist/contract/src/app.d.ts +16 -0
- package/dist/contract/src/changes.d.ts +50 -0
- package/dist/contract/src/diagnostics.d.ts +86 -0
- package/dist/contract/src/index.d.ts +18 -0
- package/dist/contract/src/plugin.d.ts +1391 -0
- package/dist/contract/src/resources.d.ts +79 -0
- package/dist/contract/src/service.d.ts +806 -0
- package/dist/contract/src/ui.d.ts +1039 -0
- package/dist/contract/src/usage.d.ts +102 -0
- package/dist/core/llm/ai/anthropic-messages-request.d.ts +82 -0
- package/dist/core/llm/ai/anthropic-messages.d.ts +43 -0
- package/dist/core/llm/ai/cache-routing.d.ts +53 -0
- package/dist/core/llm/ai/chat-delta.d.ts +107 -0
- package/dist/core/llm/ai/compat-key.d.ts +19 -0
- package/dist/core/llm/ai/endpoint.d.ts +57 -0
- package/dist/core/llm/ai/failure.d.ts +181 -0
- package/dist/core/llm/ai/index.d.ts +16 -0
- package/dist/core/llm/ai/openai-chat-completions-request.d.ts +49 -0
- package/dist/core/llm/ai/openai-chat-completions.d.ts +37 -0
- package/dist/core/llm/ai/openai-responses-request.d.ts +63 -0
- package/dist/core/llm/ai/openai-responses.d.ts +11 -0
- package/dist/core/llm/ai/prefix-fingerprint.d.ts +20 -0
- package/dist/core/llm/ai/reasoning-compat.d.ts +69 -0
- package/dist/core/llm/ai/request-params-compat.d.ts +39 -0
- package/dist/core/llm/ai/retry.d.ts +130 -0
- package/dist/core/llm/ai/sanitize-history.d.ts +23 -0
- package/dist/core/llm/ai/think-tag.d.ts +37 -0
- package/dist/core/llm/ai/thinking-options.d.ts +35 -0
- package/dist/core/llm/ai/tool-names.d.ts +17 -0
- package/dist/core/llm/ai/tool-pairing-compat.d.ts +53 -0
- package/dist/core/llm/ai/tool-result-images-compat.d.ts +24 -0
- package/dist/core/llm/ai/tool-schema.d.ts +20 -0
- package/dist/core/llm/ai/usage-fields.d.ts +30 -0
- package/dist/core/llm/ai/vendors/index.d.ts +20 -0
- package/dist/core/llm/ai/vendors/thinking.d.ts +39 -0
- package/dist/core/llm/ai/vendors/types.d.ts +47 -0
- package/dist/core/llm/config/image-models.d.ts +34 -0
- package/dist/core/llm/config/retry-policy.d.ts +35 -0
- package/dist/core/llm/images/chat-images.d.ts +11 -0
- package/dist/core/llm/images/dimensions.d.ts +15 -0
- package/dist/core/llm/images/generate.d.ts +15 -0
- package/dist/core/llm/images/openai-images.d.ts +11 -0
- package/dist/core/llm/images/quota.d.ts +9 -0
- package/dist/core/llm/images/shape.d.ts +44 -0
- package/dist/core/llm/images/types.d.ts +118 -0
- package/dist/core/llm/model-catalog-format.d.ts +50 -0
- package/dist/core/llm/model-catalog.d.ts +51 -0
- package/dist/core/llm/types/message.d.ts +450 -0
- package/dist/core/llm/types/provider.d.ts +169 -0
- package/dist/core/llm/types/tool.d.ts +23 -0
- package/dist/core/llm/types.d.ts +10 -0
- package/dist/core/llm/utils/pricing.d.ts +18 -0
- package/dist/core/llm/utils/record.d.ts +2 -0
- package/dist/core/llm/utils/sse.d.ts +69 -0
- package/dist/infra/rpc/src/endpoint.d.ts +36 -0
- package/dist/infra/rpc/src/index.d.ts +2 -0
- package/dist/infra/rpc/src/rpc.d.ts +54 -0
- package/dist/theme.css +336 -0
- package/dist/ui.d.ts +2 -0
- package/lib/build.mjs +143 -0
- package/lib/check.mjs +23 -0
- package/lib/dev.mjs +52 -0
- package/lib/icons.mjs +2 -0
- package/lib/init.mjs +109 -0
- package/lib/install.mjs +80 -0
- package/lib/link.mjs +44 -0
- package/lib/lint/i18n.mjs +149 -0
- package/lib/lint/imports.mjs +83 -0
- package/lib/lint/index.mjs +54 -0
- package/lib/lint/styles.mjs +160 -0
- package/lib/manifest.d.mts +9 -0
- package/lib/manifest.mjs +99 -0
- package/lib/targets.mjs +60 -0
- package/package.json +34 -4
- package/skill/SKILL.md +150 -0
- package/skill/references/components.md +2830 -0
- package/skill/references/logic.md +526 -0
- package/skill/references/style-i18n.md +70 -0
- package/skill/references/ui.md +532 -0
- package/template/AGENTS.md +17 -0
- package/template/CLAUDE.md +1 -0
- package/template/README.md +12 -0
- package/template/gitignore +2 -0
- package/template/src/index.ts +28 -0
- package/template/src/messages.ts +16 -0
- package/template/src/types.ts +8 -0
- package/template/src/ui.tsx +30 -0
- package/template/tsconfig.json +7 -0
- package/tsconfig.json +25 -0
- package/README.md +0 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 挑数字、挑时间的控件。
|
|
3
|
+
*
|
|
4
|
+
* 它们各自替掉一个由平台来画的 `<input>`:数字框的上下箭头、时间框的时钟。样式够不着这些部件,于是它们会以系统挑的
|
|
5
|
+
* 形状和颜色,出现在一排自己画的控件旁边。所以留下原生元素的行为和无障碍,看得见的部分自己画。
|
|
6
|
+
*/
|
|
7
|
+
import { type JSX } from "react";
|
|
8
|
+
/**
|
|
9
|
+
* 带自己画的步进按钮的数字框。
|
|
10
|
+
*
|
|
11
|
+
* 用 `type="text"` 加数字键盘提示,不用 `type="number"`:后者的上下箭头每个浏览器画得都不一样,而且它认为不合法的
|
|
12
|
+
* 输入一律报成空字符串,`1e5`、`--3` 看着像收下了,到手却是「什么也没敲」。
|
|
13
|
+
*
|
|
14
|
+
* 存的值不是每敲一下就改:聚焦时框里留一份草稿,下限是 11 时「1」才能留到变成「16」。永远到不了范围内的字符进不来,
|
|
15
|
+
* 加减按钮停在同样的边界上。拒掉的按键不提示。
|
|
16
|
+
*/
|
|
17
|
+
export declare function NumberField({ value, onChange, min, max, step, width, label, name, }: {
|
|
18
|
+
value: number;
|
|
19
|
+
onChange: (value: number) => void;
|
|
20
|
+
min?: number;
|
|
21
|
+
max?: number;
|
|
22
|
+
step?: number;
|
|
23
|
+
width?: number;
|
|
24
|
+
label: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
}): JSX.Element;
|
|
27
|
+
/**
|
|
28
|
+
* 时间,用两个列表挑,不用浏览器的时钟。
|
|
29
|
+
*
|
|
30
|
+
* `<input type="time">` 的分段、分隔符和弹出的面板都归平台:macOS 上是步进器,Windows 上是下拉。它还按系统区域解析和
|
|
31
|
+
* 显示,同一个任务在一台机器上读作 `09:00`,在另一台上读作 `9:00 AM`,存的却是同一串字。
|
|
32
|
+
*
|
|
33
|
+
* 两个列表把这些都去掉,顺便去掉了打字:要的只是某个小时的某一分,00:00–23:59 之外没有别的值要表达。
|
|
34
|
+
*/
|
|
35
|
+
export declare function TimeField({ value, onChange, label, }: {
|
|
36
|
+
/** `HH:mm`,24 小时制。 */
|
|
37
|
+
value: string;
|
|
38
|
+
onChange: (value: string) => void;
|
|
39
|
+
label: string;
|
|
40
|
+
}): JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useFieldFade(field: React.RefObject<HTMLElement | null>, host: React.RefObject<HTMLElement | null>): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 快捷键的写法按本机键盘来。 */
|
|
2
|
+
export declare function macKeyboard(platform?: string): boolean;
|
|
3
|
+
/** 界面文案一律用紧凑的 Mac 写法;别的键盘要把修饰键写成名字。 */
|
|
4
|
+
export declare function shortcutLabel(text: string, platform?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* 快捷键按的是哪个字母:键帽上印的那个。
|
|
7
|
+
*
|
|
8
|
+
* `key` 是拉丁字母时用 `key`。QWERTY、AZERTY、QWERTZ、Dvorak 上它就是键帽上的字母,也就是快捷键的
|
|
9
|
+
* 写法;改用 `code` 匹配的话,AZERTY 的 Ctrl+Alt+A 会变成印着 Q 的那个键,Dvorak 的 Ctrl+B 变成印着 X 的。
|
|
10
|
+
*
|
|
11
|
+
* 否则用 `code`。没有拉丁字母的布局(俄语、希腊语、希伯来语)没有印着 A 的键可按,用户会去按 A 所在
|
|
12
|
+
* 位置的那个键——浏览器自己的快捷键和 CodeMirror 的键位表都是这样兜底的。macOS 的 Option 也落到这里:
|
|
13
|
+
* 它是死键修饰,⌥S 到达时是「ß」,只有位置还说明它是 S。
|
|
14
|
+
*/
|
|
15
|
+
export declare function shortcutLetter(event: Pick<KeyboardEvent, "key" | "code">): string | null;
|
|
16
|
+
/** 把 Electron 的 accelerator 写成按键文字,不把 Control、Command 和 Windows 键混为一谈。 */
|
|
17
|
+
export declare function acceleratorLabel(accelerator: string, platform?: string): string;
|
|
18
|
+
export declare function markComposition(target: EventTarget, active: boolean): void;
|
|
19
|
+
/** 这些键归输入法和 AltGr;当成命令处理的话,打字打到一半就切了窗格。 */
|
|
20
|
+
export declare function composingKey(event: KeyboardEvent): boolean;
|
|
21
|
+
export declare function recordAccelerator(event: KeyboardEvent, platform?: string): string | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 审批卡的外框:压在输入框正上方的那块玻璃。标题栏整条是收放的按钮,不只是右端那颗箭头:点在标题上也能收起,
|
|
3
|
+
* 键盘也落得到;收起时只剩一行,想先往上看看上下文也不用答。
|
|
4
|
+
*
|
|
5
|
+
* 产品的通用审批卡和插件画的提问卡共用它,同一个位置上的卡片长一个样;正文和按钮放在 `children` 里,跟着一起收。
|
|
6
|
+
* 标题栏右边依次是类型小标签、倒计时(`ApprovalExpiry`)和后面还排着几张(+N)。
|
|
7
|
+
*/
|
|
8
|
+
import { type ReactNode } from "react";
|
|
9
|
+
/**
|
|
10
|
+
* 这张卡还剩多久失效,每秒走一格(「4:59 后失效」)。到期没人答,本体按拒绝收场:不说出来的截止比没有截止更糟,
|
|
11
|
+
* 人回来时这一轮已经被一个没见过的「不」结束了。
|
|
12
|
+
*
|
|
13
|
+
* 单独一个组件,秒针走动不重画旁边正在打字的表单。走到零就不说了:正常情况下卡片这一刻已经收走,留下的只可能是
|
|
14
|
+
* 一份过时的快照,「0:00 后失效」不该出现。
|
|
15
|
+
*/
|
|
16
|
+
export declare function ApprovalExpiry({ at }: {
|
|
17
|
+
at: number;
|
|
18
|
+
}): import("react").JSX.Element | null;
|
|
19
|
+
export declare function ApprovalFrame({ requestId, icon, title, kind, expiresAt, queued, children, }: {
|
|
20
|
+
/** 这次请求的 id(`toolCallId`):换了一张卡,收起状态不带过去。 */
|
|
21
|
+
requestId: string;
|
|
22
|
+
/** 标题前 15px 的图标:权限请求是警告,提问是气泡。 */
|
|
23
|
+
icon: ReactNode;
|
|
24
|
+
title: ReactNode;
|
|
25
|
+
/** 类型小标签(「执行命令」);提问这类不是权限的不写。 */
|
|
26
|
+
kind?: string;
|
|
27
|
+
/** `ApprovalRequest.expiresAt`,有就画倒计时。 */
|
|
28
|
+
expiresAt?: number | undefined;
|
|
29
|
+
/** 排在这张后面还在等的张数,大于 0 时写 +N。 */
|
|
30
|
+
queued?: number;
|
|
31
|
+
/** 正文和按钮,收起时一起收。 */
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/** 收起时的内容留到尺寸过渡走完,再放掉开销大的子树。 */
|
|
3
|
+
export declare function Collapse({ open, children, bodyClassName, className, keepMounted, }: {
|
|
4
|
+
open: boolean;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
bodyClassName?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
keepMounted?: boolean;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一枚贴在框角上的复制键,鼠标进来才出现。
|
|
3
|
+
*
|
|
4
|
+
* 给那些「内容本身就是要拿去别处用」的框:一段报错、一份组件栈、一块代码。这些东西的下一步几乎
|
|
5
|
+
* 总是粘贴到别的地方去,而手动框选一段会滚动的等宽文本是这件事里最容易出错的一步——选多了、选少
|
|
6
|
+
* 了、漏了最后一行,而漏掉的那一行往往正是有用的那一行。
|
|
7
|
+
*
|
|
8
|
+
* 平时不画:一个常驻的按钮压在内容上,每一次阅读都要绕过它一次。鼠标进了这个框才是「打算对它做
|
|
9
|
+
* 点什么」的时刻,那时它再出现。
|
|
10
|
+
*
|
|
11
|
+
* 按下之后变成一个对钩,一秒多之后变回来(`useCopied`)。
|
|
12
|
+
*
|
|
13
|
+
* 用它的框自己要是 `relative` 且带 `group/copy`,并且给这一角留出位置(内容那侧补内边距),
|
|
14
|
+
* 否则它会压在第一行字上。
|
|
15
|
+
*/
|
|
16
|
+
export declare function CopyMark({ text, side }: {
|
|
17
|
+
text: string;
|
|
18
|
+
side?: "left" | "right";
|
|
19
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一段能折起来的内容,以及它长什么样的唯一定义处。
|
|
3
|
+
*
|
|
4
|
+
* 同一件事可以有好几种写法:`▾` 字符换成 `▸`、一个时有时无的箭头、一块直接渲染或不渲染的内容。三种读起来
|
|
5
|
+
* 都像不同的机制,而不是同一个意思;字符那种最糟——字形按字体自己高兴的粗细画,还不能旋转,于是展开是一次
|
|
6
|
+
* 替换而不是一个动作。
|
|
7
|
+
*
|
|
8
|
+
* 浏览器自己的 `<details>` 也不行:它按平台的大小和粗细画一枚系统三角,没有过渡地一下弹开,点击区域只在
|
|
9
|
+
* 标记那十一个像素上。和页面上其他东西放在一起,它像是从另一个应用里贴过来的。
|
|
10
|
+
*
|
|
11
|
+
* 这里定下来的:
|
|
12
|
+
*
|
|
13
|
+
* - 箭头旋转而不是被替换,状态是同一个东西的两个位置;
|
|
14
|
+
* - 内容展开到它自己的高度(`plume-reveal`),收起和展开是同一个手势,而不是一刀切;
|
|
15
|
+
* - 标题是一个盖住整行的真按钮,点击区域是这一行,而不是箭头那十一个像素;
|
|
16
|
+
* - 计数跟在标题旁边而不是写进标题里,因为「活动 3」是一个标题加一个数量,不是一个五个字的标题。
|
|
17
|
+
*/
|
|
18
|
+
import { type ReactNode } from "react";
|
|
19
|
+
/**
|
|
20
|
+
* 同一种折叠的三种摆法。
|
|
21
|
+
*
|
|
22
|
+
* `section` 是上面带一条线的标题,给详情视图里的各个部分;`compact` 是行内的一句,没有自己的外框;`framed`
|
|
23
|
+
* 是正文流里的一个框——README 里 `<details>` 的样子,也是表单底部「高级」那一块。
|
|
24
|
+
*/
|
|
25
|
+
declare const LOOK: {
|
|
26
|
+
readonly section: {
|
|
27
|
+
readonly root: "border-t border-line-soft first:border-t-0";
|
|
28
|
+
readonly head: "";
|
|
29
|
+
readonly button: "py-2.5";
|
|
30
|
+
readonly title: "text-label font-medium";
|
|
31
|
+
readonly body: "pb-3";
|
|
32
|
+
};
|
|
33
|
+
readonly compact: {
|
|
34
|
+
readonly root: "";
|
|
35
|
+
readonly head: "";
|
|
36
|
+
readonly button: "py-1";
|
|
37
|
+
readonly title: "text-detail";
|
|
38
|
+
readonly body: "pl-3.5";
|
|
39
|
+
};
|
|
40
|
+
readonly framed: {
|
|
41
|
+
readonly root: "overflow-hidden rounded-lg border border-line-soft";
|
|
42
|
+
readonly head: "pr-3";
|
|
43
|
+
readonly button: "py-2 pl-3";
|
|
44
|
+
readonly title: "";
|
|
45
|
+
readonly body: "px-3 pb-3";
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
type Control = {
|
|
49
|
+
open: boolean;
|
|
50
|
+
onToggle: () => void;
|
|
51
|
+
defaultOpen?: never;
|
|
52
|
+
} | {
|
|
53
|
+
open?: never;
|
|
54
|
+
onToggle?: never;
|
|
55
|
+
defaultOpen?: boolean;
|
|
56
|
+
};
|
|
57
|
+
export declare function Disclosure({ title, count, trailing, children, variant, ...control }: {
|
|
58
|
+
title: ReactNode;
|
|
59
|
+
/** 显示在标题后面。零值得说;undefined 不说。 */
|
|
60
|
+
count?: number;
|
|
61
|
+
/** 属于这一段而不是它的内容的控件——一个编辑按钮、一个链接。 */
|
|
62
|
+
trailing?: ReactNode;
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
variant?: keyof typeof LOOK;
|
|
65
|
+
} & Control): import("react").JSX.Element;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 抛出的错误和一扇灰窗口之间的最后一道。
|
|
3
|
+
*
|
|
4
|
+
* 错误一路没被接住到了根上,React 会卸掉整棵树,于是一个组件抛错就带走整个应用——剩下的只有窗口底色和三个
|
|
5
|
+
* 红绿灯。没有消息、没有栈、没有能做的事;从外面看,它和卡死、构建失败、主进程崩溃分不出来。
|
|
6
|
+
*
|
|
7
|
+
* 它不会让本来不工作的东西工作起来。它让失败读得懂:什么抛的、在哪,以及唯一值得给的那个动作——重新加载
|
|
8
|
+
* 渲染进程。在桌面应用里这是真的恢复:主进程、会话、设置都还活在 IPC 边界的另一边,只有这扇窗口要重建。
|
|
9
|
+
*
|
|
10
|
+
* 用 class,因为 `getDerivedStateFromError` 没有对应的 hook。这是唯一的理由。
|
|
11
|
+
*/
|
|
12
|
+
import { Component, type ErrorInfo, type ReactNode } from "react";
|
|
13
|
+
interface State {
|
|
14
|
+
error: Error | null;
|
|
15
|
+
/** React 自己记下的是哪个组件抛的,调用栈不告诉你这个。 */
|
|
16
|
+
componentStack: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare class ErrorBoundary extends Component<{
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}, State> {
|
|
21
|
+
state: State;
|
|
22
|
+
static getDerivedStateFromError(error: Error): Partial<State>;
|
|
23
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
24
|
+
render(): ReactNode;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode, Ref } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* 自己画顶行的页面(`ui.page` 给了 `topRow: true`)每一栏最上面那一行:坐在窗口顶行的高度上,和侧栏顶上那一行齐平。
|
|
4
|
+
*
|
|
5
|
+
* 整行拖得动窗口、双击能缩放;行里能点的控件(按钮、链接、输入框)自动挖成不拖动的,不用一个个标。不给整行
|
|
6
|
+
* no-drag:那样这一栏宽的一段就既拖不动窗口、也双击不了。Windows、Linux 上窗口顶上另有一条拖窗口的带子,宿主在根元素上
|
|
7
|
+
* 标 `data-plume-window-header`,这一行跟着改成不拖动(`app-region` 不认 `var()`,只能按选择器切):在卡片里拖窗口会带上系统标题栏的行为(右键系统菜单、拖到屏幕边贴边)。
|
|
8
|
+
*
|
|
9
|
+
* `start` 是贴着页面左边的那一栏:侧栏收起时红绿灯和前进、后退浮在这里,左边让出它们的宽度(宿主经
|
|
10
|
+
* `--plume-top-row-inset` 给,侧栏开着时是 0)。两栏页面的右栏在窄窗口里换成整页时,也给 `start`。
|
|
11
|
+
*
|
|
12
|
+
* 高度、内边距之外的排法(间距、两端对齐)由 `className` 补;行里不折行,放不下的东西自己截断。
|
|
13
|
+
*/
|
|
14
|
+
export declare function PageTopRow({ start, className, children, ...rest }: {
|
|
15
|
+
start?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
ref?: Ref<HTMLElement>;
|
|
19
|
+
} & HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LucideIcon } from "../icons/index.ts";
|
|
2
|
+
/**
|
|
3
|
+
* 空面板正文的中间。
|
|
4
|
+
*
|
|
5
|
+
* 居中的图标、名字、一句话说这是什么。每一种标签页都是同一个形状,面板读起来是一个东西装着几种内容,
|
|
6
|
+
* 而不是碰巧共用一个框的几块互不相干的屏。
|
|
7
|
+
*
|
|
8
|
+
* 单独一个文件,因为面板外壳和它里面的东西都要用它,由外壳导出的话两边会互相 import。
|
|
9
|
+
*/
|
|
10
|
+
export declare function PanelEmpty({ icon: Icon, art, title, children, }: {
|
|
11
|
+
icon: LucideIcon;
|
|
12
|
+
/** 画在图标的位置上、比一枚线性图标更能说明这里该有什么的东西——子智能体面板放的是几张睡着的脸。 */
|
|
13
|
+
art?: React.ReactNode;
|
|
14
|
+
title: string;
|
|
15
|
+
/** 可省:有些空状态的标题已经把话说完了,底下再补一句就是在解释一个不需要解释的东西。 */
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 窗格能拖的那条边。
|
|
3
|
+
*
|
|
4
|
+
* 出现的是指针处的一小段握把,不是沿整条边的一道线。整高的线读起来是边框——布局里永久的一部分——而它要说的
|
|
5
|
+
* 是「这一处可以拖」。跟着指针走的握把只说这一件事,边界看起来也不会因为你碰巧靠近而变样。
|
|
6
|
+
*
|
|
7
|
+
* 抓取区跨在边界上,几乎全在邻居那一侧,这样才离窗格里的滚动条远——见 `INSIDE`。渲染它的地方要给它一个
|
|
8
|
+
* 不裁切的定位上下文:窗格会裁掉自己的溢出,悬在窗格外面的拖把会直接被切掉。所以用它的地方要在窗格外面
|
|
9
|
+
* 再包一层框。
|
|
10
|
+
*
|
|
11
|
+
* 报告的是从拖动开始处算出的绝对宽度,不是增量。每次 mousemove 累加增量会把夹紧误差攒起来:拖过最小值
|
|
12
|
+
* 再拖回来,窗格就少了你拖过头的那一截。
|
|
13
|
+
*/
|
|
14
|
+
export declare function ResizeHandle({ edge, width, min, max, onResize, onReset, label, }: {
|
|
15
|
+
/** 在窗格的哪一边:左边的窗格是 `end`,右边的是 `start`。 */
|
|
16
|
+
edge: "start" | "end";
|
|
17
|
+
width: number;
|
|
18
|
+
min: number;
|
|
19
|
+
max: number;
|
|
20
|
+
onResize: (next: number) => void;
|
|
21
|
+
/** 双击恢复默认。 */
|
|
22
|
+
onReset?: () => void;
|
|
23
|
+
label: string;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** 留住少数几个看过的页面;藏起来的页面暂停 effect,保留局部状态。 */
|
|
2
|
+
export declare function RetainedViews<T extends string>({ active, render, limit, pageClassName, slide, }: {
|
|
3
|
+
active: T;
|
|
4
|
+
render: (key: T) => React.ReactNode;
|
|
5
|
+
limit?: number;
|
|
6
|
+
/** 到达时的类。不同的页面可以换一种更长的淡入加升起。 */
|
|
7
|
+
pageClassName?: string;
|
|
8
|
+
/**
|
|
9
|
+
* 标签,按标签条上的顺序:每次切换,新页面从它所在的那一侧滑进来并淡入,而不是一帧之内换掉。
|
|
10
|
+
*
|
|
11
|
+
* 用 Web Animations API 在布局 effect 里播,不用类。用类的话——见下面 `seen` 的注释——从 `display: none`
|
|
12
|
+
* 回来的页面会先在终点画一帧,动画才接上。布局 effect 在页面显示之后、任何东西画出来之前跑,所以谁看到的
|
|
13
|
+
* 第一帧都已经是滑入的第一帧。回到一个页面也播:标签条是来回切的地方,只在第一次有动画的切换,第二次读起来
|
|
14
|
+
* 就像坏了。
|
|
15
|
+
*/
|
|
16
|
+
slide?: readonly T[];
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
/**
|
|
19
|
+
* 回来的那一页,里面的 CSS 动画不重演。
|
|
20
|
+
*
|
|
21
|
+
* `display: none` 一撤,页面里挂着动画 class 的元素按规范会把动画从头再播一遍。那些动画说的都是
|
|
22
|
+
* 「刚刚发生」:回复写完时底下那行操作从 0 长到 24px、排队的消息展开、头像做一次表情。回到一段
|
|
23
|
+
* 早就在那里的对话,什么也没刚发生——可那一行每次切回都重新长一遍,整条回复跟着跳 38px。
|
|
24
|
+
*
|
|
25
|
+
* 在下一帧画出来之前做,不在显示它的那次提交里做。藏着的页面不跟 store 同步(订阅也是 effect,
|
|
26
|
+
* 跟着一起拆了),离开期间写完的回复要等回来、订阅重新挂上才补进来——那是紧跟着的另一次提交,
|
|
27
|
+
* 当场处理会漏掉它,而它同样是在补账,不是此刻发生的事。两次提交都落在第一帧之前,逐帧量过。
|
|
28
|
+
*
|
|
29
|
+
* 页面自己那层(`pageClassName`)不算:那是换页本身的到达动画,每次换页都该有。转圈、呼吸这种
|
|
30
|
+
* 没有终点的照常跑——它们也没法跳到终点,`finish()` 会抛错。
|
|
31
|
+
*/
|
|
32
|
+
export declare function finishReplayedAnimations(page: HTMLElement): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设置页里一节的版式:分组标题、卡片、带标签的一行。
|
|
3
|
+
*
|
|
4
|
+
* 放在这里而不是产品里,是因为插件也能往设置页加一节(`ui.settingsSection`):两边用同一份,插件那一节和产品自己的几节
|
|
5
|
+
* 才长得一样。产品的设置页经 `settings/layout.tsx` 用原来的名字(`SectionTitle`、`Card`、`Row`)引用它们。
|
|
6
|
+
*/
|
|
7
|
+
import type { LucideIcon } from "../icons/index.ts";
|
|
8
|
+
/** 一组卡片上面的分组标题。 */
|
|
9
|
+
export declare function SettingsSectionTitle({ children }: {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* 其余属性原样透传,卡片可以带一个 `data-` 标记给测试量它。
|
|
14
|
+
*
|
|
15
|
+
* 卡片用 `float` 那张纸:设置卡片和弹出菜单是同一个颜色,两个主题下都比页面亮一档的实底。边框随之用 `line-float`,
|
|
16
|
+
* 那是给「画在自己那张纸上」的线准备的;卡片里面的线和控件怎么跟着换,见 `controls.css` 的 `.plume-settings-card`。
|
|
17
|
+
*/
|
|
18
|
+
export declare function SettingsCard({ children, className, ...rest }: React.ComponentProps<"div">): import("react").JSX.Element;
|
|
19
|
+
/** 卡片里带标签的一行,控件靠右。 */
|
|
20
|
+
export declare function SettingsRow({ title, detail, control, children, }: {
|
|
21
|
+
title: React.ReactNode;
|
|
22
|
+
detail?: React.ReactNode;
|
|
23
|
+
control?: React.ReactNode;
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
declare const NOTICE_TONES: {
|
|
27
|
+
readonly danger: "border-danger/30 bg-danger/10 text-danger";
|
|
28
|
+
readonly accent: "border-accent/35 bg-accent/6 text-ink-muted";
|
|
29
|
+
readonly muted: "border-line";
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* 页面要告诉你的一句话:出错了(`danger`)、有东西要看一眼(`accent`),或者只是让你知道(`muted`)。
|
|
33
|
+
*
|
|
34
|
+
* 框和语气在这里定一次,产品的设置页和插件加的设置分区共用。安静的那种不定字色:用它的页面在里面放一行偏灰的标题、
|
|
35
|
+
* 几行更淡的说明,这里给一种颜色会把层次压平。
|
|
36
|
+
*/
|
|
37
|
+
export declare function SettingsNotice({ tone, icon: Icon, className, children, ...rest }: React.ComponentProps<"div"> & {
|
|
38
|
+
tone: keyof typeof NOTICE_TONES;
|
|
39
|
+
icon?: LucideIcon;
|
|
40
|
+
}): import("react").JSX.Element;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 两个窗格之间能拖的边界:两张卡片之间留出的那道缝。
|
|
3
|
+
*
|
|
4
|
+
* 出现的是**指针处**的一小段握把,不是沿整条边的一道线——和侧栏的拖把同一种做法,理由也一样。整条的线读起来
|
|
5
|
+
* 是边框,布局里永久的一部分,而它要说的是「这一处可以拖」。跟着指针走的握把只说这一件事,边界看起来也不会
|
|
6
|
+
* 因为你碰巧靠近而变样。
|
|
7
|
+
*
|
|
8
|
+
* 抓取区是以缝为中心的九像素带子,指针能稳稳找到的最窄宽度。
|
|
9
|
+
*
|
|
10
|
+
* 报告的是**份额**,不是增量。累加增量会把夹紧误差攒起来——拖过下限再拖回来,边界就少了你拖过头的那一截。
|
|
11
|
+
*
|
|
12
|
+
* 停靠面板和对话分屏用的是同一个:两边的分隔条行为一样,拖动的手感是量出来的,不该有两份。
|
|
13
|
+
*/
|
|
14
|
+
import { type SplitterBox } from "../lib/tiling.ts";
|
|
15
|
+
export declare function Splitter({ handle, containerRef, onResize, onEven, at, onDragStart, }: {
|
|
16
|
+
handle: SplitterBox;
|
|
17
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
18
|
+
onResize: (share: number) => void;
|
|
19
|
+
/** 双击:让这条边界两侧的窗格一样大。 */
|
|
20
|
+
onEven: () => void;
|
|
21
|
+
/** 横向位置换成这个,和两边格子同一种写法。 */
|
|
22
|
+
at?: string;
|
|
23
|
+
/** 拖动开始时调用,返回的函数在拖动结束时调用。分屏用它在拖动期间压住布局的落盘。 */
|
|
24
|
+
onDragStart?: () => () => void;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 智能体长什么样:一个形状配一个颜色,再加一双眼睛(眼睛归 `ui/avatar` 画)。
|
|
3
|
+
*
|
|
4
|
+
* 这里只管「谁是谁」,不管怎么画——纯逻辑,没有 React,单测不需要 DOM。
|
|
5
|
+
*
|
|
6
|
+
* 形象写在定义文件的 `avatar: cloud-violet` 里,是这个智能体身份的一部分:换台机器、换个
|
|
7
|
+
* 窗口、在面板里还是在设置页里,同一个名字是同一张脸。没写的(手写的定义、旧文件)按名字
|
|
8
|
+
* 算一张,算法是确定的,所以同一个名字每次都算出同一张。
|
|
9
|
+
*/
|
|
10
|
+
export declare const AVATAR_SHAPES: readonly ["circle", "drop", "squircle", "blob", "cloud", "pill", "triangle", "flower", "hexagon", "ghost", "star", "bean", "arch", "diamond", "heart", "burst"];
|
|
11
|
+
export declare const AVATAR_COLORS: readonly ["blue", "green", "pink", "teal", "violet", "brown", "orange", "red", "yellow", "indigo", "lime", "sky", "rose", "mint", "coral", "plum"];
|
|
12
|
+
export type AvatarShape = (typeof AVATAR_SHAPES)[number];
|
|
13
|
+
export type AvatarColor = (typeof AVATAR_COLORS)[number];
|
|
14
|
+
export interface Avatar {
|
|
15
|
+
shape: AvatarShape;
|
|
16
|
+
color: AvatarColor;
|
|
17
|
+
}
|
|
18
|
+
/** `cloud-violet` → `{ shape: "cloud", color: "violet" }`;认不出来的一律 `null`,由调用方兜底。 */
|
|
19
|
+
export declare function parseAvatar(value: unknown): Avatar | null;
|
|
20
|
+
export declare function formatAvatar(avatar: Avatar): string;
|
|
21
|
+
/**
|
|
22
|
+
* 按名字算一张,避开 `taken` 里已经有人用的。
|
|
23
|
+
*
|
|
24
|
+
* 和 `freshAvatar` 一样挑剔:形状、颜色都没人用的先要,其次形状新,再次颜色新,最后只要组合
|
|
25
|
+
* 新——只是这里的「挑」是确定的,从名字算出的那一格开始往后找。从前只要组合没人用就收,于是
|
|
26
|
+
* 一个手写的 `boss` 算出来是蓝色的拱门,站在蓝色的圆 `general` 下面,像是同一个人换了个发型。
|
|
27
|
+
*
|
|
28
|
+
* 全被占了(两百多个智能体)就不避了——总得给一张,重复一张脸比没有脸好。
|
|
29
|
+
*/
|
|
30
|
+
export declare function hashedAvatar(name: string, taken?: Iterable<Avatar>): Avatar;
|
|
31
|
+
/**
|
|
32
|
+
* 一份名单里每个人的脸,保证互不相同。
|
|
33
|
+
*
|
|
34
|
+
* 写明了的先落座(定义里的 `avatar`,其次是 `fallback` 给的,内置的那几个就走这条),剩下的
|
|
35
|
+
* **按名字排好序**再逐个算——排序是为了让结果只取决于名单里有谁,不取决于名单是按什么顺序
|
|
36
|
+
* 送来的:设置页和提及菜单拿到的是同一批人、不同的顺序,两边必须画出同一张脸。
|
|
37
|
+
*
|
|
38
|
+
* 写明了的两个撞了,照写的来:那是人自己挑的。
|
|
39
|
+
*/
|
|
40
|
+
export declare function assignAvatars(agents: readonly {
|
|
41
|
+
name: string;
|
|
42
|
+
avatar?: string;
|
|
43
|
+
}[], fallback?: (name: string) => string | undefined): Map<string, Avatar>;
|
|
44
|
+
/**
|
|
45
|
+
* 给一个新智能体挑一张没人用过的脸。
|
|
46
|
+
*
|
|
47
|
+
* 不只是「这个组合没人用」:形状和颜色能都不撞就都不撞。内置的几个已经把圆、水滴、方块……和
|
|
48
|
+
* 蓝、绿、粉……占了,新来的要是个绿色的圆,组合是新的,一眼看过去却像 `general` 换了件衣服。
|
|
49
|
+
* 两样都新的挑不出来,退一步只要形状新,再退一步只要组合新。
|
|
50
|
+
*/
|
|
51
|
+
export declare function freshAvatar(taken: Iterable<Avatar>, random?: () => number): Avatar;
|
|
52
|
+
/**
|
|
53
|
+
* 眨眼的节奏,按名字定。
|
|
54
|
+
*
|
|
55
|
+
* 一屏七张脸要是同一个节拍一起眨,看起来像是屏幕闪了一下,而不是七个各自活着的东西。间隔落在
|
|
56
|
+
* 2.8–6.4 秒之间:人大约三到四秒眨一次,再慢就像在发呆,再快就像在紧张。
|
|
57
|
+
*/
|
|
58
|
+
export declare function blinkPause(name: string, random?: () => number): number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 在每个平台上都画得出中文的等宽字体栈。
|
|
3
|
+
*
|
|
4
|
+
* 等宽字体没有汉字,所以编辑器里的中文注释、终端里的中文行,是由排在它们后面的字体画的——字体栈一走到
|
|
5
|
+
* 通用的 `monospace`,Windows 上的 Chromium 就拿新宋体来答汉字,代码中间冒出一段细线衬线体。默认字体栈
|
|
6
|
+
* 正是为此把雅黑排在 `monospace` 前面(见 theme.css 的 `--plume-font-mono`);可要是一个字体预设只写了
|
|
7
|
+
* 苹方,Windows 上没有它,选了 Consolas、JetBrains Mono 之类,编辑器和终端里的中文就又落回宋体一族。
|
|
8
|
+
*
|
|
9
|
+
* 所以不管存下来的是哪个字体栈——预设、默认、手写的——缺了默认栈里的那几个中文字体,就补到 `monospace`
|
|
10
|
+
* 前面。已经自己选了中文字体的栈,它的排在这些前面;它列出的任何一项都不挪。
|
|
11
|
+
*/
|
|
12
|
+
export declare function withHanFallback(stack: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** 代码主题配色,供代码块、编辑器、终端和 diff 共用。 */
|
|
2
|
+
import type { MessageKey } from "../../i18n/messages/index.ts";
|
|
3
|
+
export interface CodeThemeSpec {
|
|
4
|
+
id: string;
|
|
5
|
+
/** 主题原名不翻译;有 labelKey 时由选择器按当前语言显示。 */
|
|
6
|
+
label: string;
|
|
7
|
+
labelKey?: MessageKey;
|
|
8
|
+
mode: "light" | "dark";
|
|
9
|
+
/** 代码底色和默认字色;允许调用方只提供继承应用配色的主题。 */
|
|
10
|
+
background?: string;
|
|
11
|
+
foreground?: string;
|
|
12
|
+
/** 默认主题继承应用底色;上面的色值仍用于预览和兜底。 */
|
|
13
|
+
inherit?: boolean;
|
|
14
|
+
/** diff 新增行底色。 */
|
|
15
|
+
addedBg?: string;
|
|
16
|
+
/** diff 删除行底色。 */
|
|
17
|
+
removedBg?: string;
|
|
18
|
+
/** 语法配色,运算符和标点分别定义。 */
|
|
19
|
+
tokens?: {
|
|
20
|
+
keyword: string;
|
|
21
|
+
string: string;
|
|
22
|
+
number: string;
|
|
23
|
+
comment: string;
|
|
24
|
+
function: string;
|
|
25
|
+
type: string;
|
|
26
|
+
variable: string;
|
|
27
|
+
operator: string;
|
|
28
|
+
punctuation: string;
|
|
29
|
+
tag: string;
|
|
30
|
+
attribute: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export declare const LIGHT_CODE_THEMES: CodeThemeSpec[];
|
|
34
|
+
export declare const DARK_CODE_THEMES: CodeThemeSpec[];
|
|
35
|
+
export declare function findCodeTheme(id?: string, mode?: "light" | "dark"): CodeThemeSpec;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `toLocaleString(locale, options)`,但把格式器留着。
|
|
3
|
+
*
|
|
4
|
+
* 每次带选项调用都会新建一个 `Intl.DateTimeFormat`——大约 30µs,复用一个只要 7µs。一次不算什么;可侧栏
|
|
5
|
+
* 渲染时几十行每行都要格式化一次提示,对话记录里每条消息的说明也一样,加起来就是一次渲染的大头。
|
|
6
|
+
* 按语言和格式分别留着,两者都只有寥寥几种取值。
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatDate(at: Date | number, locale: string, options: Intl.DateTimeFormatOptions): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 小时要不要补零,取决于这种语言按哪种钟点报时。
|
|
3
|
+
*
|
|
4
|
+
* 24 小时制下「09:05」是通常的写法,中文界面一直这样显示。12 小时制下那个零读起来像打错了——「02:28 PM」——
|
|
5
|
+
* 所以英文不补。
|
|
6
|
+
*
|
|
7
|
+
* 写 `hour: "numeric"` 的格式在每种语言里都不动小时,不用换成这个;换了反而会给一个从来不补零的中文
|
|
8
|
+
* 9:05 补上零。
|
|
9
|
+
*
|
|
10
|
+
* 按语言留着:每一行消息都要问,而答案只随语言变。
|
|
11
|
+
*/
|
|
12
|
+
import type { ResolvedUiLocale } from "../i18n/index.ts";
|
|
13
|
+
export declare function hourStyle(locale: ResolvedUiLocale): "numeric" | "2-digit";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数字输入框里敲到一半的字能不能留着。
|
|
3
|
+
*
|
|
4
|
+
* 每敲一下就钳到范围里的话,最小值 11 的框会在敲「16」的路上拒掉「1」。所以框里留一份草稿:永远到不了范围内的字符
|
|
5
|
+
* 进不来,其余的照留,什么也不提示。
|
|
6
|
+
*/
|
|
7
|
+
export interface NumberBounds {
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
step?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function decimalsOf(step: number): number;
|
|
13
|
+
export declare function formatNumber(value: number, decimals: number): string;
|
|
14
|
+
/** 步进按钮和方向键:按步长加减,钳在范围里。 */
|
|
15
|
+
export declare function stepNumber(value: number, delta: number, bounds: NumberBounds): number;
|
|
16
|
+
/** 草稿落成数字:没敲完的(空、只有负号或小数点)给 null,完整的数字按步长取整、钳进范围。 */
|
|
17
|
+
export declare function commitDraft(text: string, bounds: NumberBounds): number | null;
|
|
18
|
+
/**
|
|
19
|
+
* 这串字能不能留在框里。
|
|
20
|
+
*
|
|
21
|
+
* 空着可以,这样全选后能整个替换。负号只在下限小于 0 时可以。超过上限的完整数字拒掉;低于下限的,只有再往后敲数字
|
|
22
|
+
* (或小数)还能落进范围时才留着。
|
|
23
|
+
*/
|
|
24
|
+
export declare function isLegalDraft(text: string, bounds: NumberBounds): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多久以前,用人会用的单位说。
|
|
3
|
+
*/
|
|
4
|
+
import type { ResolvedUiLocale } from "../i18n/index.ts";
|
|
5
|
+
/** 故意说得粗:列表里没人关心一次提交的确切分钟。 */
|
|
6
|
+
export declare function relativeTime(iso: string, now?: number): string;
|
|
7
|
+
/**
|
|
8
|
+
* 同一段时间,不带「前」,给一行的角落用。
|
|
9
|
+
*
|
|
10
|
+
* 列表把它画在一列的右边,这一列还要放标题,这里每多一个字,标题就少一个字。挨着标题时,一段时长
|
|
11
|
+
* 不用说明也读得出是「多久以前」,所以各家代码托管站在同一个位置都这样写。
|
|
12
|
+
*
|
|
13
|
+
* `now` 是参数而不是在里面取,这样组件可以跟着一个共享的时钟重渲染——整个列表一个定时器,而不是每行
|
|
14
|
+
* 一个——也让它保持一个不用冻结时间就能测的函数。
|
|
15
|
+
*/
|
|
16
|
+
export declare function shortRelativeTime(iso: string, now?: number): string;
|
|
17
|
+
/** 确切的时刻,给取整过的那个当悬停提示。 */
|
|
18
|
+
export declare function exactTime(iso: string, locale?: ResolvedUiLocale): string;
|