@silo-code/sdk 0.31.0 → 0.32.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/dist/ActivityGlyph.d.ts +25 -0
- package/dist/ActivityGlyph.d.ts.map +1 -0
- package/dist/ActivityGlyph.js +25 -0
- package/dist/ActivityGlyph.js.map +1 -0
- package/dist/IconButton.d.ts +23 -6
- package/dist/IconButton.d.ts.map +1 -1
- package/dist/IconButton.js +14 -5
- package/dist/IconButton.js.map +1 -1
- package/dist/activity.d.ts +36 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +33 -0
- package/dist/activity.js.map +1 -0
- package/dist/editor-service.d.ts +5 -1
- package/dist/editor-service.d.ts.map +1 -1
- package/dist/icon-button-classes.d.ts +10 -2
- package/dist/icon-button-classes.d.ts.map +1 -1
- package/dist/icon-button-classes.js +9 -5
- package/dist/icon-button-classes.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/phosphor-icon.d.ts +15 -0
- package/dist/phosphor-icon.d.ts.map +1 -0
- package/dist/phosphor-icon.js +2 -0
- package/dist/phosphor-icon.js.map +1 -0
- package/dist/tab-adornment.d.ts +193 -0
- package/dist/tab-adornment.d.ts.map +1 -0
- package/dist/tab-adornment.js +2 -0
- package/dist/tab-adornment.js.map +1 -0
- package/dist/terminal-service.d.ts +18 -35
- package/dist/terminal-service.d.ts.map +1 -1
- package/dist/toolbar-items.d.ts +171 -0
- package/dist/toolbar-items.d.ts.map +1 -0
- package/dist/toolbar-items.js +2 -0
- package/dist/toolbar-items.js.map +1 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workspace-service.d.ts +66 -45
- package/dist/workspace-service.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ActivityGlyph.tsx +43 -0
- package/src/IconButton.tsx +28 -6
- package/src/activity.test.ts +35 -0
- package/src/activity.ts +57 -0
- package/src/editor-service.ts +5 -1
- package/src/icon-button-classes.test.ts +10 -0
- package/src/icon-button-classes.ts +18 -5
- package/src/index.ts +32 -1
- package/src/phosphor-icon.ts +14 -0
- package/src/tab-adornment.ts +208 -0
- package/src/terminal-service.ts +21 -35
- package/src/toolbar-items.ts +190 -0
- package/src/types.ts +17 -0
- package/src/workspace-service.ts +72 -45
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
import {
|
|
3
|
+
activityClass,
|
|
4
|
+
type Activity as ActivityKind,
|
|
5
|
+
type ActivitySize,
|
|
6
|
+
} from "./activity";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Host-painted activity glyph — same look on workspace rows, CenterDock tabs,
|
|
10
|
+
* and extension UI. Pick an {@link Activity}; the host owns color and motion
|
|
11
|
+
* (ADR 0030). Omit `activity` only for the workspace-row neutral gray fallback.
|
|
12
|
+
*
|
|
13
|
+
* Styled purely via host-provided `.silo-activity*` classes — no stylesheet
|
|
14
|
+
* import is needed in the extension.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <ActivityGlyph activity="working" size="md" />
|
|
19
|
+
* <ActivityGlyph activity="ready" />
|
|
20
|
+
* <ActivityGlyph size="sm" /> // workspace neutral (omit)
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @category Consumer Services
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export function ActivityGlyph({
|
|
27
|
+
activity,
|
|
28
|
+
size = "sm",
|
|
29
|
+
className,
|
|
30
|
+
...rest
|
|
31
|
+
}: {
|
|
32
|
+
activity?: ActivityKind;
|
|
33
|
+
size?: ActivitySize;
|
|
34
|
+
} & Omit<HTMLAttributes<HTMLSpanElement>, "children">) {
|
|
35
|
+
const classes = activityClass(activity, size);
|
|
36
|
+
return (
|
|
37
|
+
<span
|
|
38
|
+
className={className ? `${classes} ${className}` : classes}
|
|
39
|
+
aria-hidden={rest["aria-label"] == null ? true : undefined}
|
|
40
|
+
{...rest}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
package/src/IconButton.tsx
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { ButtonHTMLAttributes, ReactNode } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
iconButtonClass,
|
|
4
|
+
type IconButtonSize,
|
|
5
|
+
type IconButtonVariant,
|
|
6
|
+
} from "./icon-button-classes";
|
|
3
7
|
|
|
4
|
-
export type { IconButtonSize };
|
|
8
|
+
export type { IconButtonSize, IconButtonVariant };
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* A square icon-only button — the kit's one answer for ✕, ⋮, ↻, ✏️, and
|
|
@@ -9,18 +13,27 @@ export type { IconButtonSize };
|
|
|
9
13
|
* label is the accessible name. Pair with {@link Tooltip} so sighted users
|
|
10
14
|
* get the same label on hover.
|
|
11
15
|
*
|
|
16
|
+
* Sized in terms of `--silo-font-size-base` so the hit target and child SVGs
|
|
17
|
+
* scale with Silo's UI zoom (`uiFontSize`). Prefer Phosphor `size="1em"`
|
|
18
|
+
* (or omit a fixed px size) so the glyph tracks the button.
|
|
19
|
+
*
|
|
12
20
|
* Styled purely via host-provided `.silo-icon-button*` classes — no
|
|
13
21
|
* stylesheet import is needed in the extension.
|
|
14
22
|
*
|
|
15
23
|
* @example
|
|
16
24
|
* ```tsx
|
|
17
25
|
* <IconButton aria-label="Refresh" onClick={refresh}>
|
|
18
|
-
* <RefreshIcon />
|
|
26
|
+
* <RefreshIcon size="1em" />
|
|
19
27
|
* </IconButton>
|
|
20
28
|
*
|
|
21
29
|
* // compact — e.g. in a ListRow's trailing slot
|
|
22
30
|
* <IconButton size="sm" aria-label="Pin" onClick={pin}>
|
|
23
|
-
* <PinIcon />
|
|
31
|
+
* <PinIcon size="1em" />
|
|
32
|
+
* </IconButton>
|
|
33
|
+
*
|
|
34
|
+
* // panel / breadcrumb toolbar (local-web-viewer tone)
|
|
35
|
+
* <IconButton size="sm" variant="toolbar" aria-label="Mark">
|
|
36
|
+
* <FlagIcon size="1em" weight="bold" />
|
|
24
37
|
* </IconButton>
|
|
25
38
|
* ```
|
|
26
39
|
*
|
|
@@ -29,19 +42,28 @@ export type { IconButtonSize };
|
|
|
29
42
|
*/
|
|
30
43
|
export function IconButton({
|
|
31
44
|
size = "normal",
|
|
45
|
+
variant = "normal",
|
|
32
46
|
className,
|
|
33
47
|
type = "button",
|
|
34
48
|
children,
|
|
35
49
|
"aria-label": ariaLabel,
|
|
36
50
|
...rest
|
|
37
51
|
}: {
|
|
38
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Hit-target size in `em` of `--silo-font-size-base` (tracks Zoom In/Out).
|
|
54
|
+
* `normal` = 2.5em, `sm` = 2em (local-web-viewer toolbar buttons).
|
|
55
|
+
*/
|
|
39
56
|
size?: IconButtonSize;
|
|
57
|
+
/**
|
|
58
|
+
* `"toolbar"` — black/white toolbar-text icons, hover fill only, no
|
|
59
|
+
* press-scale. Use on editor/terminal breadcrumb clusters and panel bars.
|
|
60
|
+
*/
|
|
61
|
+
variant?: IconButtonVariant;
|
|
40
62
|
/** Required — the icon is the only visual. */
|
|
41
63
|
"aria-label": string;
|
|
42
64
|
children?: ReactNode;
|
|
43
65
|
} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "aria-label">) {
|
|
44
|
-
const classes = iconButtonClass(size);
|
|
66
|
+
const classes = iconButtonClass(size, variant);
|
|
45
67
|
return (
|
|
46
68
|
<button
|
|
47
69
|
type={type}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { activityClass, activityFromAgent } from "./activity";
|
|
3
|
+
|
|
4
|
+
describe("activityClass", () => {
|
|
5
|
+
it("maps kinds and sizes", () => {
|
|
6
|
+
expect(activityClass("working", "md")).toBe(
|
|
7
|
+
"silo-activity silo-activity-working silo-activity-md",
|
|
8
|
+
);
|
|
9
|
+
expect(activityClass("ready")).toBe(
|
|
10
|
+
"silo-activity silo-activity-ready silo-activity-sm",
|
|
11
|
+
);
|
|
12
|
+
expect(activityClass("warn", "sm")).toBe(
|
|
13
|
+
"silo-activity silo-activity-warn silo-activity-sm",
|
|
14
|
+
);
|
|
15
|
+
expect(activityClass("error")).toBe(
|
|
16
|
+
"silo-activity silo-activity-error silo-activity-sm",
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("uses none fallback when activity is omitted", () => {
|
|
21
|
+
expect(activityClass(undefined)).toBe(
|
|
22
|
+
"silo-activity silo-activity-none silo-activity-sm",
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("activityFromAgent", () => {
|
|
28
|
+
it("maps overlapping agent states", () => {
|
|
29
|
+
expect(activityFromAgent("working")).toBe("working");
|
|
30
|
+
expect(activityFromAgent("idle")).toBe("ready");
|
|
31
|
+
expect(activityFromAgent("error")).toBe("error");
|
|
32
|
+
expect(activityFromAgent("none")).toBeNull();
|
|
33
|
+
expect(activityFromAgent("dead")).toBeNull();
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/activity.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { AgentActivity } from "./agents-service";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Host-owned activity state for chrome (workspace rows, CenterDock tabs,
|
|
5
|
+
* SideDock tabs, and the public {@link Activity} glyph). Extensions pick a
|
|
6
|
+
* kind only — never an icon, color, or motion. See ADR 0030.
|
|
7
|
+
*
|
|
8
|
+
* @category Core Types
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export type Activity = "working" | "ready" | "warn" | "error";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Glyph size for {@link Activity}. `"sm"` matches workspace status rows (~6px);
|
|
15
|
+
* `"md"` is slightly larger for CenterDock / SideDock tabs.
|
|
16
|
+
*
|
|
17
|
+
* @category Core Types
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export type ActivitySize = "sm" | "md";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Map {@link AgentActivity} onto UI {@link Activity}. Returns `null` when there
|
|
24
|
+
* is nothing to paint (`none` / `dead` — callers may map `dead` → `"error"`
|
|
25
|
+
* themselves if they want chrome).
|
|
26
|
+
*
|
|
27
|
+
* @category Core Types
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export function activityFromAgent(a: AgentActivity): Activity | null {
|
|
31
|
+
switch (a) {
|
|
32
|
+
case "working":
|
|
33
|
+
return "working";
|
|
34
|
+
case "idle":
|
|
35
|
+
return "ready";
|
|
36
|
+
case "error":
|
|
37
|
+
return "error";
|
|
38
|
+
case "none":
|
|
39
|
+
case "dead":
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the host `.silo-activity*` class string. Pinned by unit tests
|
|
46
|
+
* (RFC 0016 class-contract pattern). When `activity` is omitted, uses the
|
|
47
|
+
* neutral workspace fallback (gray “none” look).
|
|
48
|
+
*
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export function activityClass(
|
|
52
|
+
activity: Activity | undefined,
|
|
53
|
+
size: ActivitySize = "sm",
|
|
54
|
+
): string {
|
|
55
|
+
const kind = activity ?? "none";
|
|
56
|
+
return `silo-activity silo-activity-${kind} silo-activity-${size}`;
|
|
57
|
+
}
|
package/src/editor-service.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Disposable } from "./types";
|
|
2
2
|
import type { Event } from "./event";
|
|
3
3
|
import type { EditorMode } from "./domain-types";
|
|
4
|
+
import type { TabAdornmentMethods } from "./tab-adornment";
|
|
4
5
|
|
|
5
6
|
// `ctx.editors` — the editor & document domain (public contract). Opening files
|
|
6
7
|
// into editor tabs, the active-editor save/close commands, the diff-content
|
|
@@ -225,10 +226,13 @@ export interface EditorSaveEvent {
|
|
|
225
226
|
* editors register save handlers. The single entry point for opening editors —
|
|
226
227
|
* prefer it over reaching into workspace/editor state.
|
|
227
228
|
*
|
|
229
|
+
* Tab chrome adornments (`setIcon` / `setIndicator` / …) take an **editor id**
|
|
230
|
+
* as the target — see {@link TabAdornmentMethods}.
|
|
231
|
+
*
|
|
228
232
|
* @category Consumer Services
|
|
229
233
|
* @public
|
|
230
234
|
*/
|
|
231
|
-
export interface EditorService {
|
|
235
|
+
export interface EditorService extends TabAdornmentMethods {
|
|
232
236
|
/**
|
|
233
237
|
* Open a file in an editor tab. Promotes an existing preview, focuses an
|
|
234
238
|
* already-open tab, or opens a new one.
|
|
@@ -5,9 +5,19 @@ describe("iconButtonClass", () => {
|
|
|
5
5
|
it("defaults to silo-icon-button", () => {
|
|
6
6
|
expect(iconButtonClass()).toBe("silo-icon-button");
|
|
7
7
|
expect(iconButtonClass("normal")).toBe("silo-icon-button");
|
|
8
|
+
expect(iconButtonClass("normal", "normal")).toBe("silo-icon-button");
|
|
8
9
|
});
|
|
9
10
|
|
|
10
11
|
it("adds the sm modifier", () => {
|
|
11
12
|
expect(iconButtonClass("sm")).toBe("silo-icon-button silo-icon-button-sm");
|
|
12
13
|
});
|
|
14
|
+
|
|
15
|
+
it("adds the toolbar variant", () => {
|
|
16
|
+
expect(iconButtonClass("normal", "toolbar")).toBe(
|
|
17
|
+
"silo-icon-button silo-icon-button-toolbar",
|
|
18
|
+
);
|
|
19
|
+
expect(iconButtonClass("sm", "toolbar")).toBe(
|
|
20
|
+
"silo-icon-button silo-icon-button-sm silo-icon-button-toolbar",
|
|
21
|
+
);
|
|
22
|
+
});
|
|
13
23
|
});
|
|
@@ -6,14 +6,27 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export type IconButtonSize = "normal" | "sm";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Visual tone for {@link IconButton}. `"toolbar"` matches the local-web-viewer
|
|
11
|
+
* bar buttons (toolbar-text icons, hover fill only, no press-scale).
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export type IconButtonVariant = "normal" | "toolbar";
|
|
16
|
+
|
|
9
17
|
/**
|
|
10
18
|
* Resolve the host `.silo-icon-button*` class string for an IconButton's
|
|
11
|
-
* `size`. Default is the
|
|
19
|
+
* `size` + `variant`. Default is the standalone size; `sm` adds the compact
|
|
20
|
+
* modifier; `toolbar` swaps in the breadcrumb/panel-toolbar tone.
|
|
12
21
|
*
|
|
13
22
|
* @internal
|
|
14
23
|
*/
|
|
15
|
-
export function iconButtonClass(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
export function iconButtonClass(
|
|
25
|
+
size: IconButtonSize = "normal",
|
|
26
|
+
variant: IconButtonVariant = "normal",
|
|
27
|
+
): string {
|
|
28
|
+
const parts = ["silo-icon-button"];
|
|
29
|
+
if (size === "sm") parts.push("silo-icon-button-sm");
|
|
30
|
+
if (variant === "toolbar") parts.push("silo-icon-button-toolbar");
|
|
31
|
+
return parts.join(" ");
|
|
19
32
|
}
|
package/src/index.ts
CHANGED
|
@@ -110,6 +110,37 @@ export type {
|
|
|
110
110
|
TerminalTabDecorationProvider,
|
|
111
111
|
OscEvent,
|
|
112
112
|
} from "./terminal-service";
|
|
113
|
+
export type {
|
|
114
|
+
TabAdornmentColor,
|
|
115
|
+
TabIconAdornment,
|
|
116
|
+
TabIndicatorAdornment,
|
|
117
|
+
TabIndicatorFlash,
|
|
118
|
+
TabActivityAdornment,
|
|
119
|
+
TabActivityFlash,
|
|
120
|
+
TabIconContribution,
|
|
121
|
+
TabIndicatorContribution,
|
|
122
|
+
TabActivityContribution,
|
|
123
|
+
TabIconBinder,
|
|
124
|
+
TabIndicatorBinder,
|
|
125
|
+
TabActivityBinder,
|
|
126
|
+
TabAdornmentMethods,
|
|
127
|
+
} from "./tab-adornment";
|
|
128
|
+
export type { Activity, ActivitySize } from "./activity";
|
|
129
|
+
export { activityFromAgent } from "./activity";
|
|
130
|
+
export { ActivityGlyph } from "./ActivityGlyph";
|
|
131
|
+
export type { PhosphorIconName } from "./phosphor-icon";
|
|
132
|
+
export type {
|
|
133
|
+
ToolbarSurface,
|
|
134
|
+
ToolbarItemContext,
|
|
135
|
+
ToolbarItemFields,
|
|
136
|
+
ToolbarCommandItemContribution,
|
|
137
|
+
ToolbarMenuItemContribution,
|
|
138
|
+
ToolbarChromeFields,
|
|
139
|
+
ToolbarSeparatorContribution,
|
|
140
|
+
ToolbarSpacerSize,
|
|
141
|
+
ToolbarSpacerContribution,
|
|
142
|
+
ToolbarItemContribution,
|
|
143
|
+
} from "./toolbar-items";
|
|
113
144
|
export type {
|
|
114
145
|
FileService,
|
|
115
146
|
FileMeta,
|
|
@@ -226,7 +257,7 @@ export { Tooltip } from "./Tooltip";
|
|
|
226
257
|
export { Button } from "./Button";
|
|
227
258
|
export type { ButtonVariant, ButtonSize } from "./Button";
|
|
228
259
|
export { IconButton } from "./IconButton";
|
|
229
|
-
export type { IconButtonSize } from "./IconButton";
|
|
260
|
+
export type { IconButtonSize, IconButtonVariant } from "./IconButton";
|
|
230
261
|
export { Input } from "./Input";
|
|
231
262
|
export { Textarea } from "./Textarea";
|
|
232
263
|
export { SearchInput } from "./SearchInput";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export name of an icon from `@phosphor-icons/react` — e.g. `"Flag"`,
|
|
3
|
+
* `"ArrowClockwise"`, `"PushPin"`. The host resolves the name and paints it:
|
|
4
|
+
* toolbar chrome uses `weight="bold"`; tab decorations use `weight="regular"`
|
|
5
|
+
* by default (`filled: true` → `weight="fill"`); both use `size="1em"` so
|
|
6
|
+
* glyphs track UI zoom.
|
|
7
|
+
*
|
|
8
|
+
* Use the PascalCase component name from
|
|
9
|
+
* [Phosphor](https://phosphoricons.com), not a kebab-case path.
|
|
10
|
+
*
|
|
11
|
+
* @category Registration
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export type PhosphorIconName = string;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { Activity } from "./activity";
|
|
3
|
+
import type { PhosphorIconName } from "./phosphor-icon";
|
|
4
|
+
import type { Disposable } from "./types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Semantic color for a CenterDock tab trailing {@link TabIndicatorAdornment}
|
|
8
|
+
* (and optional chip background).
|
|
9
|
+
*
|
|
10
|
+
* @category Consumer Services
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export type TabAdornmentColor = "accent" | "warn" | "ok" | "error" | "muted";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Leading identity adornment on a CenterDock tab — arbitrary React artwork
|
|
17
|
+
* (e.g. an app logo). Set via {@link EditorService.setIcon} /
|
|
18
|
+
* {@link TerminalService.setIcon}.
|
|
19
|
+
*
|
|
20
|
+
* @category Consumer Services
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export interface TabIconAdornment {
|
|
24
|
+
/** Extension-owned key; stacking + {@link EditorService.clearIcon} target. */
|
|
25
|
+
id: string;
|
|
26
|
+
/** Leading glyph / logo rendered before the tab title. */
|
|
27
|
+
icon: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Trailing status adornment on a CenterDock tab — static Phosphor glyph.
|
|
32
|
+
* For busy/ready/warn/error chrome use {@link TabActivityAdornment} instead
|
|
33
|
+
* (ADR 0030).
|
|
34
|
+
*
|
|
35
|
+
* Set via {@link EditorService.setIndicator} /
|
|
36
|
+
* {@link TerminalService.setIndicator}.
|
|
37
|
+
*
|
|
38
|
+
* @category Consumer Services
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export interface TabIndicatorAdornment {
|
|
42
|
+
/** Extension-owned key; stacking + clear target. */
|
|
43
|
+
id: string;
|
|
44
|
+
/**
|
|
45
|
+
* Glyph as a {@link PhosphorIconName} (e.g. `"Flag"`). The host resolves
|
|
46
|
+
* and paints it at 1em in regular weight by default. Set
|
|
47
|
+
* {@link TabIndicatorAdornment.filled | filled} for Phosphor fill weight;
|
|
48
|
+
* {@link TabIndicatorAdornment.color | color} tints the glyph; set
|
|
49
|
+
* {@link TabIndicatorAdornment.chip | chip} for a soft tinted background.
|
|
50
|
+
*/
|
|
51
|
+
icon: PhosphorIconName;
|
|
52
|
+
/** Tooltip shown when hovering the indicator. */
|
|
53
|
+
tooltip?: string;
|
|
54
|
+
/** Semantic color for the glyph (and chip fill). */
|
|
55
|
+
color?: TabAdornmentColor;
|
|
56
|
+
/**
|
|
57
|
+
* When true, paint a soft tinted chip behind the icon. Default is
|
|
58
|
+
* glyph-only — no background.
|
|
59
|
+
*/
|
|
60
|
+
chip?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* When true, paint the glyph with Phosphor `weight="fill"`. Default is
|
|
63
|
+
* regular weight (outline).
|
|
64
|
+
*/
|
|
65
|
+
filled?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Host-owned {@link Activity} on a CenterDock tab. Extensions pick the kind
|
|
70
|
+
* (+ optional tooltip); never an icon or color (ADR 0030).
|
|
71
|
+
*
|
|
72
|
+
* @category Consumer Services
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export interface TabActivityAdornment {
|
|
76
|
+
/** Extension-owned key; stacking + clear target. */
|
|
77
|
+
id: string;
|
|
78
|
+
activity: Activity;
|
|
79
|
+
tooltip?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Payload for {@link EditorService.flashIndicator} /
|
|
84
|
+
* {@link TerminalService.flashIndicator} — timed one-shot; no stable `id`
|
|
85
|
+
* (auto-cleared after `durationMs`).
|
|
86
|
+
*
|
|
87
|
+
* @category Consumer Services
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
export type TabIndicatorFlash = TabIndicatorContribution & {
|
|
91
|
+
/** How long to show the flash. Defaults to host choice (typically ~800ms). */
|
|
92
|
+
durationMs?: number;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Payload for {@link EditorService.flashActivity} /
|
|
97
|
+
* {@link TerminalService.flashActivity}.
|
|
98
|
+
*
|
|
99
|
+
* @category Consumer Services
|
|
100
|
+
* @public
|
|
101
|
+
*/
|
|
102
|
+
export type TabActivityFlash = TabActivityContribution & {
|
|
103
|
+
durationMs?: number;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Fields contributed by a {@link TabIconBinder.provide} call (the binder’s
|
|
108
|
+
* own `id` is applied by the host).
|
|
109
|
+
*
|
|
110
|
+
* @category Consumer Services
|
|
111
|
+
* @public
|
|
112
|
+
*/
|
|
113
|
+
export type TabIconContribution = Omit<TabIconAdornment, "id">;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Fields contributed by a {@link TabIndicatorBinder.provide} call.
|
|
117
|
+
*
|
|
118
|
+
* @category Consumer Services
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
export type TabIndicatorContribution = Omit<TabIndicatorAdornment, "id">;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Fields contributed by a {@link TabActivityBinder.provide} call.
|
|
125
|
+
*
|
|
126
|
+
* @category Consumer Services
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
129
|
+
export type TabActivityContribution = Omit<TabActivityAdornment, "id">;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Keep a leading-icon projection in sync for every editor/terminal tab.
|
|
133
|
+
* Prefer over repeatedly calling {@link EditorService.setIcon}.
|
|
134
|
+
*
|
|
135
|
+
* @category Consumer Services
|
|
136
|
+
* @public
|
|
137
|
+
*/
|
|
138
|
+
export interface TabIconBinder {
|
|
139
|
+
/** Extension-owned key — conventionally `"<extension-id>.tab-icon"`. */
|
|
140
|
+
id: string;
|
|
141
|
+
/**
|
|
142
|
+
* Called synchronously per tab during render. Return `null` to contribute
|
|
143
|
+
* nothing for this target id (editor id or terminal session id).
|
|
144
|
+
*/
|
|
145
|
+
provide(targetId: string): TabIconContribution | null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Keep a trailing-indicator projection in sync for every editor/terminal tab.
|
|
150
|
+
*
|
|
151
|
+
* @category Consumer Services
|
|
152
|
+
* @public
|
|
153
|
+
*/
|
|
154
|
+
export interface TabIndicatorBinder {
|
|
155
|
+
/** Extension-owned key — conventionally `"<extension-id>.tab-indicator"`. */
|
|
156
|
+
id: string;
|
|
157
|
+
/**
|
|
158
|
+
* Called synchronously per tab during render. Return `null` to contribute
|
|
159
|
+
* nothing for this target id.
|
|
160
|
+
*/
|
|
161
|
+
provide(targetId: string): TabIndicatorContribution | null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Keep a trailing-activity projection in sync for every editor/terminal tab.
|
|
166
|
+
*
|
|
167
|
+
* @category Consumer Services
|
|
168
|
+
* @public
|
|
169
|
+
*/
|
|
170
|
+
export interface TabActivityBinder {
|
|
171
|
+
/** Extension-owned key — conventionally `"<extension-id>.tab-activity"`. */
|
|
172
|
+
id: string;
|
|
173
|
+
provide(targetId: string): TabActivityContribution | null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Shared adorn verbs for CenterDock editor and terminal tabs. Implemented by
|
|
178
|
+
* {@link EditorService} and {@link TerminalService} (target id is the editor
|
|
179
|
+
* or terminal session id respectively).
|
|
180
|
+
*
|
|
181
|
+
* @category Consumer Services
|
|
182
|
+
* @public
|
|
183
|
+
*/
|
|
184
|
+
export interface TabAdornmentMethods {
|
|
185
|
+
setIcon(targetId: string, adornment: TabIconAdornment): void;
|
|
186
|
+
clearIcon(targetId: string, adornmentId: string): void;
|
|
187
|
+
bindIcon(binder: TabIconBinder): Disposable;
|
|
188
|
+
|
|
189
|
+
setIndicator(targetId: string, adornment: TabIndicatorAdornment): void;
|
|
190
|
+
clearIndicator(targetId: string, adornmentId: string): void;
|
|
191
|
+
flashIndicator(targetId: string, flash: TabIndicatorFlash): void;
|
|
192
|
+
bindIndicator(binder: TabIndicatorBinder): Disposable;
|
|
193
|
+
|
|
194
|
+
setActivity(targetId: string, adornment: TabActivityAdornment): void;
|
|
195
|
+
clearActivity(targetId: string, adornmentId: string): void;
|
|
196
|
+
flashActivity(targetId: string, flash: TabActivityFlash): void;
|
|
197
|
+
bindActivity(binder: TabActivityBinder): Disposable;
|
|
198
|
+
|
|
199
|
+
/** All leading icons for `targetId`, in set/bind order. */
|
|
200
|
+
getIcons(targetId: string): TabIconAdornment[];
|
|
201
|
+
/** All trailing indicators for `targetId`, in set/bind/flash order. */
|
|
202
|
+
getIndicators(targetId: string): TabIndicatorAdornment[];
|
|
203
|
+
/** All trailing activities for `targetId`, in set/bind/flash order. */
|
|
204
|
+
getActivities(targetId: string): TabActivityAdornment[];
|
|
205
|
+
/** Signal that binder data changed — re-query `provide` and re-render. */
|
|
206
|
+
invalidateTabAdornments(): void;
|
|
207
|
+
subscribeTabAdornments(listener: () => void): Disposable;
|
|
208
|
+
}
|
package/src/terminal-service.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type React from "react";
|
|
2
1
|
import type { Disposable } from "./types";
|
|
3
2
|
import type { TerminalKind, TerminalRecord } from "./domain-types";
|
|
3
|
+
import type {
|
|
4
|
+
TabAdornmentMethods,
|
|
5
|
+
TabIndicatorContribution,
|
|
6
|
+
} from "./tab-adornment";
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* A parsed OSC (Operating System Command) escape sequence emitted by a
|
|
@@ -26,32 +29,18 @@ export interface OscEvent {
|
|
|
26
29
|
export type { TerminalKind, TerminalRecord } from "./domain-types";
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
+
* @deprecated Prefer {@link TerminalService.setIndicator} /
|
|
33
|
+
* {@link TerminalService.bindIndicator}. Alias for a trailing indicator
|
|
34
|
+
* contribution (no `id` — the provider id supplies it).
|
|
32
35
|
*
|
|
33
36
|
* @category Consumer Services
|
|
34
37
|
* @public
|
|
35
38
|
*/
|
|
36
|
-
export
|
|
37
|
-
/**
|
|
38
|
-
* Small React node rendered as a decoration badge on the tab (≤16 px).
|
|
39
|
-
* The extension supplies the shape; the host applies `color` via a CSS
|
|
40
|
-
* data attribute mapped to design tokens.
|
|
41
|
-
*/
|
|
42
|
-
icon: React.ReactNode;
|
|
43
|
-
/** Tooltip shown when hovering the decoration icon. */
|
|
44
|
-
tooltip?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Semantic color applied to the icon element. The host maps this to the
|
|
47
|
-
* matching `--silo-color-*` design token so themes control the exact shade.
|
|
48
|
-
*/
|
|
49
|
-
color?: "accent" | "warn" | "ok" | "error" | "muted";
|
|
50
|
-
}
|
|
39
|
+
export type TerminalTabDecoration = TabIndicatorContribution;
|
|
51
40
|
|
|
52
41
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
42
|
+
* @deprecated Prefer {@link TerminalService.bindIndicator}. Terminal-only
|
|
43
|
+
* trailing-indicator provider kept as a shim over the adornment registry.
|
|
55
44
|
*
|
|
56
45
|
* @category Consumer Services
|
|
57
46
|
* @public
|
|
@@ -61,8 +50,7 @@ export interface TerminalTabDecorationProvider {
|
|
|
61
50
|
id: string;
|
|
62
51
|
/**
|
|
63
52
|
* Called synchronously for each terminal tab during render. Return `null`
|
|
64
|
-
* to contribute nothing for this terminal.
|
|
65
|
-
* registered, the first non-null result wins.
|
|
53
|
+
* to contribute nothing for this terminal.
|
|
66
54
|
*/
|
|
67
55
|
provide(terminalId: string): TerminalTabDecoration | null;
|
|
68
56
|
}
|
|
@@ -92,10 +80,13 @@ export interface CreateTerminalInput {
|
|
|
92
80
|
* deleting the workspace. The tab itself is rendered by the core dock from the
|
|
93
81
|
* workspace's terminal records.
|
|
94
82
|
*
|
|
83
|
+
* Tab chrome adornments (`setIcon` / `setIndicator` / …) take a **terminal
|
|
84
|
+
* session id** as the target — see {@link TabAdornmentMethods}.
|
|
85
|
+
*
|
|
95
86
|
* @category Consumer Services
|
|
96
87
|
* @public
|
|
97
88
|
*/
|
|
98
|
-
export interface TerminalService {
|
|
89
|
+
export interface TerminalService extends TabAdornmentMethods {
|
|
99
90
|
/**
|
|
100
91
|
* Open a new terminal in a workspace (defaults to the active one). Returns the
|
|
101
92
|
* created {@link TerminalRecord}; the PTY session spawns lazily when its tab
|
|
@@ -156,29 +147,24 @@ export interface TerminalService {
|
|
|
156
147
|
focus(terminalId: string): void;
|
|
157
148
|
|
|
158
149
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* providers are not consulted. Returns a {@link Disposable} that unregisters
|
|
162
|
-
* the provider.
|
|
150
|
+
* @deprecated Prefer {@link TerminalService.bindIndicator}. Thin shim that
|
|
151
|
+
* registers a trailing-indicator binder for terminal tabs only.
|
|
163
152
|
*/
|
|
164
153
|
registerTabDecoration(provider: TerminalTabDecorationProvider): Disposable;
|
|
165
154
|
|
|
166
155
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
156
|
+
* @deprecated Prefer {@link TerminalService.getIndicators}. Returns the first
|
|
157
|
+
* trailing indicator for a terminal tab, or `null`.
|
|
169
158
|
*/
|
|
170
159
|
getTabDecoration(terminalId: string): TerminalTabDecoration | null;
|
|
171
160
|
|
|
172
161
|
/**
|
|
173
|
-
*
|
|
174
|
-
* via {@link TerminalService.subscribeTabDecorations}, causing terminal tabs
|
|
175
|
-
* to re-query providers and re-render their decoration.
|
|
162
|
+
* @deprecated Prefer {@link TerminalService.invalidateTabAdornments}.
|
|
176
163
|
*/
|
|
177
164
|
invalidateTabDecorations(): void;
|
|
178
165
|
|
|
179
166
|
/**
|
|
180
|
-
*
|
|
181
|
-
* that cancels the subscription.
|
|
167
|
+
* @deprecated Prefer {@link TerminalService.subscribeTabAdornments}.
|
|
182
168
|
*/
|
|
183
169
|
subscribeTabDecorations(listener: () => void): Disposable;
|
|
184
170
|
|