@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,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 菜单由这些零件组成:行、分隔线、小标题、搜索框、带内衬的正文。
|
|
3
|
+
*
|
|
4
|
+
* 和 `Popover` 分开,弹层只是一个定好位的面。弹层里可以放任何东西——取色器、表单——菜单也可以放在
|
|
5
|
+
* 不是弹层的地方。把两者分开,「行长什么样」和「面落在哪」才不会被顺手一起改掉。
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 每个菜单的内容所在的盒子。
|
|
9
|
+
*
|
|
10
|
+
* 行四周的留白在滚动区上(`--plume-menu-inset`),不在这里。这里再加一层内衬会叠在那圈外边距上,
|
|
11
|
+
* 上下就成了左右的两倍。
|
|
12
|
+
*/
|
|
13
|
+
export declare function MenuBody({ children, insetIcons, className, }: {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
/** 每行都留出图标列,给只有部分行有图标的菜单用。 */
|
|
16
|
+
insetIcons?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* 菜单分隔线下面的行:比如列表下面的「新建」。
|
|
21
|
+
*
|
|
22
|
+
* 弹层的 footer 槽位没有自己的留白,因为放在那里的不都是行——也可能是一条通栏,或者一张小表单。
|
|
23
|
+
* 行需要列表的留白和列表的圆角(`.plume-menu-foot`),否则悬停底色从边铺到边,位置也比上面的行偏左
|
|
24
|
+
* 一截;各菜单各自补一圈留白,又会补出不一样的宽度。
|
|
25
|
+
*/
|
|
26
|
+
export declare function MenuFooter({ children }: {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
/**
|
|
30
|
+
* 菜单里的一行。
|
|
31
|
+
*
|
|
32
|
+
* 每个菜单各自长一份的话——高度不同、圆角不同、有的干脆没有圆角——同一个手势在不同菜单里看着不一样。
|
|
33
|
+
* 视觉状态放在 `.plume-item` 里,需要别的形状的行(比如两行的选项)也能用上它们。
|
|
34
|
+
*/
|
|
35
|
+
export declare function MenuItem({ icon, children, detail, hint, trailing, checked, selected, danger, disabled, title, className, onClick, }: {
|
|
36
|
+
icon?: React.ReactNode;
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* 解释这个选项的第二行。
|
|
40
|
+
*
|
|
41
|
+
* 在这里处理,而不是每个菜单自己排两行的行:自己排的话会长出自己的高度、内边距和悬停效果,同一个
|
|
42
|
+
* 手势在不同菜单里看着不一样。
|
|
43
|
+
*/
|
|
44
|
+
detail?: React.ReactNode;
|
|
45
|
+
/** 右对齐的注记:数量、快捷键数字、上下文大小。 */
|
|
46
|
+
hint?: React.ReactNode;
|
|
47
|
+
/** 右对齐的元素,放勾或箭头。 */
|
|
48
|
+
trailing?: React.ReactNode;
|
|
49
|
+
/**
|
|
50
|
+
* 让这一行成为开关设置:行尾一个小开关,`menuitemcheckbox` 语义。
|
|
51
|
+
*
|
|
52
|
+
* 文字仍是设置的名字——「自动更新」——状态由开关说。两样都用字写的话,「自动更新:开(点击关闭)」
|
|
53
|
+
* 是一句要解析的话,而本该扫一眼就够,还会跑出菜单的右边。
|
|
54
|
+
*/
|
|
55
|
+
checked?: boolean;
|
|
56
|
+
selected?: boolean;
|
|
57
|
+
danger?: boolean;
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
title?: string;
|
|
60
|
+
/**
|
|
61
|
+
* 加在行本身上的类,给用别的方式标记行的菜单。
|
|
62
|
+
*
|
|
63
|
+
* 比如右边那一列已经被占了、所以选中行用填充而不是打勾的菜单。选了这种方式的行得能说出来——在这里
|
|
64
|
+
* 说,高度、圆角和按下状态仍是共用的,而这正是行只住在一个地方的意义。
|
|
65
|
+
*/
|
|
66
|
+
className?: string;
|
|
67
|
+
onClick?: () => void;
|
|
68
|
+
}): import("react").JSX.Element;
|
|
69
|
+
/** 分开菜单里的几组行。 */
|
|
70
|
+
export declare function MenuSeparator(): import("react").JSX.Element;
|
|
71
|
+
/** 一组行上面的小标题。 */
|
|
72
|
+
export declare function MenuLabel({ children }: {
|
|
73
|
+
children: React.ReactNode;
|
|
74
|
+
}): import("react").JSX.Element;
|
|
75
|
+
/**
|
|
76
|
+
* 列出超过一屏的菜单顶上的筛选框。
|
|
77
|
+
*
|
|
78
|
+
* 每个菜单各写一份的话,同样的高度、同样的放大镜、同样的占位文案,每多一份就多一次走样的机会。
|
|
79
|
+
* 给 `Popover` 的 `header` 槽位用,列表滚动时它不动;它下面那条线属于那个槽位,不在这里画。
|
|
80
|
+
*
|
|
81
|
+
* Escape 先清空再关闭,和 `SearchField` 一样:第一次按撤销输入,只有没东西可撤销时按才关掉菜单。
|
|
82
|
+
*/
|
|
83
|
+
export declare function MenuSearch({ value, onChange, placeholder, autoFocus, onKeyDown, }: {
|
|
84
|
+
value: string;
|
|
85
|
+
onChange: (value: string) => void;
|
|
86
|
+
placeholder?: string;
|
|
87
|
+
autoFocus?: boolean;
|
|
88
|
+
/** 给焦点留在输入框里、由它来移动高亮(方向键和 Enter)的菜单用。 */
|
|
89
|
+
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
90
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 遮罩的黑有多浓,和 `overlay.css` 里 `.plume-scrim-in` 画的一致——两者必须对上,因为遮罩在的时候,
|
|
3
|
+
* 窗口自己的按钮就是按这个压暗的(见 `scrims.ts`)。
|
|
4
|
+
*/
|
|
5
|
+
export declare const SCRIM_ALPHA = 0.22;
|
|
6
|
+
export declare const OverlayDepth: import("react").Context<number>;
|
|
7
|
+
/** 播完退场,再运行 `after`——没有别的要做时运行 `onClose`。 */
|
|
8
|
+
export type Dismiss = (after?: () => void) => void;
|
|
9
|
+
/** Escape、点遮罩、取消和完成共用一套生命周期,嵌套的对话框也一样。 */
|
|
10
|
+
export declare function Overlay({ children, onClose, align, width, label, returnFocus, }: {
|
|
11
|
+
children: React.ReactNode | ((dismiss: Dismiss) => React.ReactNode);
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
align?: "center" | "bottom";
|
|
14
|
+
width?: number;
|
|
15
|
+
label?: string;
|
|
16
|
+
returnFocus?: HTMLElement;
|
|
17
|
+
}): import("react").ReactNode;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 锚在打开它的元素上的弹层。
|
|
3
|
+
*
|
|
4
|
+
* 属于某个控件的菜单应该出现在那个控件旁边,而不是窗口正中——居中的对话框丢掉了「点的是什么」和
|
|
5
|
+
* 「打开的是什么」之间的联系。位置从触发元素的矩形量出来,要跑出屏幕时翻到另一侧。
|
|
6
|
+
*
|
|
7
|
+
* 面是三个槽位而不是一个:中间滚动时 `header` 和 `footer` 不动。没有这个的话,要搜索框的菜单只能把它
|
|
8
|
+
* 放进滚动区,再想办法不让它被滚走——每个菜单各解决一遍,解法还各不相同。
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 挂菜单的一个点,给右键用——被操作的是一整行,唯一有意义的位置就是指针本身。
|
|
12
|
+
*/
|
|
13
|
+
interface PointAnchor {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
}
|
|
17
|
+
export type Anchor = HTMLElement | PointAnchor | null;
|
|
18
|
+
/**
|
|
19
|
+
* 浮起的面允许的宽度。
|
|
20
|
+
*
|
|
21
|
+
* 各自挑宽度的话,184 到 288 之间能挑出十几种,长得一样的两个菜单也对不上——同一个手势在侧栏和输入框里
|
|
22
|
+
* 打开的面板差四个像素,谁也说不出为什么。这里四档,按面里装的是什么来选,而不是按写它那天最长的
|
|
23
|
+
* 标签碰巧有多长。
|
|
24
|
+
*/
|
|
25
|
+
declare const MENU_WIDTH: {
|
|
26
|
+
/** 只有动作,每个一两个词。 */
|
|
27
|
+
readonly compact: 190;
|
|
28
|
+
/** 普通的菜单——图标、文字,有时有第二行——以及所有下拉。 */
|
|
29
|
+
readonly default: 224;
|
|
30
|
+
/** 带搜索框的,或者长到要滚动的列表。 */
|
|
31
|
+
readonly wide: 272;
|
|
32
|
+
/** 不是菜单:一段读数、一个滑块、一张表单。 */
|
|
33
|
+
readonly panel: 300;
|
|
34
|
+
/**
|
|
35
|
+
* 内容多宽就多宽(`undefined` 就是「这一层别管宽度」)。
|
|
36
|
+
*
|
|
37
|
+
* 给宽度要跟着自己的字走的面用(比如一条动作条):写死一个数,字一变总有一边要截断。菜单默认的
|
|
38
|
+
* `compact` 是要写死的那种默认,不是这个。
|
|
39
|
+
*/
|
|
40
|
+
readonly hug: undefined;
|
|
41
|
+
};
|
|
42
|
+
export type PopoverWidth = keyof typeof MENU_WIDTH | number;
|
|
43
|
+
/**
|
|
44
|
+
* 列东西的菜单最高能长到多高。
|
|
45
|
+
*
|
|
46
|
+
* 交给窗口决定的话,高屏幕上的一个列表菜单会从输入框一直铺到屏幕顶——技术上没错,但四十行的列表没人
|
|
47
|
+
* 读到底。会滚动的菜单出于同一个理由各挑一个上限(280、300、320),这里把这个理由说一次。
|
|
48
|
+
*/
|
|
49
|
+
export declare const MENU_MAX_HEIGHT = 340;
|
|
50
|
+
export interface PopoverProps {
|
|
51
|
+
/** 弹层挂在哪个元素上,右键菜单则是一个点。 */
|
|
52
|
+
anchor: Anchor;
|
|
53
|
+
onClose: () => void;
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* 优先放在哪一侧。地方不够时自动翻转。
|
|
57
|
+
*
|
|
58
|
+
* `right` 把菜单放在触发元素旁边而不是下面,这对列表里的一行很重要:往下掉的菜单会盖住你正要拿来
|
|
59
|
+
* 对比的那几行。
|
|
60
|
+
*/
|
|
61
|
+
placement?: "top" | "bottom" | "right";
|
|
62
|
+
/** 弹层的哪条边和锚点对齐。 */
|
|
63
|
+
align?: "start" | "end" | "center";
|
|
64
|
+
width?: PopoverWidth;
|
|
65
|
+
/**
|
|
66
|
+
* 钉在滚动正文上面——搜索框、标题。
|
|
67
|
+
*
|
|
68
|
+
* 不放进 `children`,因为它不能滚动:一用就离开屏幕的筛选框,要改它还得滚回去。
|
|
69
|
+
*/
|
|
70
|
+
header?: React.ReactNode;
|
|
71
|
+
/** 钉在它下面,给不管列表多长都要够得着的动作。 */
|
|
72
|
+
footer?: React.ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* 钉在它左边——比如一列分类。
|
|
75
|
+
*
|
|
76
|
+
* 是槽位,理由和另外两个一样:跟着被筛选的列表一起滚走的筛选,要改还得滚回去。它也不能作为 sticky
|
|
77
|
+
* 的一列放在 `children` 里,因为滚动区的内容盒会裁掉横向溢出,而祖先上的任何 `overflow` 都会让
|
|
78
|
+
* `sticky` 粘在那个祖先上而不是视口上。
|
|
79
|
+
*/
|
|
80
|
+
aside?: React.ReactNode;
|
|
81
|
+
/** 给否则会长满窗口的面一个上限——见 `MENU_MAX_HEIGHT`。 */
|
|
82
|
+
maxHeight?: number;
|
|
83
|
+
/**
|
|
84
|
+
* 这个面是什么,给读窗口而不是看窗口的东西。
|
|
85
|
+
*
|
|
86
|
+
* 写死成 `menu` 对大多数是对的,对不是菜单的就错了:重命名表单、一段读数、一个滑块。被播报成菜单项
|
|
87
|
+
* 的输入框,比什么都不播报更糟。
|
|
88
|
+
*/
|
|
89
|
+
role?: "menu" | "listbox" | "dialog" | "group";
|
|
90
|
+
/** 触发元素没说清时,给这个面一个名字。 */
|
|
91
|
+
label?: string;
|
|
92
|
+
className?: string;
|
|
93
|
+
/** 加在滚动正文上,给自己给内容加内衬的面。 */
|
|
94
|
+
bodyClassName?: string;
|
|
95
|
+
/**
|
|
96
|
+
* 一列行,还是一样东西。
|
|
97
|
+
*
|
|
98
|
+
* `menu` 是每个菜单要的内衬:圆角需要地方,行不能跑到滚动条底下,渐隐的边说明列表在那之外还有。
|
|
99
|
+
* 这三样对只装一块自己画底色的面板的面都是错的——比如一段 diff,它的代码底色会在离卡片右边 25px、
|
|
100
|
+
* 离顶 6px 处就停了,缝里露出浮层的底。面板读起来像嵌在一张它没填满的卡片里。
|
|
101
|
+
*
|
|
102
|
+
* `panel` 把整个正文交给内容,让叠加的滑块浮在上面,这正是叠加滚动条的用途。
|
|
103
|
+
*/
|
|
104
|
+
surface?: "menu" | "panel";
|
|
105
|
+
/**
|
|
106
|
+
* 把悬停交给整个面,给悬停打开的弹层用。
|
|
107
|
+
*
|
|
108
|
+
* 调用方如果挂在自己传的 `header` 和 `children` 上,描边、滚动区自己的外边距、滚动条那一条和滑块都在
|
|
109
|
+
* 处理范围之外:指针从这些地方进入弹层,在调用方看来仍然在外面——待执行的关闭就跑了。抓住悬停预览的
|
|
110
|
+
* 滚动条会把它关掉。
|
|
111
|
+
*/
|
|
112
|
+
onMouseEnter?: () => void;
|
|
113
|
+
onMouseLeave?: () => void;
|
|
114
|
+
}
|
|
115
|
+
export declare function Popover({ anchor, onClose, children, placement, align, width, header, footer, aside, maxHeight, role, label, className, bodyClassName, surface: kind, onMouseEnter, onMouseLeave, }: PopoverProps): import("react").ReactNode;
|
|
116
|
+
/** 记下锚点元素和打开状态,每个弹层触发器都要的这一对。 */
|
|
117
|
+
export declare function usePopover(): {
|
|
118
|
+
anchor: Anchor;
|
|
119
|
+
open: boolean;
|
|
120
|
+
toggle: (event: React.MouseEvent<HTMLElement>) => void;
|
|
121
|
+
/** 对着指定元素打开。 */
|
|
122
|
+
openAt: (element: HTMLElement) => void;
|
|
123
|
+
/** 在指针处打开——右键作用于整行,所以行不是锚点。 */
|
|
124
|
+
openAtPoint: (event: React.MouseEvent) => void;
|
|
125
|
+
close: () => void;
|
|
126
|
+
};
|
|
127
|
+
export { MenuBody, MenuFooter, MenuItem, MenuLabel, MenuSearch, MenuSeparator } from "./Menu.tsx";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 应用的悬停提示,写成 JSX 包装,比属性读起来顺。
|
|
3
|
+
*
|
|
4
|
+
* 它只给子元素打标记——气泡本身由 `tooltip.ts` 里那一个文档级监听器画。所以两种写法表现完全一样,
|
|
5
|
+
* 这很重要,因为第三方库自己建的按钮只能靠属性够到。
|
|
6
|
+
*
|
|
7
|
+
* 取代浏览器的 `title`:那个改不了样式,要等一秒半左右,不跟应用的字体和主题,在 macOS 上画成一个
|
|
8
|
+
* 系统面板,看着像属于另一个程序。
|
|
9
|
+
*/
|
|
10
|
+
export declare function Tooltip({ label, children, side }: {
|
|
11
|
+
label: string;
|
|
12
|
+
children: React.ReactElement;
|
|
13
|
+
side?: "top" | "bottom";
|
|
14
|
+
}): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 弹层走后在屏幕上留一会儿的东西。
|
|
3
|
+
*
|
|
4
|
+
* 只有 Escape 和点外面能在弹层卸载前先通知到 `Popover`,所以只有这两种走法有退场。其他走法都是一帧
|
|
5
|
+
* 就没了:再按一次触发按钮(切换把锚点设成 null)、选中一行(行调用 `onClose`)、离开悬停预览
|
|
6
|
+
* (`setHover(null)`)。这些都是调用方说了算,而调用方大多写的是 `open && <Popover>`,当场就移除了。
|
|
7
|
+
*
|
|
8
|
+
* 与其教每个调用方等一等,不如让弹层走的时候留一份自己的副本,由副本来播退场。它是一张画,不是
|
|
9
|
+
* 菜单:inert、对辅助技术隐藏、指针穿透、去掉文档里查找所依据的 id 和 role,动画结束时移除——
|
|
10
|
+
* 动画结束一直不来,就靠计时器。
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* 趁 `card` 还在布局里时复制它,等 React 真的移除它之后再显示副本。
|
|
14
|
+
*
|
|
15
|
+
* 从弹层卸载时的清理函数里调用,那时 React 还没把元素摘下来,所以这里读到的滚动位置、还在进行的
|
|
16
|
+
* 入场的透明度、每一条行内样式,都是屏幕上的样子。显不显示要等一个微任务:清理不一定是移除——
|
|
17
|
+
* 严格模式会对留下来的组件跑它,`Activity` 被隐藏时也会——只有真的离开文档的卡片才需要替身。
|
|
18
|
+
* 微任务仍在下一次绘制之前运行,所以不会有两者都不在的一帧。
|
|
19
|
+
*/
|
|
20
|
+
export declare function leaveAfterimage(card: HTMLElement | null): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 「自己冒出来的东西,现在该不该冒出来」只有一个答案。
|
|
3
|
+
*
|
|
4
|
+
* 有些面不是谁要求才出现的,而是指针停在某处就出来了:悬停提示,以及列表行旁边的悬停卡片。
|
|
5
|
+
* 有人主动打开了什么,它们都得让开——菜单上方淡入一个气泡是噪音,而一张悬停卡片是一大块噪音,
|
|
6
|
+
* 还画在它盖住的那个菜单上面。
|
|
7
|
+
*
|
|
8
|
+
* 如果各问各的:提示靠弹层设的一个模块级标志,再在每次 `pointerover` 时用选择器去找菜单的类名;
|
|
9
|
+
* 标志只认得弹层,选择器只认得弹层碰巧带着的那串类名,悬停卡片则谁也不问——右键一行,指针移开
|
|
10
|
+
* 再移回来,420ms 后卡片又回来了,压在还开着的菜单上面。所以集中在这里问一次。
|
|
11
|
+
*
|
|
12
|
+
* 两种请求,因为两类调用方要的不一样:
|
|
13
|
+
*
|
|
14
|
+
* `claimHoverSuppression` 是菜单在说「我在的时候别来」。弹层只盖住一小块,窗口其余部分照样能悬停,
|
|
15
|
+
* 没有一个持续的声明,指针随便溜到旁边一行就又把卡片叫出来了。
|
|
16
|
+
*
|
|
17
|
+
* `dismissHoverLayers` 是模态框在说「把屏幕清干净」。它的遮罩盖住一切,底下不可能再引出新的气泡或
|
|
18
|
+
* 卡片,持续的声明什么也买不到——代价却是真的:对话框里有自己的提示,在模态框开着的整段时间里压住,
|
|
19
|
+
* 等于把它们全关了。所以这只拿走打开那一刻屏幕上已有的东西,那才是真正的问题——从键盘打开的
|
|
20
|
+
* 对话框,没有按下这个动作替它清掉,卡片就挂在它上面。
|
|
21
|
+
*/
|
|
22
|
+
/** 现在是否有菜单或别的局部遮盖的面在压着它们。 */
|
|
23
|
+
export declare function hoverLayersSuppressed(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 调用方在屏幕上的这段时间里一直压着它们,并清掉现在显示着的。
|
|
26
|
+
*
|
|
27
|
+
* 返回释放函数,调用两次也安全:组件在 React 严格模式的双重调用里卸载,否则会把计数减到零以下,
|
|
28
|
+
* 之后每个声明都差一截。
|
|
29
|
+
*
|
|
30
|
+
* 用计数而不是布尔值。菜单会嵌套,对话框会弹出菜单,子菜单关掉不能撤销父菜单还压着的声明——
|
|
31
|
+
* 用布尔值的话,里层的清理会清掉外层的,最后一次释放碰巧赢。
|
|
32
|
+
*/
|
|
33
|
+
export declare function claimHoverSuppression(): () => void;
|
|
34
|
+
/** 拿走屏幕上现有的,不对接下来可能出现的东西下声明。 */
|
|
35
|
+
export declare function dismissHoverLayers(): void;
|
|
36
|
+
/**
|
|
37
|
+
* 听通知,而不是轮询。
|
|
38
|
+
*
|
|
39
|
+
* 对话框打开时屏幕上已有的卡片得拿走,而那一刻卡片自己的 props 什么也没变。
|
|
40
|
+
*/
|
|
41
|
+
export declare function onHoverLayersDismissed(listener: () => void): () => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 所有浮起来的东西挂在哪。
|
|
3
|
+
*
|
|
4
|
+
* 好几个组件要 portal 到 `document.body`——对话框、弹层、悬停卡片、通知、看图器。它们不是同一个
|
|
5
|
+
* 组件,也不该是:对话框困住焦点,弹层跟着锚点,通知会堆叠。它们共有的只是一个决定,不该每处写一遍。
|
|
6
|
+
*
|
|
7
|
+
* 这个决定是 `document.body` 而不是应用里的某个容器,理由很具体:`backdrop-filter` 采样的是最近的
|
|
8
|
+
* backdrop root,而*任何* `mask` 都会建一个。每个边缘渐隐的 `Scroller` 都带 mask,所以渲染在里面的
|
|
9
|
+
* 菜单模糊的是滚动区自己透明的底,而不是页面——毛玻璃看着是坏的,透明度怎么调都没用。portal 到
|
|
10
|
+
* body,模糊的才是真正在后面的东西。
|
|
11
|
+
*
|
|
12
|
+
* 是共用的函数而不是共用的组件,这样每个调用方保留自己的行为,又都不用重新推一遍这件事。
|
|
13
|
+
*/
|
|
14
|
+
import type { ReactNode } from "react";
|
|
15
|
+
/**
|
|
16
|
+
* 把 `children` 渲染到文档的最上层。
|
|
17
|
+
*
|
|
18
|
+
* 没有文档时返回 `null`——在没有 DOM 的服务端或测试里渲染的组件什么也拿不到而不是崩溃,对纯视觉的
|
|
19
|
+
* 东西来说这是对的形状。
|
|
20
|
+
*/
|
|
21
|
+
export declare function portal(children: ReactNode): ReactNode;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 现在是什么在压暗整个窗口。
|
|
3
|
+
*
|
|
4
|
+
* 在 Windows 和 Linux 上,最小化、最大化、关闭按钮由系统自己画在页面上方,颜色由应用交给它——页面里
|
|
5
|
+
* 什么都盖不住它们。对话框的遮罩压暗了整个窗口,唯独右上角那一小块没暗,成了屏幕上最亮的地方。
|
|
6
|
+
* 压暗窗口的东西在压暗期间在这里持有一个遮罩;画在页面之外的东西跟着它变。
|
|
7
|
+
*
|
|
8
|
+
* 只是一份状态,背后没有服务,这样 `ui/` 里的浮层能说出自己在做什么,又不越过自己这一层。
|
|
9
|
+
*/
|
|
10
|
+
export interface Scrim {
|
|
11
|
+
/** `#rrggbb`。 */
|
|
12
|
+
color: string;
|
|
13
|
+
/** 盖住底下多少,0–1。 */
|
|
14
|
+
alpha: number;
|
|
15
|
+
}
|
|
16
|
+
/** 用这个遮罩压暗窗口,直到调用返回的释放函数。 */
|
|
17
|
+
export declare function holdScrim(color: string, alpha: number): () => void;
|
|
18
|
+
/** 现在持有的遮罩,按铺下的顺序,第一个在最底下。 */
|
|
19
|
+
export declare function heldScrims(): Scrim[];
|
|
20
|
+
export declare function onScrimsChange(listener: () => void): () => void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 整个窗口只有一个悬停提示,由属性驱动。
|
|
3
|
+
*
|
|
4
|
+
* React 的 `<Tooltip>` 包装只够得着 React 渲染的元素。第三方库自己建的 DOM(比如编辑器的搜索面板)
|
|
5
|
+
* 里的按钮只能用原生 `title`——形状不同、延迟不同,颜色和应用其余部分也对不上。
|
|
6
|
+
*
|
|
7
|
+
* 属性在什么上都管用:`data-plume-tip="下一个"` 挂在 React 节点上,和挂在第三方库刚建的 DOM 节点上
|
|
8
|
+
* 表现完全一样,因为显示气泡的是文档上的一个监听器,而不是每个目标一个组件。
|
|
9
|
+
*/
|
|
10
|
+
interface Box {
|
|
11
|
+
top: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
left: number;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 气泡放在哪:对着目标居中,放在要求的那一侧,除非那一侧出了屏幕,并且永远不越过任何一条边。
|
|
19
|
+
*
|
|
20
|
+
* 导出并且不碰 DOM,因为翻转是容易写反的部分,而写反了是看不出来的,直到有人指向靠边的那一个控件。
|
|
21
|
+
* 它确实写反过——每个 `side="top"` 的提示都画在目标下面——又因为另一个 bug 让提示根本不出现,
|
|
22
|
+
* 一直没人发现。
|
|
23
|
+
*/
|
|
24
|
+
export declare function tipPlacement(target: Box, tip: {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}, side: "top" | "bottom" | "right", viewport: {
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}): {
|
|
31
|
+
left: number;
|
|
32
|
+
top: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* 长标签在浏览器已经允许的之外,还能在哪里断行。
|
|
36
|
+
*
|
|
37
|
+
* 对断行器来说,一条路径或一个文件名是一个不断开的词——`_`、`.`、`/` 都不是断行点——所以一个写着
|
|
38
|
+
* `REQUIREMENTS_POLICY_PORTAL_v2_final_review_notes.md` 的提示会撑满宽度上限,`overflow-wrap` 在上限
|
|
39
|
+
* 落下的地方硬切,第二行只剩一个「d」。在长串 ASCII 里(16 个字符以上:路径、文件名、URL、标识符——
|
|
40
|
+
* 不是句子里的 "85.3%" 或 "v1.2"),一行现在可以在 `/ \ _ - . : ? & = # + @` 任一个后面结束。
|
|
41
|
+
*
|
|
42
|
+
* 返回这些位置之间的片段;调用方用 `<wbr>` 连起来,它是一个断行机会,不给文字加任何东西。
|
|
43
|
+
*/
|
|
44
|
+
export declare function softBreaks(text: string): string[];
|
|
45
|
+
/**
|
|
46
|
+
* 提示仍不比最宽时更高的最窄宽度。
|
|
47
|
+
*
|
|
48
|
+
* `max-content` 被 `max-width` 封顶时,第一行填满到上限,剩下的留给下一行——上面那个文件名排成了一行
|
|
49
|
+
* 343px 和一行 7px。把气泡收窄到再窄一像素就要多一行为止,文字就均匀地铺在它本来就需要的那几行上,
|
|
50
|
+
* 不管浏览器在哪断,包括 `overflow-wrap` 在词中间断的。这也是为什么不用 `text-wrap: balance`:它把行
|
|
51
|
+
* 排匀了,但盒子仍然停在上限,短行旁边的空白还留在气泡里。
|
|
52
|
+
*
|
|
53
|
+
* `heightAt` 按一个宽度排版提示并报告它的高度。由外面传进来,这样不用排版引擎也能测试这个搜索。
|
|
54
|
+
*/
|
|
55
|
+
export declare function balancedWidth(widest: number, heightAt: (width: number) => number): number;
|
|
56
|
+
/**
|
|
57
|
+
* 特意不在获得焦点时显示。
|
|
58
|
+
*
|
|
59
|
+
* 键盘用户从标签拿到无障碍名,Tab 穿过工具栏时冒出来的气泡是噪音而不是帮助。
|
|
60
|
+
*/
|
|
61
|
+
export declare function installTooltips(): void;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 按钮,只有界面真正用到的五种样子。
|
|
3
|
+
*
|
|
4
|
+
* 各处手写 `<button>` 的话,高度会长出七八种——26、28、30、32、44——没有一种是有意的。一排基线对不齐的
|
|
5
|
+
* 控件读起来像两条工具栏硬拼在一起。
|
|
6
|
+
*
|
|
7
|
+
* 这里收的是按钮一路自己长出来的那几种状态:一档给密集行的尺寸,还有一个忙碌态——每个异步操作原本都
|
|
8
|
+
* 在用 disabled 加旁边一个转圈各自实现它。
|
|
9
|
+
*
|
|
10
|
+
* 不是通用的按钮库。五种外观、三档尺寸,没有 `style`——要的就是调用方发明不出第九种高度。
|
|
11
|
+
* 类名组合在 `@plume/styles` 的 `button`。
|
|
12
|
+
*/
|
|
13
|
+
import type { ReactNode, MouseEvent } from "react";
|
|
14
|
+
/**
|
|
15
|
+
* 原样透传到 `<button>` 上的 `data-*`。
|
|
16
|
+
*
|
|
17
|
+
* 测试按这些找控件,而不是按文字,所以改个措辞不会弄坏一套测试。别的都不透传:没有 style,也没有
|
|
18
|
+
* 一整类事件——见文件开头。
|
|
19
|
+
*/
|
|
20
|
+
export type DataAttributes = {
|
|
21
|
+
[key: `data-${string}`]: string | boolean | undefined;
|
|
22
|
+
};
|
|
23
|
+
export type ButtonVariant = "primary" | "ghost" | "subtle" | "soft" | "danger";
|
|
24
|
+
/**
|
|
25
|
+
* `md` 32px,是默认:对话框的按钮就是这么高。
|
|
26
|
+
*
|
|
27
|
+
* `sm` 26px,给面板里的行,整高的按钮在那儿会喧宾夺主。
|
|
28
|
+
*
|
|
29
|
+
* `xs` 20px,给一句话末尾或一行小字后面的动作:26px 的按钮放在那儿,会让这一行比它所属的文字还高。
|
|
30
|
+
*/
|
|
31
|
+
export type ButtonSize = "md" | "sm" | "xs";
|
|
32
|
+
export declare function Button({ children, icon, onClick, variant, size, disabled, loading, label, ariaLabel, menu, expanded, pressed, className, type, ...data }: DataAttributes & {
|
|
33
|
+
/**
|
|
34
|
+
* 只有图标的按钮不传。
|
|
35
|
+
*
|
|
36
|
+
* 图标旁边再写一个字是把同一件事说两遍,一排这样的按钮会把工具栏变成一句话。图标说得清意思的地方,
|
|
37
|
+
* `label` 同时作悬停提示和无障碍名——读屏的人什么都没丢,丢的只是眼睛看到的那几个字。
|
|
38
|
+
*/
|
|
39
|
+
children?: ReactNode;
|
|
40
|
+
icon?: ReactNode;
|
|
41
|
+
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
42
|
+
variant?: ButtonVariant;
|
|
43
|
+
size?: ButtonSize;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* 忙碌。按钮不能按、变淡,宽度不变。
|
|
47
|
+
*
|
|
48
|
+
* 每个异步操作各自做这件事时,做法都略有不同——有的把文字换成转圈,整行跟着跳;有的按钮还能按,
|
|
49
|
+
* 能被按两次。宽度不变是因为:一个看着它的时候在缩的按钮,回头找的时候可能就找不到了。
|
|
50
|
+
*/
|
|
51
|
+
loading?: boolean;
|
|
52
|
+
/** 悬停提示;没有可见文字时也是无障碍名。 */
|
|
53
|
+
label?: string;
|
|
54
|
+
/** 可见文字本身说不清按钮做什么时的无障碍名——`中文` 是一个值,不是一个动作。 */
|
|
55
|
+
ariaLabel?: string;
|
|
56
|
+
/** 会打开一个菜单;值是它现在开没开。普通按钮不传。 */
|
|
57
|
+
menu?: boolean;
|
|
58
|
+
/** 原地展开或收起一段——`aria-expanded`,但不像 `menu` 那样声明弹出。 */
|
|
59
|
+
expanded?: boolean;
|
|
60
|
+
/** 一排选择里选中的那个——筛选、视图。不是一组里的按钮不传。 */
|
|
61
|
+
pressed?: boolean;
|
|
62
|
+
className?: string;
|
|
63
|
+
type?: "button" | "submit";
|
|
64
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个会转的方向箭头,专给「按下去会展开点什么」的按钮用。
|
|
3
|
+
*
|
|
4
|
+
* 每处各写一遍 `<ChevronDown className={open ? "rotate-180" : ""} />` 的话,有的加了过渡有的没加,
|
|
5
|
+
* 加了的时长也各不相同。结果是同一个手势在不同的角落表现不同——一处的箭头滑过去,另一处「啪」地
|
|
6
|
+
* 跳过去,而这两下是同一件事:一张单子打开了。
|
|
7
|
+
*
|
|
8
|
+
* 转多少度由 `from` 决定,因为收起时的朝向不止一种:下拉菜单的箭头向下、展开到 180 度朝上;
|
|
9
|
+
* 树和折叠块的箭头向右、展开到 90 度朝下。两种都在这里,调用方只说自己是哪一种。
|
|
10
|
+
*
|
|
11
|
+
* 只画箭头,不画按钮。它是按钮里的一个字形,而不是一个控件——`aria-hidden`,名字归按钮自己的
|
|
12
|
+
* `aria-label` 管。
|
|
13
|
+
*/
|
|
14
|
+
export declare function Caret({ open,
|
|
15
|
+
/** 收起时箭头朝哪儿:`down` 展开到朝上(下拉),`right` 展开到朝下(树、折叠块)。 */
|
|
16
|
+
from, size, strokeWidth, className,
|
|
17
|
+
/** 代码预览那种自带配色的表面上,颜色是算出来的而不是 token。 */
|
|
18
|
+
style, }: {
|
|
19
|
+
open: boolean;
|
|
20
|
+
from?: "down" | "right";
|
|
21
|
+
size?: number;
|
|
22
|
+
strokeWidth?: number;
|
|
23
|
+
className?: string;
|
|
24
|
+
style?: React.CSSProperties;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自己画的选中标记。
|
|
3
|
+
*
|
|
4
|
+
* 原生复选框带着宿主系统的样子:macOS 上是 Aqua,Windows 上是 Fluent,哪个都和周围 ink / accent 的
|
|
5
|
+
* 卡片对不上。一个标记,两种形状。
|
|
6
|
+
*/
|
|
7
|
+
export declare function ChoiceMark({ checked, kind, indeterminate, className, }: {
|
|
8
|
+
checked: boolean;
|
|
9
|
+
kind: "checkbox" | "radio";
|
|
10
|
+
indeterminate?: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MouseEvent, ReactNode } from "react";
|
|
2
|
+
import type { DataAttributes } from "./Button.tsx";
|
|
3
|
+
/**
|
|
4
|
+
* 窗格标签条里的一个标签:用来挑它的名字,和关掉它的 ✕。
|
|
5
|
+
*
|
|
6
|
+
* 终端和文件窗格共用这一份,各写一份的话会慢慢走样——一个标签被读成标签,另一个被读成普通按钮。
|
|
7
|
+
* `data-*` 落在外层上,测试按它找标签。
|
|
8
|
+
*
|
|
9
|
+
* ✕ 只出现在指着的那个和当前那个标签上。每个标签都带一个的话,三个标签的一条就成了六个目标,关闭
|
|
10
|
+
* 按钮和名字一样响——而这一条的全部用处就是让人按名字挑。
|
|
11
|
+
*/
|
|
12
|
+
export declare function ClosableTab({ children, current, onSelect, onClose, closeLabel, tip, onContextMenu, className, labelClassName, ...data }: DataAttributes & {
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
current: boolean;
|
|
15
|
+
onSelect: () => void;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
/** 说出关的是哪个标签:一排同样的「关闭」按钮对读屏什么都没说。 */
|
|
18
|
+
closeLabel: string;
|
|
19
|
+
tip?: string;
|
|
20
|
+
onContextMenu?: (event: MouseEvent<HTMLDivElement>) => void;
|
|
21
|
+
className?: string;
|
|
22
|
+
labelClassName?: string;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 变化时会走过去、刚出现时直接出现的数。
|
|
3
|
+
*
|
|
4
|
+
* 这个区别就是它做成组件、而不是在调用处直接用 `useCountUp` 的全部理由。hook 必须在调用方的提前
|
|
5
|
+
* return 之前调用,于是真实的数还在读的时候它拿到的是 0——等数落地,再从 0 动画上去。打开一个面板,
|
|
6
|
+
* 计数在半秒里从 0 数到 200,好像你看着的时候有两百个文件被改了。
|
|
7
|
+
*
|
|
8
|
+
* 在值已知的地方挂载,「第一个值」就是第一个*真实*的值。调用方有东西可显示时才渲染它,所以它的初始
|
|
9
|
+
* 状态就是真实的数,没有起点可走。之后的每次读数都是真的变化,动起来正是为了这个。曲线和为什么不往下
|
|
10
|
+
* 走,见 `useCountUp`。
|
|
11
|
+
*/
|
|
12
|
+
export declare function CountUp({ value, className,
|
|
13
|
+
/** 走动中的数怎么写。默认是四舍五入的整数。 */
|
|
14
|
+
format, bidirectional, ms, ...rest }: {
|
|
15
|
+
value: number;
|
|
16
|
+
className?: string;
|
|
17
|
+
format?: (shown: number) => string;
|
|
18
|
+
/** 往下也走——见 `useCountUp`。给按更短的时段重算的读数。 */
|
|
19
|
+
bidirectional?: boolean;
|
|
20
|
+
ms?: number;
|
|
21
|
+
} & Omit<React.ComponentProps<"span">, "className" | "children">): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub 的标志,每个仓库页上的那个。
|
|
3
|
+
*
|
|
4
|
+
* 16px 的 `mark-github` octicon,和 https://github.com 自己导航里画的一模一样,而不是 lucide 的图形:
|
|
5
|
+
* lucide 去掉了品牌图标,而仓库链接旁边放一个通用的「代码」或「分支」符号,得读了提示才知道它通向哪——
|
|
6
|
+
* 这个标志在读任何字之前就说了是 GitHub。
|
|
7
|
+
* 用 `currentColor`,在哪种主题下都取它所在位置的字色。
|
|
8
|
+
*/
|
|
9
|
+
export declare function GitHubMark({ size, className }: {
|
|
10
|
+
size?: number;
|
|
11
|
+
className?: string;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { DataAttributes } from "./Button.tsx";
|
|
2
|
+
/**
|
|
3
|
+
* 标签是一个图标的按钮。
|
|
4
|
+
*
|
|
5
|
+
* 各个工具栏各写各的,会长出五种高度、三种圆角,按下的反馈从没有到缩小 10% 都有。缩小是有意去掉的——
|
|
6
|
+
* 一个在接触那一刻从指针底下跳开的控件读起来不稳,在这么小的尺寸上那是一下晃动而不是按下。按下用底色
|
|
7
|
+
* 深一档表示,真的按钮就是这样:它待在原地,只是换了状态。
|
|
8
|
+
*
|
|
9
|
+
* 标签同时是悬停提示和无障碍名,调用方没法只给一个——只有图标的工具栏就是这样变得读屏读不出来的。
|
|
10
|
+
* 类名组合在 `@plume/styles` 的 `iconButton`。
|
|
11
|
+
*/
|
|
12
|
+
export declare function IconButton({ label, ariaLabel, icon, onClick, active, disabled, emphasis, badge, explainDisabled, tone, size, tipSide, menu, expanded, className, ...data }: DataAttributes & {
|
|
13
|
+
label: string;
|
|
14
|
+
/**
|
|
15
|
+
* 无障碍名要比悬停提示多说一点时用。
|
|
16
|
+
*
|
|
17
|
+
* 一列同样的按钮在读屏里是同一个词念了一遍又一遍;无障碍名带上是哪一行(`归档会话「a」`),
|
|
18
|
+
* 悬停提示仍然短,因为指针已经在那一行上了。不传时 `label` 两样都是,这是通常的情况。
|
|
19
|
+
*/
|
|
20
|
+
ariaLabel?: string;
|
|
21
|
+
icon: React.ReactNode;
|
|
22
|
+
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
23
|
+
/** 按住 / 开着,给「区分大小写」这类开关。 */
|
|
24
|
+
active?: boolean;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* 一排里现在值得按的那一个。
|
|
28
|
+
*
|
|
29
|
+
* 满色的字,对比一排平时淡灰的字,这是界面里已经用来表示「就是这个」的对比。不是实心或彩色按钮:
|
|
30
|
+
* 长出 primary 按钮的工具栏就不再是工具栏了。
|
|
31
|
+
*/
|
|
32
|
+
emphasis?: boolean;
|
|
33
|
+
/** 角上的计数。零和 null 都画成什么都没有。 */
|
|
34
|
+
badge?: number | null;
|
|
35
|
+
/**
|
|
36
|
+
* 禁用时也显示悬停提示,因为标签说明的正是为什么禁用。
|
|
37
|
+
*
|
|
38
|
+
* 默认关,对大多数工具栏默认是对的:一个因为显而易见的原因变灰的控件,再冒一个泡重复它的名字
|
|
39
|
+
* 没有意义。原因本身才是重点的地方就不对了——「当前分支没有上游」正是悬停在一个按不动的拉取按钮上
|
|
40
|
+
* 的人想知道的,没有这个他们只能得到一片沉默,自己去猜。
|
|
41
|
+
*/
|
|
42
|
+
explainDisabled?: boolean;
|
|
43
|
+
tone?: "default" | "danger";
|
|
44
|
+
/**
|
|
45
|
+
* `xs` 20px,是窗格标题行和一行小字的高度;圆角跟着降到 6px,这个尺寸的按钮都这样。`composer`
|
|
46
|
+
* 跟着主输入框自己的控件高度走,那个高度变了,它那一排仍然是一行。
|
|
47
|
+
*/
|
|
48
|
+
size?: "xs" | "sm" | "md" | "composer";
|
|
49
|
+
tipSide?: "top" | "bottom";
|
|
50
|
+
/** 会打开一个菜单;值是它现在开没开。和 `Button` 的一样。 */
|
|
51
|
+
menu?: boolean;
|
|
52
|
+
/** 原地展开或收起一段。和 `Button` 的一样。 */
|
|
53
|
+
expanded?: boolean;
|
|
54
|
+
className?: string;
|
|
55
|
+
}): import("react").JSX.Element;
|