@linkdesk/ui 0.1.0 → 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.
@@ -2,18 +2,29 @@
2
2
  * E5.8#99:实心 accent 动作按钮(按钮双轨制实心轨)——动作/提交,对标 VS Code。
3
3
  * ghost 轨(选择/分组)= SegmentedRadio。双轨约定:选什么用 ghost 分段,做什么用实心按钮。
4
4
  *
5
+ * E6#30.14 variant——语义动作层级(10-市场UI拥有权.md §四·一:安装=success 填充 / 卸载=danger /
6
+ * 禁用=ghost;视觉源 = mockup 02 st-*):
7
+ * 缺省 = 实心 accent(现状不变)——主操作
8
+ * success = 实心绿(--success)——正面主操作(安装 / 启用)
9
+ * danger = 破坏性次级(danger 文本+边,非实心——destructive 不抢主操作眼)
10
+ * ghost = 次级透明钮(text-secondary + separator 边)
11
+ * 变体样式全走语义/主题 token,零硬编码 hex(硬约束 1)。variant = props 非配置项(零新配置)。
12
+ *
5
13
  * 抽壳动机:动作按钮此前是 settings 插件 CSS 类 .settings-action-btn,却被壳共享组件
6
14
  * FilePathInput 消费——壳组件依赖插件 CSS 的倒置耦合。收编壳后 shell 组件零依赖插件样式,
7
15
  * 第三方插件直接用 <Button> 即得壳动作按钮(不用拷 CSS)。
8
16
  *
