@jetcrab/pi-desk-sdk 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +4 -2
- package/dist/browser.d.ts +388 -0
- package/dist/browser.js +66 -0
- package/dist/capabilities.d.ts +104 -0
- package/dist/capabilities.js +89 -0
- package/dist/entry.d.ts +137 -0
- package/dist/entry.js +11 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +14 -0
- package/dist/host-runtime/base.js +284 -0
- package/dist/host-runtime/markdown.js +130 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/react-base.d.ts +33 -0
- package/dist/react-base.js +120 -0
- package/dist/react-log.d.ts +12 -0
- package/dist/react-log.js +99 -0
- package/dist/react-markdown.d.ts +5 -0
- package/dist/react-markdown.js +16 -0
- package/dist/react-ui.d.ts +197 -0
- package/dist/react-ui.js +310 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +2 -0
- package/dist/session.d.ts +155 -0
- package/dist/session.js +167 -0
- package/dist/settings.d.ts +24 -0
- package/dist/settings.js +22 -0
- package/dist/shared.d.ts +31 -0
- package/dist/shared.js +11 -0
- package/package.json +118 -3
package/dist/react-ui.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu';
|
|
3
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
4
|
+
import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area';
|
|
5
|
+
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
6
|
+
import { EyeIcon, EyeOffIcon } from 'lucide-react';
|
|
7
|
+
import { cloneElement, isValidElement, useId, useState } from 'react';
|
|
8
|
+
const PLUGIN_UI_STYLES = `
|
|
9
|
+
[data-pi-desk-ui-root]{box-sizing:border-box;min-width:0;max-width:100%;container-type:inline-size;color:var(--pi-desk-plugin-foreground,var(--foreground));font:inherit;font-size:.875rem;line-height:1.5}
|
|
10
|
+
[data-pi-desk-ui-root] *,[data-pi-desk-ui-root] *::before,[data-pi-desk-ui-root] *::after{box-sizing:border-box}
|
|
11
|
+
.pi-desk-ui-panel-header{display:grid;gap:.35rem;min-width:0;border-bottom:1px solid var(--pi-desk-plugin-border,var(--border));padding:1rem}
|
|
12
|
+
.pi-desk-ui-panel-header-main{display:flex;min-width:0;align-items:flex-start;justify-content:space-between;gap:.75rem}.pi-desk-ui-panel-header-copy{display:grid;min-width:0;gap:.2rem}.pi-desk-ui-panel-header-title{margin:0;font-size:1.25rem;font-weight:600;line-height:1.4;color:inherit}.pi-desk-ui-panel-header-description{color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font-size:.875rem;line-height:1.5;overflow-wrap:anywhere}.pi-desk-ui-panel-header-actions{display:flex;flex:none;align-items:center;gap:.4rem}.pi-desk-ui-panel-header-meta{display:flex;min-width:0;align-items:center;gap:.4rem;flex-wrap:wrap}
|
|
13
|
+
.pi-desk-ui-panel-header-compact{gap:.25rem;padding:.75rem}.pi-desk-ui-panel-header-compact .pi-desk-ui-panel-header-title{font-size:.875rem}
|
|
14
|
+
.pi-desk-ui-section{display:grid;min-width:0;gap:.6rem}.pi-desk-ui-section-header{display:flex;min-width:0;align-items:flex-start;justify-content:space-between;gap:.75rem}.pi-desk-ui-section-copy{display:grid;min-width:0;gap:.2rem}.pi-desk-ui-section-title{margin:0;font-size:.875rem;font-weight:600;line-height:1.5;color:var(--pi-desk-plugin-foreground,var(--foreground))}.pi-desk-ui-section-description{font-size:.875rem;line-height:1.5;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}.pi-desk-ui-section-action{display:flex;flex:none;align-items:center}.pi-desk-ui-section-content{min-width:0}.pi-desk-ui-section-compact{gap:.5rem}
|
|
15
|
+
.pi-desk-ui-action-row{display:flex;min-width:0;align-items:center;gap:.5rem;flex-wrap:wrap}.pi-desk-ui-action-row-end{justify-content:flex-end}.pi-desk-ui-action-row-between{justify-content:space-between}
|
|
16
|
+
.pi-desk-ui-tabs{display:flex;min-width:0;align-items:center;gap:.5rem;flex-wrap:wrap;border-bottom:1px solid var(--pi-desk-plugin-border,var(--border))}
|
|
17
|
+
.pi-desk-ui-tab{display:inline-flex;min-height:2rem;align-items:center;justify-content:center;border:0;border-bottom:2px solid transparent;padding:.25rem .5rem;background:transparent;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font:inherit;font-size:.875rem;font-weight:500;cursor:pointer;outline:none;transition:background-color 150ms ease-out,color 150ms ease-out}
|
|
18
|
+
.pi-desk-ui-tab:hover{background:color-mix(in oklab,var(--foreground) 8%,transparent);color:var(--foreground)}
|
|
19
|
+
.pi-desk-ui-tab[data-active="true"]{border-bottom-color:var(--foreground);color:var(--foreground)}.pi-desk-ui-tab:focus-visible{outline:2px solid var(--pi-desk-plugin-ring,var(--ring));outline-offset:2px}.pi-desk-ui-tab:disabled{cursor:not-allowed;opacity:.5}
|
|
20
|
+
.pi-desk-ui-key-values{display:grid;min-width:0;gap:.5rem;margin:0}.pi-desk-ui-key-value{display:grid;min-width:0;grid-template-columns:minmax(5rem,auto) minmax(0,1fr) auto;align-items:start;gap:.3rem .65rem}.pi-desk-ui-key-value-label{color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font-size:.75rem;line-height:1.45}.pi-desk-ui-key-value-value{min-width:0;margin:0;font-size:.875rem;line-height:1.5;overflow-wrap:anywhere}.pi-desk-ui-key-value-action{display:flex;align-items:center}.pi-desk-ui-key-values-compact{gap:.35rem}.pi-desk-ui-key-values-compact .pi-desk-ui-key-value{grid-template-columns:minmax(3.5rem,auto) minmax(0,1fr) auto;gap:.2rem .5rem}.pi-desk-ui-key-values-compact .pi-desk-ui-key-value-label{font-size:.75rem}.pi-desk-ui-key-values-stacked .pi-desk-ui-key-value{grid-template-columns:minmax(0,1fr);gap:.1rem}.pi-desk-ui-key-values-stacked .pi-desk-ui-key-value-action{justify-self:start}
|
|
21
|
+
.pi-desk-ui-loading{display:flex;min-height:6rem;align-items:center;justify-content:center;gap:.5rem;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font-size:.875rem;text-align:center}.pi-desk-ui-loading-error{display:grid;gap:.6rem}.pi-desk-ui-spinner{width:1rem;height:1rem;animation:pi-desk-ui-spin .8s linear infinite;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}@keyframes pi-desk-ui-spin{to{transform:rotate(360deg)}}
|
|
22
|
+
.pi-desk-ui-split{display:grid;grid-template-columns:minmax(11rem,13.5rem) minmax(0,1fr);gap:1rem;align-items:start}
|
|
23
|
+
.pi-desk-ui-navigation,.pi-desk-ui-content{min-width:0;min-height:0}.pi-desk-ui-navigation{overflow:hidden}
|
|
24
|
+
.pi-desk-ui-list{display:grid;gap:.375rem;min-width:0}.pi-desk-ui-list-compact{gap:.25rem}
|
|
25
|
+
.pi-desk-ui-list-item{display:flex;width:100%;min-width:0;align-items:flex-start;gap:.625rem;border:1px solid transparent;border-radius:calc(var(--pi-desk-plugin-radius,var(--radius,.45rem)) + .25rem);padding:.7rem .75rem;background:transparent;color:inherit;text-align:left;font:inherit;cursor:pointer;outline:none;transition:background-color .15s,border-color .15s,color .15s}.pi-desk-ui-list-item-compact{gap:.45rem;border-radius:var(--pi-desk-plugin-radius,var(--radius,.45rem));padding:.5rem .55rem}
|
|
26
|
+
.pi-desk-ui-list-item:hover{background:var(--pi-desk-plugin-muted,var(--muted))}
|
|
27
|
+
.pi-desk-ui-list-item[aria-pressed="true"]{background:var(--accent);color:var(--accent-foreground)}
|
|
28
|
+
.pi-desk-ui-list-item[aria-pressed="true"]:hover{background:color-mix(in oklab,var(--accent),var(--foreground) 5%)}
|
|
29
|
+
.pi-desk-ui-list-item:focus-visible,.pi-desk-ui-button:focus-visible,.pi-desk-ui-control:focus-visible{outline:2px solid var(--pi-desk-plugin-ring,var(--ring));outline-offset:2px}
|
|
30
|
+
.pi-desk-ui-list-item:disabled,.pi-desk-ui-button:disabled,.pi-desk-ui-control:disabled{cursor:not-allowed;opacity:.5}
|
|
31
|
+
.pi-desk-ui-card{min-width:0;border:1px solid var(--pi-desk-plugin-border,var(--border));border-radius:.75rem;padding:1rem;background:var(--pi-desk-plugin-surface,var(--card));color:var(--pi-desk-plugin-surface-foreground,var(--card-foreground,var(--foreground)))}.pi-desk-ui-card-compact{border-radius:.5rem;padding:.75rem}
|
|
32
|
+
.pi-desk-ui-markdown{min-width:0;font-size:var(--chat-body-font-size,1rem);line-height:1.7;color:inherit}
|
|
33
|
+
.pi-desk-ui-markdown>*{margin-block:0}
|
|
34
|
+
.pi-desk-ui-markdown :where(p){margin-block:0;line-height:1.7}
|
|
35
|
+
.pi-desk-ui-markdown>:is(h1,h2,h3,h4,h5,h6){margin-block:0;font-weight:600;letter-spacing:-.015em}
|
|
36
|
+
.pi-desk-ui-markdown>h1{font-size:1.5rem;line-height:1.3}
|
|
37
|
+
.pi-desk-ui-markdown>h2{font-size:1.25rem;line-height:1.35}
|
|
38
|
+
.pi-desk-ui-markdown>h3{font-size:1.125rem;line-height:1.4}
|
|
39
|
+
.pi-desk-ui-markdown>h4{font-size:1rem;line-height:1.45}
|
|
40
|
+
.pi-desk-ui-markdown>h5{font-size:.9375rem;line-height:1.5}
|
|
41
|
+
.pi-desk-ui-markdown>h6{font-size:.875rem;line-height:1.5}
|
|
42
|
+
.pi-desk-ui-markdown>h1:not(:first-child){margin-block-start:1rem}
|
|
43
|
+
.pi-desk-ui-markdown>h2:not(:first-child){margin-block-start:.875rem}
|
|
44
|
+
.pi-desk-ui-markdown>h3:not(:first-child){margin-block-start:.75rem}
|
|
45
|
+
.pi-desk-ui-markdown>:is(h4,h5,h6):not(:first-child){margin-block-start:.625rem}
|
|
46
|
+
.pi-desk-ui-markdown>:is(h1,h2,h3,h4,h5,h6)+*{margin-block-start:.375rem}
|
|
47
|
+
.pi-desk-ui-markdown :where([data-streamdown="ordered-list"],[data-streamdown="unordered-list"]){margin-block:0}
|
|
48
|
+
.pi-desk-ui-markdown [data-streamdown="list-item"]{padding-block:.125rem;line-height:1.625}
|
|
49
|
+
.pi-desk-ui-markdown :where([data-streamdown="blockquote"]){margin-block:0;border-left-width:2px;padding-left:.75rem;line-height:1.6}
|
|
50
|
+
.pi-desk-ui-markdown>*+*{margin-block-start:.5rem}
|
|
51
|
+
.pi-desk-ui-markdown [data-streamdown="horizontal-rule"]{margin-block:.875rem}
|
|
52
|
+
.pi-desk-ui-markdown a{color:inherit;text-decoration:underline;text-underline-offset:3px}
|
|
53
|
+
/* Streamdown 的 200px 虚拟高度会在代码块首次可见时改变内容总高度。 */
|
|
54
|
+
.pi-desk-ui-markdown [data-streamdown="code-block"]{position:relative;display:block;margin-block:.375rem;overflow:hidden;content-visibility:visible!important;contain-intrinsic-size:none!important;gap:0;padding:0;border:0;border-radius:var(--pi-desk-plugin-radius,var(--radius));background:var(--pi-desk-plugin-muted,var(--muted))}
|
|
55
|
+
.pi-desk-ui-markdown>[data-streamdown="code-block"]+*{margin-block-start:.375rem}
|
|
56
|
+
.pi-desk-ui-markdown>[data-streamdown="code-block"]+[data-streamdown="horizontal-rule"]{margin-block-start:.875rem}
|
|
57
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-header"]{display:none}
|
|
58
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-body"]{max-width:100%;overflow-x:auto;border:0;border-radius:0;background:transparent;padding:.5rem 2.5rem .5rem .875rem;font-size:var(--chat-code-font-size,.875rem);line-height:var(--chat-code-line-height,1.6)}
|
|
59
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-body"] pre,.pi-desk-ui-markdown [data-streamdown="code-block-body"] code{background:transparent;font-size:inherit;line-height:inherit;white-space:var(--pi-desk-code-white-space,pre-wrap);overflow-wrap:var(--pi-desk-code-overflow-wrap,anywhere)}
|
|
60
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-body"] code>span{display:block}
|
|
61
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-body"] code>span::before{display:none;content:none}
|
|
62
|
+
.pi-desk-ui-markdown [data-streamdown="code-block"]>div:has(>[data-streamdown="code-block-actions"]){position:absolute;top:.25rem;right:.375rem;z-index:10;display:block;height:auto;margin:0;pointer-events:none}
|
|
63
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-actions"]{pointer-events:auto;gap:0;border:0;background:var(--pi-desk-plugin-muted,var(--muted));padding:0;opacity:0;box-shadow:none;backdrop-filter:none;transition:opacity 120ms ease}
|
|
64
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-actions"]>button{display:flex;width:1.75rem;height:1.75rem;align-items:center;justify-content:center;border-radius:.375rem;padding:0}
|
|
65
|
+
.pi-desk-ui-markdown [data-streamdown="code-block-actions"]>button:hover{background:var(--accent);color:var(--accent-foreground)}
|
|
66
|
+
.pi-desk-ui-markdown [data-streamdown="code-block"]:hover [data-streamdown="code-block-actions"],.pi-desk-ui-markdown [data-streamdown="code-block"]:focus-within [data-streamdown="code-block-actions"]{opacity:1}
|
|
67
|
+
@media(hover:none),(max-width:640px){.pi-desk-ui-markdown [data-streamdown="code-block-actions"]{opacity:1}}
|
|
68
|
+
.pi-desk-ui-markdown table{display:block;max-width:100%;overflow:auto;border-collapse:collapse}.pi-desk-ui-markdown :where(th,td){border:1px solid var(--pi-desk-plugin-border,var(--border));padding:.4rem .55rem;text-align:left}
|
|
69
|
+
.pi-desk-ui-markdown hr{border:0;border-top:1px solid var(--pi-desk-plugin-border,var(--border))}
|
|
70
|
+
.pi-desk-ui-markdown img{max-width:100%;height:auto}
|
|
71
|
+
.pi-desk-ui-button {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
min-height: 2rem;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
gap: .5rem;
|
|
77
|
+
border: 1px solid transparent;
|
|
78
|
+
border-radius: .5rem;
|
|
79
|
+
padding: .25rem .5rem;
|
|
80
|
+
font: inherit;
|
|
81
|
+
font-size: .875rem;
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
line-height: 1.5;
|
|
84
|
+
white-space: nowrap;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
outline: none;
|
|
87
|
+
transition: background-color 150ms ease-out, color 150ms ease-out, border-color 150ms ease-out;
|
|
88
|
+
}
|
|
89
|
+
.pi-desk-ui-button-sm, .pi-desk-ui-button-xs {
|
|
90
|
+
min-height: 1.75rem;
|
|
91
|
+
border-radius: .375rem;
|
|
92
|
+
padding: .125rem .5rem;
|
|
93
|
+
}
|
|
94
|
+
.pi-desk-ui-button svg { width: 1rem; height: 1rem; flex: none; }
|
|
95
|
+
.pi-desk-ui-button-primary{background:var(--pi-desk-plugin-primary,var(--primary));color:var(--pi-desk-plugin-primary-foreground,var(--primary-foreground))}
|
|
96
|
+
.pi-desk-ui-button-primary:hover{background:color-mix(in oklab,var(--pi-desk-plugin-primary,var(--primary)),var(--pi-desk-plugin-primary-foreground,var(--primary-foreground)) 8%)}
|
|
97
|
+
.pi-desk-ui-button-primary:active{background:color-mix(in oklab,var(--pi-desk-plugin-primary,var(--primary)),var(--pi-desk-plugin-primary-foreground,var(--primary-foreground)) 14%)}
|
|
98
|
+
.pi-desk-ui-button-secondary{background:var(--secondary);color:var(--secondary-foreground)}
|
|
99
|
+
.pi-desk-ui-button-secondary:hover{background:color-mix(in oklab,var(--secondary),var(--foreground) 8%)}
|
|
100
|
+
.pi-desk-ui-button-secondary:active{background:color-mix(in oklab,var(--secondary),var(--foreground) 14%)}
|
|
101
|
+
.pi-desk-ui-button-ghost:hover{background:color-mix(in oklab,var(--foreground) 8%,transparent);color:var(--foreground)}
|
|
102
|
+
.pi-desk-ui-button-ghost:active{background:color-mix(in oklab,var(--foreground) 14%,transparent)}
|
|
103
|
+
.pi-desk-ui-button-danger{border-color:color-mix(in srgb,var(--pi-desk-plugin-destructive,var(--destructive)) 45%,transparent);background:color-mix(in srgb,var(--pi-desk-plugin-destructive,var(--destructive)) 12%,transparent);color:var(--pi-desk-plugin-destructive,var(--destructive))}
|
|
104
|
+
.pi-desk-ui-button-danger:hover{background:color-mix(in srgb,var(--pi-desk-plugin-destructive,var(--destructive)) 20%,transparent)}
|
|
105
|
+
.pi-desk-ui-button-ghost{background:transparent;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}
|
|
106
|
+
.pi-desk-ui-button[aria-pressed="true"]{background:var(--accent);color:var(--accent-foreground)}
|
|
107
|
+
.pi-desk-ui-button[aria-pressed="true"]:hover{background:color-mix(in oklab,var(--accent),var(--foreground) 5%)}
|
|
108
|
+
.pi-desk-ui-context-menu-positioner{z-index:1020;outline:none}.pi-desk-ui-context-menu{max-height:min(20rem,var(--available-height));min-width:10rem;overflow:auto;border:1px solid var(--pi-desk-plugin-border,var(--border));border-radius:calc(var(--pi-desk-plugin-radius,var(--radius,.45rem)) + .2rem);padding:.25rem;background:var(--pi-desk-plugin-popover,var(--popover,var(--card)));color:var(--pi-desk-plugin-popover-foreground,var(--popover-foreground,var(--foreground)));box-shadow:0 .6rem 1.6rem color-mix(in srgb,#000 22%,transparent);transform-origin:var(--transform-origin);outline:none;transition:transform .1s ease-out,opacity .1s ease-out}.pi-desk-ui-context-menu[data-starting-style],.pi-desk-ui-context-menu[data-ending-style]{opacity:0;transform:scale(.98)}.pi-desk-ui-context-menu-item{display:flex;min-height:1.75rem;align-items:center;gap:.5rem;border-radius:.375rem;padding:.25rem .5rem;font:inherit;font-size:.875rem;line-height:1.5;cursor:pointer;outline:none;user-select:none}.pi-desk-ui-context-menu-item[data-highlighted]{background:var(--accent);color:var(--accent-foreground)}.pi-desk-ui-context-menu-item[data-disabled]{pointer-events:none;opacity:.5}
|
|
109
|
+
.pi-desk-ui-badge{display:inline-flex;min-height:1.25rem;align-items:center;border-radius:.375rem;padding:.0625rem .375rem;font-size:.75rem;line-height:1.5;font-weight:500;white-space:nowrap}
|
|
110
|
+
.pi-desk-ui-badge-neutral{background:var(--pi-desk-plugin-muted,var(--muted));color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}
|
|
111
|
+
.pi-desk-ui-badge-info{background:var(--muted);color:var(--foreground)}
|
|
112
|
+
.pi-desk-ui-badge-success{background:var(--muted);color:var(--status-success,var(--foreground))}
|
|
113
|
+
.pi-desk-ui-badge-warning{background:var(--muted);color:var(--status-warning,var(--foreground))}
|
|
114
|
+
.pi-desk-ui-badge-error{background:var(--muted);color:var(--pi-desk-plugin-destructive,var(--destructive))}
|
|
115
|
+
.pi-desk-ui-alert{border:1px solid var(--pi-desk-plugin-border,var(--border));border-radius:calc(var(--pi-desk-plugin-radius,var(--radius,.45rem)) + .25rem);padding:.75rem .85rem;background:color-mix(in srgb,var(--pi-desk-plugin-muted,var(--muted)) 70%,transparent);color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));line-height:1.5}.pi-desk-ui-alert-compact{border-radius:.5rem;padding:.75rem;font-size:.875rem}
|
|
116
|
+
.pi-desk-ui-alert-info{border-color:color-mix(in srgb,var(--pi-desk-plugin-primary,var(--primary)) 35%,var(--pi-desk-plugin-border,var(--border)))}
|
|
117
|
+
.pi-desk-ui-alert-warning{border-color:color-mix(in oklab,var(--status-warning,var(--foreground)) 45%,var(--border));color:var(--pi-desk-plugin-foreground,var(--foreground))}
|
|
118
|
+
.pi-desk-ui-alert-error{border-color:color-mix(in srgb,var(--pi-desk-plugin-destructive,var(--destructive)) 42%,var(--pi-desk-plugin-border,var(--border)));color:var(--pi-desk-plugin-destructive,var(--destructive))}
|
|
119
|
+
.pi-desk-ui-dialog-backdrop{position:fixed;inset:0;z-index:1000;background:rgb(0 0 0 / .35)}.pi-desk-ui-dialog{position:fixed;top:50%;left:50%;z-index:1010;display:flex;max-height:calc(100dvh - 2rem);width:calc(100vw - 2rem);max-width:27.5rem;transform:translate(-50%,-50%);flex-direction:column;overflow:hidden;container-type:inline-size;border:1px solid var(--pi-desk-plugin-border,var(--border));border-radius:.75rem;font-size:.875rem;line-height:1.5;background:var(--pi-desk-plugin-popover,var(--popover,var(--card)));color:var(--pi-desk-plugin-popover-foreground,var(--popover-foreground,var(--foreground)));box-shadow:0 .5rem 1.5rem rgb(0 0 0 / .18);outline:none}.pi-desk-ui-dialog-sm{max-width:20rem}.pi-desk-ui-dialog-lg{max-width:45rem}.pi-desk-ui-dialog-header{display:grid;flex:none;gap:.2rem;border-bottom:1px solid var(--pi-desk-plugin-border,var(--border));padding:1rem 3.5rem 1rem 1rem}.pi-desk-ui-dialog-title{margin:0;font-size:1.125rem;font-weight:600;line-height:1.4}.pi-desk-ui-dialog-description{font-size:.875rem;line-height:1.5;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));overflow-wrap:anywhere}.pi-desk-ui-dialog-close{position:absolute;top:.5rem;right:.5rem;display:inline-flex;width:2rem;height:2rem;align-items:center;justify-content:center;border:0;border-radius:var(--pi-desk-plugin-radius,var(--radius,.45rem));background:transparent;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font:inherit;font-size:1.25rem;cursor:pointer;outline:none}.pi-desk-ui-dialog-close:hover{background:var(--pi-desk-plugin-muted,var(--muted));color:var(--pi-desk-plugin-foreground,var(--foreground))}.pi-desk-ui-dialog-close:focus-visible{outline:2px solid var(--pi-desk-plugin-ring,var(--ring));outline-offset:2px}.pi-desk-ui-dialog-scroll{min-height:0;flex:1}.pi-desk-ui-dialog-body{min-height:0;padding:1rem}.pi-desk-ui-dialog-footer{display:flex;flex:none;flex-wrap:wrap;justify-content:flex-end;gap:.5rem;border-top:1px solid var(--pi-desk-plugin-border,var(--border));padding:.75rem 1rem}.pi-desk-ui-empty{display:flex;align-items:center;justify-content:center;padding:1.5rem 1rem;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));font-size:.875rem;text-align:center;line-height:1.5}
|
|
120
|
+
.pi-desk-ui-field{display:grid;gap:.25rem;min-width:0}
|
|
121
|
+
.pi-desk-ui-field-label{font-size:.875rem;font-weight:500;color:var(--pi-desk-plugin-foreground,var(--foreground))}
|
|
122
|
+
.pi-desk-ui-field-description,.pi-desk-ui-field-error{font-size:.875rem;line-height:1.5;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}
|
|
123
|
+
.pi-desk-ui-field-error{color:var(--pi-desk-plugin-destructive,var(--destructive))}
|
|
124
|
+
.pi-desk-ui-control {
|
|
125
|
+
width: 100%;
|
|
126
|
+
min-height: 2rem;
|
|
127
|
+
border: 1px solid var(--pi-desk-plugin-input,var(--input));
|
|
128
|
+
border-radius: .5rem;
|
|
129
|
+
padding: .25rem .625rem;
|
|
130
|
+
background: var(--pi-desk-plugin-surface,var(--card));
|
|
131
|
+
color: var(--pi-desk-plugin-foreground,var(--foreground));
|
|
132
|
+
font: inherit;
|
|
133
|
+
font-size: .875rem;
|
|
134
|
+
line-height: 1.5;
|
|
135
|
+
outline: none;
|
|
136
|
+
}
|
|
137
|
+
.pi-desk-ui-control-sm{min-height:1.75rem;border-radius:.375rem;padding:.125rem .625rem}
|
|
138
|
+
.pi-desk-ui-control:focus-visible{outline-offset:-2px}
|
|
139
|
+
.pi-desk-ui-control[aria-invalid="true"]{border-color:var(--destructive);outline-color:var(--destructive)}
|
|
140
|
+
.pi-desk-ui-checkbox{appearance:none;display:inline-grid;width:1rem;height:1rem;flex:none;place-content:center;border:1px solid var(--pi-desk-plugin-input,var(--input,var(--border)));border-radius:.25rem;background:var(--pi-desk-plugin-background,var(--background));color:var(--pi-desk-plugin-primary-foreground,var(--primary-foreground));cursor:pointer;outline:none;transition:background-color .15s,border-color .15s,box-shadow .15s}.pi-desk-ui-checkbox::before{content:"";width:.68rem;height:.68rem;transform:scale(0);transform-origin:center;clip-path:polygon(14% 44%,0 59%,38% 100%,100% 22%,84% 8%,37% 70%);background:currentColor;transition:transform .12s ease}.pi-desk-ui-checkbox:checked{border-color:var(--pi-desk-plugin-primary,var(--primary));background:var(--pi-desk-plugin-primary,var(--primary))}.pi-desk-ui-checkbox:checked::before{transform:scale(1)}.pi-desk-ui-checkbox:hover:not(:disabled){border-color:color-mix(in srgb,var(--pi-desk-plugin-primary,var(--primary)) 65%,var(--pi-desk-plugin-input,var(--input,var(--border))))}.pi-desk-ui-checkbox:focus-visible{outline:2px solid var(--pi-desk-plugin-ring,var(--ring));outline-offset:2px}.pi-desk-ui-checkbox:disabled{cursor:not-allowed;opacity:.5}
|
|
141
|
+
.pi-desk-ui-secret{position:relative;min-width:0}
|
|
142
|
+
.pi-desk-ui-secret .pi-desk-ui-control{padding-right:2.25rem}
|
|
143
|
+
.pi-desk-ui-secret-control{-webkit-text-security:disc}
|
|
144
|
+
.pi-desk-ui-secret-toggle{position:absolute;top:50%;right:.25rem;display:inline-flex;width:1.5rem;height:1.5rem;align-items:center;justify-content:center;transform:translateY(-50%);border:0;border-radius:.375rem;background:transparent;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground));cursor:pointer;outline:none}
|
|
145
|
+
.pi-desk-ui-secret-toggle:hover{background:var(--pi-desk-plugin-muted,var(--muted));color:var(--pi-desk-plugin-foreground,var(--foreground))}
|
|
146
|
+
.pi-desk-ui-secret-toggle:focus-visible{box-shadow:0 0 0 2px var(--pi-desk-plugin-ring,var(--ring))}
|
|
147
|
+
.pi-desk-ui-secret-toggle:disabled{pointer-events:none;opacity:.5}
|
|
148
|
+
.pi-desk-ui-secret-toggle svg{width:.875rem;height:.875rem}
|
|
149
|
+
textarea.pi-desk-ui-control{min-height:13rem;resize:vertical;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;line-height:1.5}textarea.pi-desk-ui-control-sm{min-height:7rem}
|
|
150
|
+
.pi-desk-ui-control::placeholder{color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}
|
|
151
|
+
.pi-desk-ui-select-trigger{display:flex;width:100%;min-width:0;max-width:100%;min-height:2rem;align-items:center;justify-content:space-between;gap:.5rem;border:1px solid var(--pi-desk-plugin-input,var(--input));border-radius:.5rem;padding:.25rem .625rem;background:var(--pi-desk-plugin-surface,var(--card));color:var(--pi-desk-plugin-foreground,var(--foreground));font:inherit;font-size:.875rem;line-height:1.5;text-align:left;outline:none;cursor:pointer}.pi-desk-ui-select-trigger:hover{background:var(--accent)}.pi-desk-ui-select-trigger:focus-visible{outline:2px solid var(--pi-desk-plugin-ring,var(--ring));outline-offset:-2px}.pi-desk-ui-select-trigger[data-disabled]{cursor:not-allowed;opacity:.5}.pi-desk-ui-select-trigger-sm{min-height:1.75rem;border-radius:.375rem;padding:.125rem .625rem}.pi-desk-ui-select-value{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pi-desk-ui-select-value[data-placeholder]{color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}.pi-desk-ui-select-icon{display:inline-flex;width:1rem;height:1rem;flex:none;color:var(--pi-desk-plugin-muted-foreground,var(--muted-foreground))}.pi-desk-ui-select-icon svg,.pi-desk-ui-select-indicator svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
|
152
|
+
.pi-desk-ui-select-positioner{z-index:1020}.pi-desk-ui-select-popup{max-height:min(20rem,var(--available-height));min-width:max(9rem,var(--anchor-width));overflow:auto;border:1px solid var(--pi-desk-plugin-border,var(--border));border-radius:calc(var(--pi-desk-plugin-radius,var(--radius,.45rem)) + .2rem);padding:.25rem;background:var(--pi-desk-plugin-popover,var(--popover,var(--card)));color:var(--pi-desk-plugin-popover-foreground,var(--popover-foreground,var(--foreground)));box-shadow:0 .6rem 1.6rem color-mix(in srgb,#000 22%,transparent);outline:none}.pi-desk-ui-select-item{position:relative;display:flex;min-height:2rem;align-items:center;gap:.5rem;border-radius:var(--pi-desk-plugin-radius,var(--radius,.45rem));padding:.35rem 2rem .35rem .55rem;font-size:.875rem;line-height:1.5;cursor:pointer;outline:none}.pi-desk-ui-select-item[data-highlighted]{background:var(--accent);color:var(--accent-foreground)}.pi-desk-ui-select-item[data-disabled]{pointer-events:none;opacity:.5}.pi-desk-ui-select-indicator{position:absolute;right:.55rem;display:inline-flex;width:.9rem;height:.9rem;align-items:center;justify-content:center;color:var(--pi-desk-plugin-primary,var(--primary))}
|
|
153
|
+
@container (max-width:40rem){.pi-desk-ui-split{grid-template-columns:minmax(0,1fr)}.pi-desk-ui-split-navigation-scroll{height:auto;max-height:11rem}}
|
|
154
|
+
@media(prefers-reduced-motion:reduce){.pi-desk-ui-button,.pi-desk-ui-list-item,.pi-desk-ui-context-menu{transition:none}}
|
|
155
|
+
@container (max-width:28rem){.pi-desk-ui-action-row-mobile-stack{align-items:flex-start;flex-direction:column}.pi-desk-ui-key-value{grid-template-columns:minmax(0,1fr)}.pi-desk-ui-key-value-action{justify-self:start}}
|
|
156
|
+
`;
|
|
157
|
+
const PLUGIN_SCROLL_STYLES = `
|
|
158
|
+
.pi-desk-ui-scroll{display:flex;position:relative;min-width:0;min-height:0;flex-direction:column;overflow:hidden}
|
|
159
|
+
.pi-desk-ui-scroll-viewport{width:100%;height:auto;min-width:0;min-height:0;flex:1 1 auto;outline:none}
|
|
160
|
+
.pi-desk-ui-scrollbar{display:flex;touch-action:none;padding:.1rem;user-select:none}
|
|
161
|
+
.pi-desk-ui-scrollbar[data-orientation="vertical"]{height:100%;width:.625rem;border-left:1px solid transparent}
|
|
162
|
+
.pi-desk-ui-scrollbar[data-orientation="horizontal"]{height:.625rem;flex-direction:column;border-top:1px solid transparent}
|
|
163
|
+
.pi-desk-ui-scrollbar-thumb{position:relative;flex:1;border-radius:999px;background:color-mix(in srgb,var(--pi-desk-plugin-muted-foreground,var(--muted-foreground)) 45%,transparent)}
|
|
164
|
+
.pi-desk-ui-scrollbar-thumb:hover{background:color-mix(in srgb,var(--pi-desk-plugin-muted-foreground,var(--muted-foreground)) 70%,transparent)}
|
|
165
|
+
`;
|
|
166
|
+
function classNames(...values) {
|
|
167
|
+
return values.filter(Boolean).join(' ');
|
|
168
|
+
}
|
|
169
|
+
export function PluginSurface({ className, children, ...props }) {
|
|
170
|
+
return (_jsxs("div", { ...props, "data-pi-desk-ui-root": "", className: classNames('pi-desk-ui-root', className), children: [_jsx("style", { href: "pi-desk-ui", precedence: "pi-desk-ui", children: PLUGIN_UI_STYLES }), children] }));
|
|
171
|
+
}
|
|
172
|
+
function PluginScrollBar({ orientation }) {
|
|
173
|
+
return (_jsx(ScrollAreaPrimitive.Scrollbar, { "data-slot": "plugin-scrollbar", "data-orientation": orientation, orientation: orientation, className: "pi-desk-ui-scrollbar", children: _jsx(ScrollAreaPrimitive.Thumb, { "data-slot": "plugin-scrollbar-thumb", className: "pi-desk-ui-scrollbar-thumb" }) }));
|
|
174
|
+
}
|
|
175
|
+
export function PluginScroll({ orientation = 'vertical', viewportClassName, viewportRef, onScroll, role, className, children, ...props }) {
|
|
176
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { href: "pi-desk-scroll", precedence: "pi-desk-ui", children: PLUGIN_SCROLL_STYLES }), _jsxs(ScrollAreaPrimitive.Root, { ...props, "data-pi-desk-scroll": "", role: role ?? 'region', className: classNames('pi-desk-ui-scroll', className), children: [_jsx(ScrollAreaPrimitive.Viewport, { ref: viewportRef, "data-slot": "plugin-scroll-viewport", className: classNames('pi-desk-ui-scroll-viewport', viewportClassName), onScroll: onScroll, children: children }), orientation !== 'horizontal' ? _jsx(PluginScrollBar, { orientation: "vertical" }) : null, orientation !== 'vertical' ? _jsx(PluginScrollBar, { orientation: "horizontal" }) : null, _jsx(ScrollAreaPrimitive.Corner, {})] })] }));
|
|
177
|
+
}
|
|
178
|
+
function PluginHeading({ level, className, children }) {
|
|
179
|
+
if (level === 1)
|
|
180
|
+
return _jsx("h1", { className: className, children: children });
|
|
181
|
+
if (level === 2)
|
|
182
|
+
return _jsx("h2", { className: className, children: children });
|
|
183
|
+
if (level === 3)
|
|
184
|
+
return _jsx("h3", { className: className, children: children });
|
|
185
|
+
return _jsx("h4", { className: className, children: children });
|
|
186
|
+
}
|
|
187
|
+
export function PluginPanelHeader({ title, description, actions, meta, density = 'regular', headingLevel = 2, className, ...props }) {
|
|
188
|
+
return (_jsxs("header", { ...props, className: classNames('pi-desk-ui-panel-header', density === 'compact' && 'pi-desk-ui-panel-header-compact', className), children: [_jsxs("div", { className: "pi-desk-ui-panel-header-main", children: [_jsxs("div", { className: "pi-desk-ui-panel-header-copy", children: [_jsx(PluginHeading, { level: headingLevel, className: "pi-desk-ui-panel-header-title", children: title }), description ? (_jsx("div", { className: "pi-desk-ui-panel-header-description", children: description })) : null] }), actions ? _jsx("div", { className: "pi-desk-ui-panel-header-actions", children: actions }) : null] }), meta ? _jsx("div", { className: "pi-desk-ui-panel-header-meta", children: meta }) : null] }));
|
|
189
|
+
}
|
|
190
|
+
export function PluginSection({ title, description, action, density = 'regular', headingLevel = 3, className, children, ...props }) {
|
|
191
|
+
return (_jsxs("section", { ...props, className: classNames('pi-desk-ui-section', density === 'compact' && 'pi-desk-ui-section-compact', className), children: [_jsxs("div", { className: "pi-desk-ui-section-header", children: [_jsxs("div", { className: "pi-desk-ui-section-copy", children: [_jsx(PluginHeading, { level: headingLevel, className: "pi-desk-ui-section-title", children: title }), description ? _jsx("div", { className: "pi-desk-ui-section-description", children: description }) : null] }), action ? _jsx("div", { className: "pi-desk-ui-section-action", children: action }) : null] }), _jsx("div", { className: "pi-desk-ui-section-content", children: children })] }));
|
|
192
|
+
}
|
|
193
|
+
export function PluginTabList({ label, className, ...props }) {
|
|
194
|
+
return (_jsx("div", { ...props, role: "tablist", "aria-label": label, className: classNames('pi-desk-ui-tabs', className) }));
|
|
195
|
+
}
|
|
196
|
+
export function PluginTab({ active = false, className, type, ...props }) {
|
|
197
|
+
return (_jsx("button", { ...props, type: type ?? 'button', role: "tab", "aria-selected": active, "data-active": active, className: classNames('pi-desk-ui-tab', className) }));
|
|
198
|
+
}
|
|
199
|
+
export function PluginActionRow({ align = 'start', mobileStack = false, className, ...props }) {
|
|
200
|
+
return (_jsx("div", { ...props, className: classNames('pi-desk-ui-action-row', align !== 'start' && `pi-desk-ui-action-row-${align}`, mobileStack && 'pi-desk-ui-action-row-mobile-stack', className) }));
|
|
201
|
+
}
|
|
202
|
+
export function PluginKeyValueList({ density = 'regular', layout = 'inline', className, ...props }) {
|
|
203
|
+
return (_jsx("dl", { ...props, className: classNames('pi-desk-ui-key-values', density === 'compact' && 'pi-desk-ui-key-values-compact', layout === 'stacked' && 'pi-desk-ui-key-values-stacked', className) }));
|
|
204
|
+
}
|
|
205
|
+
export function PluginKeyValueItem({ label, value, action, className, ...props }) {
|
|
206
|
+
return (_jsxs("div", { ...props, className: classNames('pi-desk-ui-key-value', className), children: [_jsx("dt", { className: "pi-desk-ui-key-value-label", children: label }), _jsx("dd", { className: "pi-desk-ui-key-value-value", children: value }), action ? _jsx("div", { className: "pi-desk-ui-key-value-action", children: action }) : null] }));
|
|
207
|
+
}
|
|
208
|
+
export function PluginSpinner({ className }) {
|
|
209
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", role: "status", "aria-label": "\u6B63\u5728\u52A0\u8F7D", className: classNames('pi-desk-ui-spinner', className), children: _jsx("path", { d: "M20 12a8 8 0 1 1-5.5-7.6" }) }));
|
|
210
|
+
}
|
|
211
|
+
export function PluginLoadingState({ loading, error, loadingLabel = '正在加载…', retryLabel = '重新加载', onRetry, className, children }) {
|
|
212
|
+
if (error) {
|
|
213
|
+
const message = error instanceof Error ? error.message : error;
|
|
214
|
+
return (_jsxs("div", { className: classNames('pi-desk-ui-loading-error', className), children: [_jsx(PluginAlert, { tone: "error", density: "compact", children: message }), onRetry ? (_jsx(PluginActionRow, { children: _jsx(PluginButton, { size: "sm", variant: "primary", onClick: onRetry, children: retryLabel }) })) : null] }));
|
|
215
|
+
}
|
|
216
|
+
if (loading) {
|
|
217
|
+
return (_jsxs("div", { className: classNames('pi-desk-ui-loading', className), role: "status", children: [_jsx(PluginSpinner, {}), _jsx("span", { children: loadingLabel })] }));
|
|
218
|
+
}
|
|
219
|
+
return _jsx(_Fragment, { children: children });
|
|
220
|
+
}
|
|
221
|
+
export function PluginSplitView({ navigation, navigationLabel = '插件导航', className, children, ...props }) {
|
|
222
|
+
const navigationContent = isValidElement(navigation) && navigation.type === PluginScroll ? (navigation) : (_jsx(PluginScroll, { className: "pi-desk-ui-split-navigation-scroll", "aria-label": navigationLabel, children: navigation }));
|
|
223
|
+
return (_jsxs("div", { ...props, className: classNames('pi-desk-ui-split', className), children: [_jsx("aside", { className: "pi-desk-ui-navigation", "aria-label": navigationLabel, children: navigationContent }), _jsx("div", { className: "pi-desk-ui-content", children: children })] }));
|
|
224
|
+
}
|
|
225
|
+
export function PluginList({ density = 'regular', className, ...props }) {
|
|
226
|
+
return (_jsx("div", { ...props, className: classNames('pi-desk-ui-list', density === 'compact' && 'pi-desk-ui-list-compact', className) }));
|
|
227
|
+
}
|
|
228
|
+
export function PluginListItem({ selected = false, density = 'regular', className, type, ...props }) {
|
|
229
|
+
return (_jsx("button", { ...props, type: type ?? 'button', "aria-pressed": selected, className: classNames('pi-desk-ui-list-item', density === 'compact' && 'pi-desk-ui-list-item-compact', className) }));
|
|
230
|
+
}
|
|
231
|
+
export function PluginCard({ density = 'regular', className, ...props }) {
|
|
232
|
+
return (_jsx("div", { ...props, className: classNames('pi-desk-ui-card', density === 'compact' && 'pi-desk-ui-card-compact', className) }));
|
|
233
|
+
}
|
|
234
|
+
export function PluginButton({ variant = 'secondary', size = 'default', className, type, ...props }) {
|
|
235
|
+
return (_jsx("button", { ...props, type: type ?? 'button', className: classNames('pi-desk-ui-button', `pi-desk-ui-button-${variant}`, size !== 'default' && `pi-desk-ui-button-${size}`, className) }));
|
|
236
|
+
}
|
|
237
|
+
export function PluginContextMenu(props) {
|
|
238
|
+
return _jsx(ContextMenuPrimitive.Root, { ...props });
|
|
239
|
+
}
|
|
240
|
+
export function PluginContextMenuTrigger(props) {
|
|
241
|
+
return _jsx(ContextMenuPrimitive.Trigger, { ...props });
|
|
242
|
+
}
|
|
243
|
+
export function PluginContextMenuContent({ className, ...props }) {
|
|
244
|
+
return (_jsx(ContextMenuPrimitive.Portal, { children: _jsx(ContextMenuPrimitive.Positioner, { className: "pi-desk-ui-context-menu-positioner", children: _jsx(ContextMenuPrimitive.Popup, { ...props, className: classNames('pi-desk-ui-context-menu', className) }) }) }));
|
|
245
|
+
}
|
|
246
|
+
export function PluginContextMenuItem({ className, ...props }) {
|
|
247
|
+
return (_jsx(ContextMenuPrimitive.Item, { ...props, className: classNames('pi-desk-ui-context-menu-item', className) }));
|
|
248
|
+
}
|
|
249
|
+
export function PluginBadge({ tone = 'neutral', className, ...props }) {
|
|
250
|
+
return (_jsx("span", { ...props, className: classNames('pi-desk-ui-badge', `pi-desk-ui-badge-${tone}`, className) }));
|
|
251
|
+
}
|
|
252
|
+
export function PluginAlert({ tone = 'neutral', density = 'regular', className, ...props }) {
|
|
253
|
+
return (_jsx("div", { ...props, role: props.role ?? (tone === 'error' ? 'alert' : undefined), className: classNames('pi-desk-ui-alert', `pi-desk-ui-alert-${tone}`, density === 'compact' && 'pi-desk-ui-alert-compact', className) }));
|
|
254
|
+
}
|
|
255
|
+
export function PluginDialog({ open, title, description, size = 'md', footer, closeLabel = '关闭弹窗', children, onOpenChange }) {
|
|
256
|
+
// 不锁定文档滚动,避免弹窗改写 body 宽度并触发背景多列工作台重新分栏。
|
|
257
|
+
return (_jsx(DialogPrimitive.Root, { open: open, modal: "trap-focus", onOpenChange: onOpenChange, children: _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Backdrop, { className: "pi-desk-ui-dialog-backdrop" }), _jsxs(DialogPrimitive.Popup, { className: classNames('pi-desk-ui-dialog', size !== 'md' && `pi-desk-ui-dialog-${size}`), children: [_jsxs("div", { className: "pi-desk-ui-dialog-header", children: [_jsx(DialogPrimitive.Title, { className: "pi-desk-ui-dialog-title", children: title }), description ? (_jsx(DialogPrimitive.Description, { className: "pi-desk-ui-dialog-description", children: description })) : null] }), _jsx(DialogPrimitive.Close, { className: "pi-desk-ui-dialog-close", "aria-label": closeLabel, title: closeLabel, children: "\u00D7" }), _jsx(PluginScroll, { className: "pi-desk-ui-dialog-scroll", viewportClassName: "pi-desk-ui-dialog-body", children: children }), footer ? _jsx("div", { className: "pi-desk-ui-dialog-footer", children: footer }) : null] })] }) }));
|
|
258
|
+
}
|
|
259
|
+
export function PluginConfirmDialog({ open, title, description, confirmLabel, cancelLabel = '取消', tone = 'default', pending = false, children, onConfirm, onOpenChange }) {
|
|
260
|
+
return (_jsx(PluginDialog, { open: open, title: title, description: description, size: "sm", closeLabel: typeof cancelLabel === 'string' ? cancelLabel : undefined, onOpenChange: onOpenChange, footer: _jsxs(_Fragment, { children: [_jsx(PluginButton, { disabled: pending, variant: "secondary", onClick: () => onOpenChange(false), children: cancelLabel }), _jsx(PluginButton, { disabled: pending, variant: tone === 'danger' ? 'danger' : 'primary', onClick: () => void Promise.resolve(onConfirm()).catch(() => undefined), children: pending ? '执行中…' : confirmLabel })] }), children: children }));
|
|
261
|
+
}
|
|
262
|
+
export function PluginEmptyState({ density = 'regular', className, ...props }) {
|
|
263
|
+
return (_jsx("div", { ...props, className: classNames('pi-desk-ui-empty', density === 'compact' && 'pi-desk-ui-empty-compact', className) }));
|
|
264
|
+
}
|
|
265
|
+
export function PluginField({ label, htmlFor, description, error, density = 'regular', className, children, ...props }) {
|
|
266
|
+
const generatedId = useId();
|
|
267
|
+
const control = isValidElement(children) &&
|
|
268
|
+
(children.type === 'input' ||
|
|
269
|
+
children.type === 'textarea' ||
|
|
270
|
+
children.type === 'select' ||
|
|
271
|
+
children.type === PluginInput ||
|
|
272
|
+
children.type === PluginTextarea ||
|
|
273
|
+
children.type === PluginSelect ||
|
|
274
|
+
children.type === PluginSecretInput)
|
|
275
|
+
? children
|
|
276
|
+
: null;
|
|
277
|
+
const controlId = htmlFor ?? control?.props.id ?? generatedId;
|
|
278
|
+
const content = control && !htmlFor && !control.props.id ? cloneElement(control, { id: controlId }) : children;
|
|
279
|
+
return (_jsxs("div", { ...props, className: classNames('pi-desk-ui-field', density === 'compact' && 'pi-desk-ui-field-compact', className), children: [_jsx("label", { className: "pi-desk-ui-field-label", htmlFor: control ? controlId : htmlFor, children: label }), content, description ? _jsx("div", { className: "pi-desk-ui-field-description", children: description }) : null, error ? _jsx("div", { className: "pi-desk-ui-field-error", children: error }) : null] }));
|
|
280
|
+
}
|
|
281
|
+
export function PluginInput({ controlSize = 'default', className, ...props }) {
|
|
282
|
+
return (_jsx("input", { ...props, className: classNames('pi-desk-ui-control', controlSize === 'sm' && 'pi-desk-ui-control-sm', className) }));
|
|
283
|
+
}
|
|
284
|
+
export function PluginCheckbox({ className, ...props }) {
|
|
285
|
+
return (_jsx("input", { ...props, type: "checkbox", className: classNames('pi-desk-ui-checkbox', className) }));
|
|
286
|
+
}
|
|
287
|
+
export function PluginSecretInput({ controlSize = 'default', className, disabled, id, ...props }) {
|
|
288
|
+
const [visible, setVisible] = useState(false);
|
|
289
|
+
const actionLabel = visible ? '隐藏原文' : '显示原文';
|
|
290
|
+
return (_jsxs("div", { className: "pi-desk-ui-secret", children: [_jsx("input", { ...props, id: id, disabled: disabled, type: "text", autoComplete: "off", autoCapitalize: "none", spellCheck: false, className: classNames('pi-desk-ui-control', controlSize === 'sm' && 'pi-desk-ui-control-sm', !visible && 'pi-desk-ui-secret-control', className) }), _jsx("button", { type: "button", className: "pi-desk-ui-secret-toggle", "aria-label": actionLabel, "aria-controls": id, "aria-pressed": visible, title: actionLabel, disabled: disabled, onClick: () => setVisible((current) => !current), children: visible ? _jsx(EyeOffIcon, { "aria-hidden": "true" }) : _jsx(EyeIcon, { "aria-hidden": "true" }) })] }));
|
|
291
|
+
}
|
|
292
|
+
export function PluginSelect({ controlSize = 'default', className, ...props }) {
|
|
293
|
+
return (_jsx("select", { ...props, className: classNames('pi-desk-ui-control', controlSize === 'sm' && 'pi-desk-ui-control-sm', className) }));
|
|
294
|
+
}
|
|
295
|
+
function PluginSelectChevronIcon() {
|
|
296
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "m7 9 5 5 5-5" }) }));
|
|
297
|
+
}
|
|
298
|
+
function PluginSelectCheckIcon() {
|
|
299
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "m5 12 4 4L19 6" }) }));
|
|
300
|
+
}
|
|
301
|
+
export function PluginSelectField({ id, name, label, description, error, value, defaultValue, options, placeholder = '请选择', disabled = false, required = false, size = 'default', className, triggerClassName, popupClassName, onValueChange }) {
|
|
302
|
+
const generatedId = useId();
|
|
303
|
+
const triggerId = id ?? generatedId;
|
|
304
|
+
const items = options.map((option) => ({ value: option.value, label: option.label }));
|
|
305
|
+
return (_jsx(PluginField, { label: label, htmlFor: triggerId, description: description, error: error, density: size === 'sm' ? 'compact' : 'regular', className: className, children: _jsxs(SelectPrimitive.Root, { name: name, value: value, defaultValue: defaultValue, items: items, disabled: disabled, required: required, onValueChange: (nextValue) => onValueChange?.(nextValue), children: [_jsxs(SelectPrimitive.Trigger, { id: triggerId, "aria-invalid": error ? true : undefined, className: classNames('pi-desk-ui-select-trigger', size === 'sm' && 'pi-desk-ui-select-trigger-sm', triggerClassName), children: [_jsx(SelectPrimitive.Value, { placeholder: placeholder, className: "pi-desk-ui-select-value" }), _jsx(SelectPrimitive.Icon, { className: "pi-desk-ui-select-icon", children: _jsx(PluginSelectChevronIcon, {}) })] }), _jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { side: "bottom", sideOffset: 4, align: "start", className: "pi-desk-ui-select-positioner", children: _jsx(SelectPrimitive.Popup, { className: classNames('pi-desk-ui-select-popup', popupClassName), children: _jsx(SelectPrimitive.List, { children: options.map((option) => (_jsxs(SelectPrimitive.Item, { value: option.value, disabled: option.disabled, label: option.textValue ??
|
|
306
|
+
(typeof option.label === 'string' ? option.label : undefined), className: "pi-desk-ui-select-item", children: [_jsx(SelectPrimitive.ItemText, { children: option.label }), _jsx(SelectPrimitive.ItemIndicator, { className: "pi-desk-ui-select-indicator", children: _jsx(PluginSelectCheckIcon, {}) })] }, option.value))) }) }) }) })] }) }));
|
|
307
|
+
}
|
|
308
|
+
export function PluginTextarea({ controlSize = 'default', className, ...props }) {
|
|
309
|
+
return (_jsx("textarea", { ...props, className: classNames('pi-desk-ui-control', controlSize === 'sm' && 'pi-desk-ui-control-sm', className) }));
|
|
310
|
+
}
|
package/dist/react.d.ts
ADDED
package/dist/react.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { AgentSession, ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
import { type PluginJsonObject, type PluginSource } from './shared.ts';
|
|
3
|
+
import type { SessionCapabilityRules } from './capabilities.js';
|
|
4
|
+
export type { PluginJsonObject, PluginJsonValue, PluginSource } from './shared.js';
|
|
5
|
+
export { PluginMethodError, isPluginMethodError, type PluginMethodErrorCode } from './errors.ts';
|
|
6
|
+
export declare const SESSION_PLUGIN_STATE_EVENT = "pi-desk:session-plugins";
|
|
7
|
+
export declare const SESSION_PLUGIN_METHOD_EVENT = "pi-desk:session-plugin-methods:v1";
|
|
8
|
+
export declare const SESSION_PLUGIN_PUSH_EVENT = "pi-desk:session-plugin-push:v1";
|
|
9
|
+
export declare const SESSION_PLUGIN_CAPABILITIES_EVENT = "pi-desk:session-capabilities";
|
|
10
|
+
export type SessionCapabilityHandler = (rules: SessionCapabilityRules, context: ExtensionContext) => void | Promise<void>;
|
|
11
|
+
/** Registration is shared only inside the Session EventBus, never serialized. */
|
|
12
|
+
export interface SessionCapabilityRegistration {
|
|
13
|
+
readonly pluginName: string;
|
|
14
|
+
readonly execute: SessionCapabilityHandler;
|
|
15
|
+
hostManaged: boolean;
|
|
16
|
+
}
|
|
17
|
+
export type SessionCapabilityRegistrationEvent = {
|
|
18
|
+
readonly type: 'register' | 'unregister';
|
|
19
|
+
readonly registration: SessionCapabilityRegistration;
|
|
20
|
+
};
|
|
21
|
+
export interface SessionPluginEventTarget {
|
|
22
|
+
events: {
|
|
23
|
+
emit(channel: string, payload: unknown): void;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export type SessionPluginSource = PluginSource;
|
|
27
|
+
export interface SessionPluginMethodContext {
|
|
28
|
+
source: SessionPluginSource;
|
|
29
|
+
extensionContext: ExtensionContext;
|
|
30
|
+
}
|
|
31
|
+
export type SessionPluginMethodHandler = (input: PluginJsonObject, context: SessionPluginMethodContext) => Promise<PluginJsonObject>;
|
|
32
|
+
export interface SessionPluginMethodRegistration {
|
|
33
|
+
readonly pluginName: string;
|
|
34
|
+
readonly method: string;
|
|
35
|
+
readonly execute: SessionPluginMethodHandler;
|
|
36
|
+
}
|
|
37
|
+
export type SessionPluginMethodEvent = {
|
|
38
|
+
readonly type: 'register';
|
|
39
|
+
readonly registration: SessionPluginMethodRegistration;
|
|
40
|
+
} | {
|
|
41
|
+
readonly type: 'unregister';
|
|
42
|
+
readonly registration: SessionPluginMethodRegistration;
|
|
43
|
+
};
|
|
44
|
+
export interface SessionPluginFacade {
|
|
45
|
+
readonly name: string;
|
|
46
|
+
setState(state: PluginJsonObject | null): void;
|
|
47
|
+
push(event: string, data: PluginJsonObject): void;
|
|
48
|
+
registerMethod(method: string, execute: SessionPluginMethodHandler): () => void;
|
|
49
|
+
onCapabilitiesChange(handler: SessionCapabilityHandler): () => void;
|
|
50
|
+
startTask(input: StartTaskInput): TaskHandle;
|
|
51
|
+
reportTasks(tasks: readonly TaskRuntimeSnapshot[]): void;
|
|
52
|
+
}
|
|
53
|
+
export interface SessionPluginPushEvent {
|
|
54
|
+
readonly pluginName: string;
|
|
55
|
+
readonly event: string;
|
|
56
|
+
readonly data: PluginJsonObject;
|
|
57
|
+
}
|
|
58
|
+
export interface SessionPluginPushCapability {
|
|
59
|
+
push(event: string, data: PluginJsonObject): void;
|
|
60
|
+
}
|
|
61
|
+
export interface SessionPluginGlobalMethodCapability {
|
|
62
|
+
invokeGlobal(method: string, input: PluginJsonObject): Promise<PluginJsonObject>;
|
|
63
|
+
}
|
|
64
|
+
export interface SessionPluginTargetCapabilities {
|
|
65
|
+
readonly push: SessionPluginPushCapability;
|
|
66
|
+
readonly global: SessionPluginGlobalMethodCapability;
|
|
67
|
+
}
|
|
68
|
+
export declare function bindSessionPlugin(pi: ExtensionAPI, pluginName: string): SessionPluginFacade;
|
|
69
|
+
export declare const TASK_REPORT_EVENT = "pi-desk:task-report:v1";
|
|
70
|
+
export type TaskStatus = 'running' | 'completed' | 'failed' | 'stopped' | 'interrupted';
|
|
71
|
+
export interface TaskInfoItem {
|
|
72
|
+
label: string;
|
|
73
|
+
value: string;
|
|
74
|
+
}
|
|
75
|
+
/** 仅在 Pi 与服务端同进程运行态中使用,不进入公共 JSON 快照。 */
|
|
76
|
+
export type TaskInfoLoader = () => readonly TaskInfoItem[] | Promise<readonly TaskInfoItem[]>;
|
|
77
|
+
export type TaskInterrupt = () => Promise<void>;
|
|
78
|
+
export interface TaskTextFileSource {
|
|
79
|
+
kind: 'text-file';
|
|
80
|
+
path: string;
|
|
81
|
+
}
|
|
82
|
+
export interface TaskPiConversationSessionSource {
|
|
83
|
+
kind: 'pi-conversation';
|
|
84
|
+
session: AgentSession;
|
|
85
|
+
sessionFile?: never;
|
|
86
|
+
}
|
|
87
|
+
export interface TaskPiConversationFileSource {
|
|
88
|
+
kind: 'pi-conversation';
|
|
89
|
+
session?: never;
|
|
90
|
+
sessionFile: string;
|
|
91
|
+
}
|
|
92
|
+
export type TaskPiConversationSource = TaskPiConversationSessionSource | TaskPiConversationFileSource;
|
|
93
|
+
export type TaskDetailSource = TaskTextFileSource | TaskPiConversationSource;
|
|
94
|
+
export interface TaskRuntimeSnapshot {
|
|
95
|
+
taskId: string;
|
|
96
|
+
taskKind?: string | null;
|
|
97
|
+
taskType?: string | null;
|
|
98
|
+
title: string;
|
|
99
|
+
info?: readonly TaskInfoItem[];
|
|
100
|
+
/** 仅服务端内存使用,Task Runtime 会在需要时调用并转成 info。 */
|
|
101
|
+
infoLoader?: TaskInfoLoader | null;
|
|
102
|
+
status: TaskStatus;
|
|
103
|
+
activity: string | null;
|
|
104
|
+
startedAt: number;
|
|
105
|
+
endedAt: number | null;
|
|
106
|
+
detailSource: TaskDetailSource | null;
|
|
107
|
+
interrupt: TaskInterrupt | null;
|
|
108
|
+
}
|
|
109
|
+
export type TaskReportEvent = {
|
|
110
|
+
type: 'upsert';
|
|
111
|
+
tasks: readonly TaskRuntimeSnapshot[];
|
|
112
|
+
} | {
|
|
113
|
+
type: 'remove';
|
|
114
|
+
taskIds: readonly string[];
|
|
115
|
+
};
|
|
116
|
+
export interface TaskEventTarget {
|
|
117
|
+
events: {
|
|
118
|
+
emit(channel: string, payload: unknown): void;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export interface StartTaskInput {
|
|
122
|
+
taskId?: string;
|
|
123
|
+
taskKind?: string | null;
|
|
124
|
+
taskType?: string | null;
|
|
125
|
+
title: string;
|
|
126
|
+
info?: readonly TaskInfoItem[];
|
|
127
|
+
/** 仅服务端内存使用,Task Runtime 会在需要时调用并转成 info。 */
|
|
128
|
+
infoLoader?: TaskInfoLoader | null;
|
|
129
|
+
activity?: string | null;
|
|
130
|
+
startedAt?: number;
|
|
131
|
+
detailSource?: TaskDetailSource | null;
|
|
132
|
+
interrupt?: TaskInterrupt | null;
|
|
133
|
+
}
|
|
134
|
+
export interface TaskUpdate {
|
|
135
|
+
taskKind?: string | null;
|
|
136
|
+
taskType?: string | null;
|
|
137
|
+
title?: string;
|
|
138
|
+
info?: readonly TaskInfoItem[];
|
|
139
|
+
/** 仅服务端内存使用,Task Runtime 会在需要时调用并转成 info。 */
|
|
140
|
+
infoLoader?: TaskInfoLoader | null;
|
|
141
|
+
activity?: string | null;
|
|
142
|
+
detailSource?: TaskDetailSource | null;
|
|
143
|
+
interrupt?: TaskInterrupt | null;
|
|
144
|
+
}
|
|
145
|
+
export interface TaskHandle {
|
|
146
|
+
readonly taskId: string;
|
|
147
|
+
update(input: TaskUpdate): void;
|
|
148
|
+
complete(activity?: string): void;
|
|
149
|
+
fail(activity?: string): void;
|
|
150
|
+
stopped(activity?: string): void;
|
|
151
|
+
interrupted(activity?: string): void;
|
|
152
|
+
remove(): void;
|
|
153
|
+
}
|
|
154
|
+
export declare function reportTasks(target: TaskEventTarget, tasks: readonly TaskRuntimeSnapshot[]): void;
|
|
155
|
+
export declare function startTask(target: TaskEventTarget, input: StartTaskInput): TaskHandle;
|