9
- * 消费方:settings renderHint:"action" 命令按钮、背景图三态按钮、FilePathInput「…」按钮。
17
+ * 消费方:settings renderHint:"action" 命令按钮、背景图三态按钮、FilePathInput「…」按钮、
18
+ * marketplace 详情 action bar(禁用/启用/卸载,E6#30.14c)。
10
19
  */
20
+ type ButtonVariant = "success" | "danger" | "ghost";
11
21
  interface ButtonProps {
12
22
  children: React.ReactNode;
13
23
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
14
24
  disabled?: boolean;
15
25
  title?: string;
16
26
  type?: "button" | "submit" | "reset";
27
+ variant?: ButtonVariant;
17
28
  }
18
- declare function Button({ children, onClick, disabled, title, type }: ButtonProps): import("react").JSX.Element;
29
+ declare function Button({ children, onClick, disabled, title, type, variant }: ButtonProps): import("react").JSX.Element;
19
30
  export default Button;
@@ -9,7 +9,7 @@
9
9
  * 选择下拉项 / Enter / 失焦(文本有变更)→ onChange(新值);文本无变更 → 不触发。
10
10
  *
11
11
  * 归一化:壳组件库范畴(components/shared/)——壳视图 + 插件共用。
12
- * 新插件用可输入下拉 → import Combobox from "@src/components/shared/combobox/Combobox"。
12
+ * 壳内部引用 @src 源码;插件作者(含内置插件 E6#54c)→ `import { Combobox } from "@linkdesk/ui"`。
13
13
  * 下拉面板视觉复用 SelectBox(.selectbox-dropdown/list/item/empty 类)——一个视觉语言
14
14
  * 一处写,jscpd 0 克隆门禁:Combobox.css 只定义 field/input/arrow,下拉视觉零重写。
15
15
  */
@@ -0,0 +1,33 @@
1
+ /**
2
+ * useClickPreview — 单击预览 / 双击锁定归一化 hook。
3
+ * E4V#28e:从 FileTreeNode 提取——任何树/列表组件复用同一交互。
4
+ * E6#15h 归位:@linkdesk/ui 零件(本文件 = 壳单一源码副本;任何插件含第三方 `import { useClickPreview } from "@linkdesk/ui"`)。
5
+ * 详见 08-共享hook归位.md。
6
+ *
7
+ * 对标 VS Code explorer 的文件点击行为:
8
+ * - 单击(mousedown 启动 250ms 定时器)→ 预览标签页(斜体,可替换)
9
+ * - 双击(e.detail === 2)→ 锁定标签页(正体,不再替换)
10
+ * - disabled = 目录节点——不启动定时器,不响应双击锁定
11
+ *
12
+ * @param onPreview 预览回调——定时器到期后触发
13
+ * @param onPin 锁定回调——双击时触发
14
+ * @param disabled 禁用预览/锁定(如目录节点),默认 false
15
+ * @param delay 双击检测窗口(ms),默认 250
16
+ * @returns { handleMouseDown, handleClick }——展开到行级事件处理器
17
+ */
18
+ interface UseClickPreviewOptions {
19
+ onPreview: () => void;
20
+ onPin: () => void;
21
+ disabled?: boolean;
22
+ delay?: number;
23
+ }
24
+ export declare function useClickPreview({ onPreview, onPin, disabled, delay }: UseClickPreviewOptions): {
25
+ handleMouseDown: (e: {
26
+ button?: number;
27
+ }) => void;
28
+ handleClick: (e: {
29
+ detail: number;
30
+ button?: number;
31
+ }) => void;
32
+ };
33
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * useClipboardKeys — 池侧 Ctrl/Cmd+C / X / V 剪贴板键归一化 hook。
3
+ * E5.8#24.8.3 定案(用户拍板路径 2):共享 hook 消除每插件重复的剪贴板键处理。
4
+ * E6#15h 归位:@linkdesk/ui 零件(本文件 = 壳单一源码副本;任何插件含第三方 `import { useClipboardKeys } from "@linkdesk/ui"`)。
5
+ * 详见 08-共享hook归位.md。
6
+ *
7
+ * 背景(教训链——看 memory keyboard-router-before-input-event):
8
+ * 壳级剪贴板键已删(E5.8#24.8.1)——主进程 keyCache 命中 = 无条件 preventDefault,
9
+ * 在池 WCV 收到键之前吞掉,且不认 when/可编辑状态 → 池内 Monaco 原生复制粘贴全死。
10
+ * 正解 = 池侧自处理:插件在自己 React keydown 里处理文本键。DOM 焦点天然分区——
11
+ * 文件树聚焦才收键,Monaco 聚焦收不到,多插件各干各的 ctrl+c 互不打扰,
12
+ * 不需要 when、不需要冲突检测。
13
+ *
14
+ * 机制与语义分离:
15
+ * 机制(ctrl/meta 检测 + preventDefault + 键映射)归一在此 hook——一处实现一处修。
16
+ * 语义(复制/剪切/粘贴各自做什么)由插件声明式交出——AI 只填回调,零追踪影响面。
17
+ *
18
+ * 焦点守卫天然成立:本 hook 返回的 handler 挂在插件容器 onKeyDown 上——
19
+ * 只有插件聚焦才收到事件;可编辑子元素(如重命名 InlineInput)须自行 stopPropagation,
20
+ * 否则打字时 Ctrl+C/V/X 冒泡到容器(文件树已如此处理)。
21
+ *
22
+ * @param onCopy 复制回调(Ctrl+C / Cmd+C)
23
+ * @param onCut 剪切回调(Ctrl+X / Cmd+X)
24
+ * @param onPaste 粘贴回调(Ctrl+V / Cmd+V)
25
+ * @returns `(e) => boolean`——在消费方 onKeyDown 中组合:返回 true 表示该键已被消费
26
+ * (调用方应 return,勿继续走其他逻辑);false 表示未命中剪贴板键。
27
+ */
28
+ export interface UseClipboardKeysCallbacks {
29
+ onCopy?: () => void;
30
+ onCut?: () => void;
31
+ onPaste?: () => void;
32
+ }
33
+ export declare function useClipboardKeys(callbacks: UseClipboardKeysCallbacks): (e: React.KeyboardEvent) => boolean;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * useDebouncedInput — 防抖输入归一化 hook。
3
+ * E3.6 E36#7.3c 提取:本地 state 即时响应 + 模块级/外部 state 防抖同步。
4
+ * E6#15h 归位:@linkdesk/ui 零件(本文件 = 壳单一源码副本;任何插件含第三方 `import { useDebouncedInput } from "@linkdesk/ui"`)。
5
+ * 详见 08-共享hook归位.md。
6
+ *
7
+ * 使用场景:输入框值需要即时反馈(不卡打字),但下游过滤/搜索走防抖(不每键重渲染)。
8
+ * 命令面板流畅就是因为输入是本地 state——这个 hook 把同样的模式归一化。
9
+ *
10
+ * @param setExternal 防抖后同步到的外部 setter(如模块级 setSearch)
11
+ * @param debounceMs 防抖毫秒数,默认 150
12
+ * @returns { value, onChange, onClear }——直接展开到 <input> 上
13
+ */
14
+ export declare function useDebouncedInput(setExternal: (value: string) => void, debounceMs?: number): {
15
+ value: string;
16
+ onChange: (next: string) => void;
17
+ onClear: () => void;
18
+ };
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- .button{background:var(--accent);color:var(--text-on-accent);border:none;border-radius:var(--radius-sm);padding:4px 12px;font-size:var(--font-size-sm);cursor:pointer;white-space:nowrap}.button:hover{opacity:.85}.button:disabled{opacity:.5;cursor:default}.colorpicker-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--z-overlay-backdrop)}.colorpicker-panel{position:fixed;z-index:var(--z-overlay);background:var(--bg-window);border:1px solid var(--separator);border-radius:var(--radius-md);padding:12px;box-shadow:var(--shadow-float);display:flex;flex-wrap:wrap;width:232px;gap:8px;top:50%;left:50%;transform:translate(-50%,-50%)}.colorpicker-panel[style]{transform:none}.colorpicker-sv{width:180px;height:150px;border-radius:var(--radius-sm);position:relative;cursor:crosshair;overflow:hidden;-webkit-user-select:none;user-select:none}.colorpicker-sv-white{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to right,#fff,transparent)}.colorpicker-sv-black{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000,transparent)}.colorpicker-sv-cursor{position:absolute;width:10px;height:10px;border:2px solid #fff;border-radius:var(--radius-full);box-shadow:var(--shadow-tiny);transform:translate(-50%,-50%);pointer-events:none}.colorpicker-hue{width:180px;height:14px;border-radius:var(--radius-md);position:relative;cursor:pointer;-webkit-user-select:none;user-select:none;background:linear-gradient(to right,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.colorpicker-hue-cursor{position:absolute;top:-2px;width:4px;height:18px;background:#fff;border-radius:var(--radius-xs);box-shadow:var(--shadow-tiny);transform:translate(-50%);pointer-events:none}.colorpicker-footer{display:flex;align-items:center;gap:6px;width:100%}.colorpicker-preview{width:28px;height:28px;border-radius:var(--radius-sm);border:1px solid var(--separator);flex-shrink:0}.colorpicker-hex{flex:1;min-width:0;height:calc(26px * var(--ui-scale));padding:2px 6px;border:1px solid var(--separator);border-radius:var(--radius-sm);background:var(--bg-input);color:var(--text-primary);font-family:var(--font-mono);font-size:var(--font-size-sm);outline:none;box-sizing:border-box}.colorpicker-hex:focus{border-color:var(--accent)}.colorpicker-ok{height:calc(26px * var(--ui-scale));padding:0 12px;background:var(--accent);color:var(--text-on-accent);border:none;border-radius:var(--radius-sm);font-size:var(--font-size-sm);cursor:pointer;flex-shrink:0}.colorpicker-ok:hover{background:var(--accent-hover)}.colorpicker-presets{width:100%;display:flex;gap:6px;flex-wrap:wrap;padding-top:4px;border-top:1px solid var(--separator)}.colorpicker-preset{width:18px;height:18px;border-radius:var(--radius-full);border:1px solid var(--separator);cursor:pointer;transition:transform .1s}.colorpicker-preset:hover{transform:scale(1.2);border-color:var(--accent)}.combobox{position:relative;display:inline-block;min-width:100px}.combobox-field{display:flex;align-items:center;gap:4px;padding:3px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-md);line-height:1.6;cursor:text}.combobox-field:hover:not(.selectbox-disabled){border-color:var(--accent)}.combobox.selectbox-open .combobox-field{border-color:var(--accent)}.combobox-input{flex:1;min-width:0;padding:0;background:transparent;border:none;outline:none;color:inherit;font:inherit;line-height:1.6}.combobox-input::placeholder{color:var(--text-muted)}.combobox-input:disabled{opacity:.5}.selectbox{position:relative;display:inline-block;min-width:100px;-webkit-user-select:none;user-select:none}.selectbox-trigger{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;padding:3px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-md);line-height:1.6;cursor:pointer;font-family:inherit;text-align:left}.selectbox-trigger:hover:not(:disabled){border-color:var(--accent)}.selectbox-trigger:disabled{opacity:.5;cursor:default}.selectbox-open .selectbox-trigger{border-color:var(--accent)}.selectbox-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.selectbox-swatch{display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:50%;border:1px solid color-mix(in srgb,var(--text-primary) 35%,transparent);vertical-align:middle;flex-shrink:0}.selectbox-arrow{flex-shrink:0;font-size:var(--font-size-sm);transition:transform .15s ease}.selectbox-arrow-up{transform:rotate(180deg)}.selectbox-dropdown{position:absolute;top:100%;left:0;margin-top:2px;background:var(--bg-window);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-pop);overflow:hidden;z-index:var(--z-dropdown);max-height:260px;max-width:calc(100vw - 24px);display:flex;flex-direction:column;animation:selectbox-in .1s ease-out}@keyframes selectbox-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.selectbox-search{padding:4px;border-bottom:1px solid var(--separator)}.selectbox-search-input{width:100%;padding:2px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-sm);font-family:inherit;outline:none;box-sizing:border-box}.selectbox-search-input:focus{border-color:var(--accent)}.selectbox-list{list-style:none;margin:0;padding:2px 0;overflow-y:auto;outline:none}.selectbox-item{padding:3px 8px;font-size:var(--font-size-md);line-height:1.6;color:var(--text-primary);cursor:pointer}.selectbox-item-focus{background:var(--accent);color:var(--text-on-accent)}.selectbox-item-selected:not(.selectbox-item-focus){background:var(--bg-selection)}.selectbox-empty{padding:6px 8px;font-size:var(--font-size-sm);color:var(--text-muted);text-align:center}.selectbox-disabled{pointer-events:none}.ctx-menu{position:fixed;min-width:140px;max-width:280px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-hairline),var(--context-menu-shadow);padding:4px 0;overflow:hidden;outline:none;opacity:0;transform:scale(.96);transform-origin:top left;transition:opacity .15s ease-out,transform .15s ease-out}.ctx-menu:focus-visible{outline:none}.ctx-menu.show{opacity:1;transform:scale(1)}.ctx-item{display:flex;align-items:center;gap:8px;padding:6px 12px;font-size:var(--font-size-md);font-weight:400;line-height:1.6;color:var(--text-primary);cursor:pointer;transition:background 60ms;-webkit-user-select:none;user-select:none}.ctx-item:hover,.ctx-item.focused{background:var(--tab-hover-bg);color:var(--text-primary);box-shadow:inset 2px 0 0 var(--accent)}.ctx-item-icon{flex-shrink:0;width:calc(16px * var(--ui-scale));height:calc(16px * var(--ui-scale));font-size:var(--font-size-lg);display:flex;align-items:center;justify-content:center;opacity:.75}.ctx-item:hover .ctx-item-icon,.ctx-item.focused .ctx-item-icon{opacity:1;color:var(--accent)}.ctx-item-shortcut{flex-shrink:0;margin-left:12px;font-size:var(--font-size-xs);opacity:.6;font-family:var(--font-mono);letter-spacing:.2px}.ctx-item:hover .ctx-item-shortcut,.ctx-item.focused .ctx-item-shortcut{opacity:.9;color:var(--text-secondary)}.ctx-item-check{flex-shrink:0;width:16px;font-size:var(--font-size-sm);color:var(--accent);display:flex;align-items:center}.ctx-item-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ctx-divider{height:1px;background:var(--separator);margin:4px 12px}.ctx-item-danger{color:var(--danger)}.ctx-item-danger .ctx-item-icon{opacity:1}.ctx-item-danger:hover,.ctx-item-danger.focused{background:var(--tab-hover-bg);color:var(--danger);box-shadow:inset 2px 0 0 var(--danger)}.ctx-item-danger:hover .ctx-item-shortcut,.ctx-item-danger.focused .ctx-item-shortcut{opacity:.9;color:var(--text-secondary)}.form-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:var(--font-size-sm);color:var(--text-primary)}.form-row>label,.form-row>.form-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-row>.toggle,.form-row>.input,.form-row>select,.form-row>.form-control{flex-shrink:0}.number-input{display:inline-flex;align-items:center;gap:0}.number-input-btn{display:flex;align-items:center;justify-content:center;width:calc(22px * var(--ui-scale));height:calc(24px * var(--ui-scale));padding:0;border:1px solid var(--border);background:var(--bg-input);color:var(--text-primary);font-size:var(--font-size-lg);line-height:1;cursor:pointer;transition:background .15s,border-color .15s;-webkit-user-select:none;user-select:none}.number-input-btn:first-child{border-radius:var(--radius-sm) 0 0 var(--radius-sm);border-right:none}.number-input-btn:last-child{border-radius:0 var(--radius-sm) var(--radius-sm) 0;border-left:none}.number-input-btn:hover:not(:disabled){background:var(--tab-hover-bg)}.number-input-btn:active:not(:disabled){background:var(--accent);color:var(--text-on-accent)}.number-input-btn:disabled{opacity:.3;cursor:default}.number-input-field{border-radius:0;text-align:center;width:44px}.number-input-unit{margin:0 6px 0 8px;color:var(--text-muted);font-size:var(--font-size-sm);line-height:1;-webkit-user-select:none;user-select:none}.segmented-radio{display:flex;gap:4px}.segmented-radio__option{display:flex;flex-direction:column;align-items:center;gap:4px;padding:4px 8px;background:transparent;border:1px solid var(--separator);border-radius:var(--radius-sm);cursor:pointer;transition:border-color .12s ease,background .12s ease}.segmented-radio__option:hover{border-color:var(--text-muted);background:var(--hover-overlay)}.segmented-radio__option:focus-visible{outline:1px solid var(--accent);outline-offset:1px}.segmented-radio__option.is-selected{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent)}.segmented-radio__label{font-size:var(--font-size-sm);color:var(--text-secondary);white-space:nowrap}.segmented-radio__option.is-selected .segmented-radio__label{color:var(--text-primary)}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:130px;height:4px;margin:0;border-radius:var(--radius-sm);background:linear-gradient(to right,var(--accent) var(--slider-pct, 0%),var(--border) var(--slider-pct, 0%));cursor:pointer;outline-offset:4px}.slider:disabled{opacity:.4;cursor:default}.slider::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:12px;height:12px;border-radius:50%;background:var(--text-primary);box-shadow:var(--shadow-tiny);cursor:grab}.slider::-webkit-slider-thumb:active{cursor:grabbing}.theme-picker{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;width:100%}.theme-card{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;cursor:pointer;background:var(--bg-card);padding:0;text-align:left;color:inherit;font:inherit;transition:border-color .15s ease,transform .15s ease}.theme-card:hover{border-color:var(--separator);transform:translateY(-1px)}.theme-card:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.theme-card.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.theme-preview{height:44px;display:flex;align-items:center;gap:3px;padding:8px;overflow:hidden}.theme-preview .pv-bar{width:26px;height:12px;border-radius:var(--radius-xs)}.theme-preview .pv-dots{display:flex;gap:3px}.theme-preview .pv-dot{width:12px;height:12px;border-radius:50%;border:1px solid color-mix(in srgb,var(--text-primary) 35%,transparent)}.theme-card .tname{padding:6px 8px;font-size:var(--font-size-xs);color:var(--text-secondary);display:flex;align-items:center;justify-content:space-between;gap:4px;overflow:hidden}.theme-card.active .tname{color:var(--text-primary)}.theme-card .tname-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.theme-card .badge{font-size:var(--font-size-2xs);color:var(--accent);white-space:nowrap}.theme-picker-empty{color:var(--text-muted);font-size:var(--font-size-sm);padding:8px 0}.toggle{width:36px;height:20px;border-radius:var(--radius-pill);background:var(--border);transition:background .15s;cursor:pointer;position:relative;flex-shrink:0}.toggle.on{background:var(--accent)}.toggle:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:var(--radius-pill);background:var(--toggle-knob);transition:transform .15s}.toggle.on:after{transform:translate(16px);background:var(--toggle-knob-on, var(--text-on-accent))}.toggle.disabled{opacity:.4;cursor:not-allowed}.inline-input{border:1px solid var(--border);background:var(--bg-input);color:var(--text-primary);font-family:inherit;outline:none;box-sizing:border-box;width:100%;transition:border-color .15s ease-out,box-shadow .15s ease-out}.inline-input:focus{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.inline-input--compact{height:calc(22px * var(--ui-scale));font-size:var(--font-size-sm);padding:0 4px}.inline-input--normal{height:calc(32px * var(--ui-scale));font-size:var(--font-size-md);padding:0 8px}
1
+ .badge{display:inline-flex;align-items:center;background:var(--badge-background);color:var(--badge-foreground);border-radius:var(--radius-sm);padding:1px 6px;font-size:var(--font-size-2xs);font-weight:500;line-height:1.4;white-space:nowrap;flex-shrink:0}.button{background:var(--accent);color:var(--text-on-accent);border:1px solid transparent;border-radius:var(--radius-sm);padding:4px 12px;font-size:var(--font-size-sm);cursor:pointer;white-space:nowrap}.button:hover:not(:disabled){opacity:.85}.button:disabled{opacity:.5;cursor:default}.button--success{background:var(--success);border-color:var(--success);color:var(--badge-text)}.button--ghost{background:transparent;border-color:var(--separator);color:var(--text-secondary)}.button--ghost:hover:not(:disabled){background:var(--hover-overlay);color:var(--text-primary);opacity:1}.button--danger{background:transparent;border-color:color-mix(in srgb,var(--danger) 45%,transparent);color:var(--danger)}.button--danger:hover:not(:disabled){background:color-mix(in srgb,var(--danger) 10%,transparent);border-color:color-mix(in srgb,var(--danger) 75%,transparent);opacity:1}.colorpicker-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--z-overlay-backdrop)}.colorpicker-panel{position:fixed;z-index:var(--z-overlay);background:var(--bg-window);border:1px solid var(--separator);border-radius:var(--radius-md);padding:12px;box-shadow:var(--shadow-float);display:flex;flex-wrap:wrap;width:232px;gap:8px;top:50%;left:50%;transform:translate(-50%,-50%)}.colorpicker-panel[style]{transform:none}.colorpicker-sv{width:180px;height:150px;border-radius:var(--radius-sm);position:relative;cursor:crosshair;overflow:hidden;-webkit-user-select:none;user-select:none}.colorpicker-sv-white{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to right,#fff,transparent)}.colorpicker-sv-black{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000,transparent)}.colorpicker-sv-cursor{position:absolute;width:10px;height:10px;border:2px solid #fff;border-radius:var(--radius-full);box-shadow:var(--shadow-tiny);transform:translate(-50%,-50%);pointer-events:none}.colorpicker-hue{width:180px;height:14px;border-radius:var(--radius-md);position:relative;cursor:pointer;-webkit-user-select:none;user-select:none;background:linear-gradient(to right,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.colorpicker-hue-cursor{position:absolute;top:-2px;width:4px;height:18px;background:#fff;border-radius:var(--radius-xs);box-shadow:var(--shadow-tiny);transform:translate(-50%);pointer-events:none}.colorpicker-footer{display:flex;align-items:center;gap:6px;width:100%}.colorpicker-preview{width:28px;height:28px;border-radius:var(--radius-sm);border:1px solid var(--separator);flex-shrink:0}.colorpicker-hex{flex:1;min-width:0;height:calc(26px * var(--ui-scale));padding:2px 6px;border:1px solid var(--separator);border-radius:var(--radius-sm);background:var(--bg-input);color:var(--text-primary);font-family:var(--font-mono);font-size:var(--font-size-sm);outline:none;box-sizing:border-box}.colorpicker-hex:focus{border-color:var(--accent)}.colorpicker-ok{height:calc(26px * var(--ui-scale));padding:0 12px;background:var(--accent);color:var(--text-on-accent);border:none;border-radius:var(--radius-sm);font-size:var(--font-size-sm);cursor:pointer;flex-shrink:0}.colorpicker-ok:hover{background:var(--accent-hover)}.colorpicker-presets{width:100%;display:flex;gap:6px;flex-wrap:wrap;padding-top:4px;border-top:1px solid var(--separator)}.colorpicker-preset{width:18px;height:18px;border-radius:var(--radius-full);border:1px solid var(--separator);cursor:pointer;transition:transform .1s}.colorpicker-preset:hover{transform:scale(1.2);border-color:var(--accent)}.combobox{position:relative;display:inline-block;min-width:100px}.combobox-field{display:flex;align-items:center;gap:4px;padding:3px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-md);line-height:1.6;cursor:text}.combobox-field:hover:not(.selectbox-disabled){border-color:var(--accent)}.combobox.selectbox-open .combobox-field{border-color:var(--accent)}.combobox-input{flex:1;min-width:0;padding:0;background:transparent;border:none;outline:none;color:inherit;font:inherit;line-height:1.6}.combobox-input::placeholder{color:var(--text-muted)}.combobox-input:disabled{opacity:.5}.selectbox{position:relative;display:inline-block;min-width:100px;-webkit-user-select:none;user-select:none}.selectbox-trigger{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;padding:3px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-md);line-height:1.6;cursor:pointer;font-family:inherit;text-align:left}.selectbox-trigger:hover:not(:disabled){border-color:var(--accent)}.selectbox-trigger:disabled{opacity:.5;cursor:default}.selectbox-open .selectbox-trigger{border-color:var(--accent)}.selectbox-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.selectbox-swatch{display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:50%;border:1px solid color-mix(in srgb,var(--text-primary) 35%,transparent);vertical-align:middle;flex-shrink:0}.selectbox-arrow{flex-shrink:0;font-size:var(--font-size-sm);transition:transform .15s ease}.selectbox-arrow-up{transform:rotate(180deg)}.selectbox-dropdown{position:absolute;top:100%;left:0;margin-top:2px;background:var(--bg-window);border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-pop);overflow:hidden;z-index:var(--z-dropdown);max-height:260px;max-width:calc(100vw - 24px);display:flex;flex-direction:column;animation:selectbox-in .1s ease-out}@keyframes selectbox-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.selectbox-search{padding:4px;border-bottom:1px solid var(--separator)}.selectbox-search-input{width:100%;padding:2px 6px;background:var(--bg-input);color:var(--text-primary);border:1px solid var(--border);border-radius:var(--radius-xs);font-size:var(--font-size-sm);font-family:inherit;outline:none;box-sizing:border-box}.selectbox-search-input:focus{border-color:var(--accent)}.selectbox-list{list-style:none;margin:0;padding:2px 0;overflow-y:auto;outline:none}.selectbox-item{padding:3px 8px;font-size:var(--font-size-md);line-height:1.6;color:var(--text-primary);cursor:pointer}.selectbox-item-focus{background:var(--accent);color:var(--text-on-accent)}.selectbox-item-selected:not(.selectbox-item-focus){background:var(--bg-selection)}.selectbox-empty{padding:6px 8px;font-size:var(--font-size-sm);color:var(--text-muted);text-align:center}.selectbox-disabled{pointer-events:none}.ctx-menu{position:fixed;min-width:140px;max-width:280px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-hairline),var(--context-menu-shadow);padding:4px 0;overflow:hidden;outline:none;opacity:0;transform:scale(.96);transform-origin:top left;transition:opacity .15s ease-out,transform .15s ease-out}.ctx-menu:focus-visible{outline:none}.ctx-menu.show{opacity:1;transform:scale(1)}.ctx-item{display:flex;align-items:center;gap:8px;padding:6px 12px;font-size:var(--font-size-md);font-weight:400;line-height:1.6;color:var(--text-primary);cursor:pointer;transition:background 60ms;-webkit-user-select:none;user-select:none}.ctx-item:hover,.ctx-item.focused{background:var(--tab-hover-bg);color:var(--text-primary);box-shadow:inset 2px 0 0 var(--accent)}.ctx-item-icon{flex-shrink:0;width:calc(16px * var(--ui-scale));height:calc(16px * var(--ui-scale));font-size:var(--font-size-lg);display:flex;align-items:center;justify-content:center;opacity:.75}.ctx-item:hover .ctx-item-icon,.ctx-item.focused .ctx-item-icon{opacity:1;color:var(--accent)}.ctx-item-shortcut{flex-shrink:0;margin-left:12px;font-size:var(--font-size-xs);opacity:.6;font-family:var(--font-mono);letter-spacing:.2px}.ctx-item:hover .ctx-item-shortcut,.ctx-item.focused .ctx-item-shortcut{opacity:.9;color:var(--text-secondary)}.ctx-item-check{flex-shrink:0;width:16px;font-size:var(--font-size-sm);color:var(--accent);display:flex;align-items:center}.ctx-item-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ctx-divider{height:1px;background:var(--separator);margin:4px 12px}.ctx-item-danger{color:var(--danger)}.ctx-item-danger .ctx-item-icon{opacity:1}.ctx-item-danger:hover,.ctx-item-danger.focused{background:var(--tab-hover-bg);color:var(--danger);box-shadow:inset 2px 0 0 var(--danger)}.ctx-item-danger:hover .ctx-item-shortcut,.ctx-item-danger.focused .ctx-item-shortcut{opacity:.9;color:var(--text-secondary)}.form-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:var(--font-size-sm);color:var(--text-primary)}.form-row>label,.form-row>.form-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.form-row>.toggle,.form-row>.input,.form-row>select,.form-row>.form-control{flex-shrink:0}.number-input{display:inline-flex;align-items:center;gap:0}.number-input-btn{display:flex;align-items:center;justify-content:center;width:calc(22px * var(--ui-scale));height:calc(24px * var(--ui-scale));padding:0;border:1px solid var(--border);background:var(--bg-input);color:var(--text-primary);font-size:var(--font-size-lg);line-height:1;cursor:pointer;transition:background .15s,border-color .15s;-webkit-user-select:none;user-select:none}.number-input-btn:first-child{border-radius:var(--radius-sm) 0 0 var(--radius-sm);border-right:none}.number-input-btn:last-child{border-radius:0 var(--radius-sm) var(--radius-sm) 0;border-left:none}.number-input-btn:hover:not(:disabled){background:var(--tab-hover-bg)}.number-input-btn:active:not(:disabled){background:var(--accent);color:var(--text-on-accent)}.number-input-btn:disabled{opacity:.3;cursor:default}.number-input-field{border-radius:0;text-align:center;width:44px}.number-input-unit{margin:0 6px 0 8px;color:var(--text-muted);font-size:var(--font-size-sm);line-height:1;-webkit-user-select:none;user-select:none}.segmented-radio{display:flex;gap:4px}.segmented-radio__option{display:flex;flex-direction:column;align-items:center;gap:4px;padding:4px 8px;background:transparent;border:1px solid var(--separator);border-radius:var(--radius-sm);cursor:pointer;transition:border-color .12s ease,background .12s ease}.segmented-radio__option:hover{border-color:var(--text-muted);background:var(--hover-overlay)}.segmented-radio__option:focus-visible{outline:1px solid var(--accent);outline-offset:1px}.segmented-radio__option.is-selected{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent)}.segmented-radio__label{font-size:var(--font-size-sm);color:var(--text-secondary);white-space:nowrap}.segmented-radio__option.is-selected .segmented-radio__label{color:var(--text-primary)}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:130px;height:4px;margin:0;border-radius:var(--radius-sm);background:linear-gradient(to right,var(--accent) var(--slider-pct, 0%),var(--border) var(--slider-pct, 0%));cursor:pointer;outline-offset:4px}.slider:disabled{opacity:.4;cursor:default}.slider::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:12px;height:12px;border-radius:50%;background:var(--text-primary);box-shadow:var(--shadow-tiny);cursor:grab}.slider::-webkit-slider-thumb:active{cursor:grabbing}.sle{display:flex;flex-direction:column;gap:4px;width:100%}.sle-row{display:flex;align-items:center;gap:6px;min-height:calc(24px * var(--ui-scale, 1));width:100%;box-sizing:border-box}.sle-glyph{font-size:var(--font-size-sm);color:var(--text-muted);flex-shrink:0}.sle-url{flex:1;min-width:0;font-family:var(--font-mono);font-size:var(--font-size-xs);color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sle-badge{flex-shrink:0;font-size:var(--font-size-2xs);color:var(--text-muted);background:var(--bg-window);padding:1px 4px;border-radius:3px;white-space:nowrap}.sle-lock{font-size:var(--font-size-sm);color:var(--text-muted);flex-shrink:0}.sle-del{display:flex;align-items:center;justify-content:center;width:calc(24px * var(--ui-scale, 1));height:calc(24px * var(--ui-scale, 1));padding:0;background:transparent;border:none;border-radius:3px;color:var(--text-muted);cursor:pointer;font-size:var(--font-size-sm);flex-shrink:0;transition:color .15s ease,background .15s ease}.sle-del:hover{color:var(--error);background:var(--hover-overlay)}.sle-add-row{display:flex;align-items:center;gap:6px;width:100%}.sle-input{flex:1;min-width:0;box-sizing:border-box;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 8px;color:var(--text-primary);font-family:var(--font-mono);font-size:var(--font-size-xs);transition:border-color .15s;outline:none}.sle-input:focus{border-color:var(--accent)}.sle-add-btn{flex-shrink:0;padding:3px 8px;border:1px solid var(--separator);border-radius:4px;background:transparent;color:var(--text-primary);cursor:pointer;font-size:var(--font-size-xs);font-family:inherit;white-space:nowrap}.sle-add-btn:hover:not(:disabled){background:var(--tab-hover-bg)}.sle-add-btn:disabled{opacity:.5;cursor:not-allowed}.sle-msg{display:block;font-size:var(--font-size-2xs);line-height:1.5;padding:0 2px}.sle-msg--error{color:var(--error)}.sle-msg--hint{color:var(--text-muted)}.theme-picker{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;width:100%}.theme-card{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;cursor:pointer;background:var(--bg-card);padding:0;text-align:left;color:inherit;font:inherit;transition:border-color .15s ease,transform .15s ease}.theme-card:hover{border-color:var(--separator);transform:translateY(-1px)}.theme-card:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.theme-card.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.theme-preview{height:44px;display:flex;align-items:center;gap:3px;padding:8px;overflow:hidden}.theme-preview .pv-bar{width:26px;height:12px;border-radius:var(--radius-xs)}.theme-preview .pv-dots{display:flex;gap:3px}.theme-preview .pv-dot{width:12px;height:12px;border-radius:50%;border:1px solid color-mix(in srgb,var(--text-primary) 35%,transparent)}.theme-card .tname{padding:6px 8px;font-size:var(--font-size-xs);color:var(--text-secondary);display:flex;align-items:center;justify-content:space-between;gap:4px;overflow:hidden}.theme-card.active .tname{color:var(--text-primary)}.theme-card .tname-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.theme-card .badge{font-size:var(--font-size-2xs);color:var(--accent);white-space:nowrap}.theme-picker-empty{color:var(--text-muted);font-size:var(--font-size-sm);padding:8px 0}.toggle{width:36px;height:20px;border-radius:var(--radius-pill);background:var(--border);transition:background .15s;cursor:pointer;position:relative;flex-shrink:0}.toggle.on{background:var(--accent)}.toggle:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:var(--radius-pill);background:var(--toggle-knob);transition:transform .15s}.toggle.on:after{transform:translate(16px);background:var(--toggle-knob-on, var(--text-on-accent))}.toggle.disabled{opacity:.4;cursor:not-allowed}.inline-input{border:1px solid var(--border);background:var(--bg-input);color:var(--text-primary);font-family:inherit;outline:none;box-sizing:border-box;width:100%;transition:border-color .15s ease-out,box-shadow .15s ease-out}.inline-input:focus{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.inline-input--compact{height:calc(22px * var(--ui-scale));font-size:var(--font-size-sm);padding:0 4px}.inline-input--normal{height:calc(32px * var(--ui-scale));font-size:var(--font-size-md);padding:0 8px}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /** @linkdesk/ui 公共类型入口(E6#54b 构建生成——勿手改;改导出面改 packages/linkdesk-ui/src/index.ts 后重跑 build) */
2
+ export { default as Badge } from "./badge/Badge";
2
3
  export { default as Button } from "./button/Button";
3
4
  export { default as ColorPicker } from "./color-picker/ColorPicker";
4
5
  export { default as Combobox } from "./combobox/Combobox";
@@ -11,11 +12,17 @@ export { default as NumberInput } from "./number-input/NumberInput";
11
12
  export { default as SegmentedRadio } from "./segmented-radio/SegmentedRadio";
12
13
  export { default as SelectBox } from "./select-box/SelectBox";
13
14
  export { default as Slider } from "./slider/Slider";
15
+ export { default as StringListEditor } from "./string-list-editor/StringListEditor";
14
16
  export { default as ThemePicker } from "./theme-picker/ThemePicker";
15
17
  export { default as Toggle } from "./toggle/Toggle";
16
18
  export { InlineInput } from "./inline-input/InlineInput";
17
19
  export { PluginIcon } from "./plugin-icon/PluginIcon";
20
+ export { default as OverlayPortal } from "./overlay-portal/OverlayPortal";
21
+ export { useClickPreview } from "./hooks/useClickPreview";
22
+ export { useClipboardKeys } from "./hooks/useClipboardKeys";
23
+ export { useDebouncedInput } from "./hooks/useDebouncedInput";
18
24
  export { inferSliderStep } from "./slider/sliderStep";
25
+ export { urlSourceKey } from "./string-list-editor/urlSourceKey";
19
26
  export type { InlineInputHandle } from "./inline-input/InlineInput";
20
27
  export type { ContextMenuProps } from "./context-menu/ContextMenu";
21
28
  export type { ManifestIconShape, ResolvedIcon } from "./plugin-icon/iconUtils";