chore: sync website translation parent

This commit is contained in:
Mohamed Boudra
2026-10-20 08:49:08 +02:00
358 changed files with 16024 additions and 7804 deletions
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@getpaseo/plugin",
"version": "0.12.0-beta.3",
"version": "0.12.0",
"description": "Paseo plugin SDK package",
"files": [
"dist",
@@ -71,20 +71,20 @@
"use-sync-external-store": "^1.6.0"
},
"devDependencies": {
"@getpaseo/client": "0.12.0-beta.3",
"@getpaseo/protocol": "0.12.0-beta.3",
"@getpaseo/client": "0.12.0",
"@getpaseo/protocol": "0.12.0",
"@types/node": "^20.9.0",
"@types/react": "~19.2.0",
"react": "19.1.0",
"react-native": "0.81.5",
"react": "19.2.3",
"react-native": "0.86.3",
"typescript": "^5.9.3",
"vitest": "^4.1.6",
"zod": "^4.4.3"
},
"peerDependencies": {
"@getpaseo/client": "0.12.0-beta.3",
"@getpaseo/protocol": "0.12.0-beta.3",
"react": "~19.1.0",
"@getpaseo/client": "0.12.0",
"@getpaseo/protocol": "0.12.0",
"react": ">=19.1.0 <20",
"react-native": ">=0.81.5",
"zod": "^4.4.3"
},
+7 -4
View File
@@ -1,14 +1,17 @@
import type { PluginText } from "../text.js";
import type { ComponentType } from "react";
import type { PluginHostProps } from "./contracts.js";
import type { PluginIconProps } from "../icons.js";
import type { PluginHostProps, PluginIcon } from "./contracts.js";
export type PluginButtonContext =
| { context: "workspace"; workspaceId: string }
| { context: "agent"; workspaceId: string; agentId: string };
export type PluginButtonIconProps = PluginHostProps &
PluginButtonContext & { size: number; color: string };
export type PluginButtonIconProps = PluginHostProps & PluginButtonContext & PluginIconProps;
export type PluginButtonContentProps = PluginHostProps & PluginButtonContext & { close(): void };
export type PluginButtonIcon = string | ComponentType<PluginButtonIconProps>;
export type PluginButtonIcon = PluginIcon<PluginButtonIconProps>;
export type PluginButtonBehavior<Text extends PluginText = string> =
| { kind: "action"; onPress(): void | Promise<void> }
+12 -9
View File
@@ -18,6 +18,7 @@ import type {
PluginTimelineTransformResult,
PluginCleanup,
} from "../contracts.js";
import type { PluginIconProps, PluginSerializableIcon } from "../icons.js";
export interface PluginHostProps {
theme: PluginTheme;
@@ -88,11 +89,13 @@ export interface PluginSidebarItemContribution<Text extends PluginText = string>
Component: ComponentType<PluginSidebarItemProps>;
}
export interface PluginIconProps {
name: string;
size?: number;
color?: string;
}
/**
* A Lucide icon name, inline SVG markup, or a component. Components receive the surface's size
* and color; buttons widen the props with their host and target context.
*/
export type PluginIcon<Props extends PluginIconProps = PluginIconProps> =
| PluginSerializableIcon
| ComponentType<Props>;
export type PluginPanelLocation = "workspace" | "explorer";
@@ -103,7 +106,7 @@ export interface PluginOpenPanelOptions {
interface PluginWorkspacePanelBase<Text extends PluginText = string> {
id: string;
title: Text;
icon: string;
icon: PluginIcon;
locations?: readonly PluginPanelLocation[];
}
@@ -176,7 +179,7 @@ export type PluginWorkspacePanelContribution<Text extends PluginText = string> =
export interface PluginSettingsScreenContribution<Text extends PluginText = string> {
id: string;
title: Text;
icon: string;
icon: PluginIcon;
Component: ComponentType<PluginSurfaceProps>;
}
@@ -200,7 +203,7 @@ export interface PluginSurfaceContribution {
export interface PluginSidebarContribution<Text extends PluginText = string> {
id: string;
title: Text;
icon: string;
icon: PluginIcon;
surface: string;
}
@@ -269,7 +272,7 @@ export interface PluginAgentCommandContext extends PluginCommandCapabilities {
interface PluginCommandCenterItemBase<Text extends PluginText = string> {
id: string;
title: Text;
icon: string;
icon: PluginIcon;
keywords?: readonly string[];
}
+2 -1
View File
@@ -8,7 +8,7 @@ export type {
PluginScreenLocation,
PluginSidebarItemProps,
PluginSidebarItemContribution,
PluginIconProps,
PluginIcon,
PluginPanelLocation,
PluginOpenPanelOptions,
PluginWorkspacePanelProps,
@@ -45,6 +45,7 @@ export type {
PluginComposerPillContribution,
PluginHeaderButtonContribution,
} from "./buttons.js";
export type { PluginIconProps, PluginSerializableIcon, PluginSvgIcon } from "../icons.js";
export { usePaseo } from "./paseo-context.js";
export { useAgent, useWorkspace } from "./client-state.js";
export { useRpc } from "./rpc-context.js";
+8 -3
View File
@@ -17,7 +17,8 @@ import type {
TextInput as NativeTextInput,
TextInputProps,
} from "react-native";
import type { PluginIconProps } from "./contracts.js";
import type { PluginIconProps } from "../icons.js";
import type { PluginIcon } from "./contracts.js";
export interface ModalProps {
title: string;
@@ -53,12 +54,16 @@ export interface ToastApi {
error(message: string): void;
}
export declare const Icon: ComponentType<PluginIconProps>;
/** Renders a Lucide icon by `name`, or any plugin icon by `icon`. An unusable icon renders nothing. */
export type IconProps = Partial<PluginIconProps> &
({ name: string; icon?: never } | { icon: PluginIcon; name?: never });
export declare const Icon: ComponentType<IconProps>;
export declare const Modal: ModalComponent;
export declare function useToast(): ToastApi;
export declare function useRevealedText(text: string, phase: "streaming" | "complete"): string;
export type { PluginIconProps } from "./contracts.js";
export type { PluginIconProps } from "../icons.js";
/** React Native scrolling with the host's sheet gestures when rendered inside a sheet. */
export declare const ScrollView: ForwardRefExoticComponent<
+3 -2
View File
@@ -1,4 +1,5 @@
import type { ComponentType, ReactNode, Ref } from "react";
import type { PluginIcon } from "./contracts.js";
export interface SettingsSectionProps {
title: string;
@@ -64,14 +65,14 @@ export interface ExternalLinkProps {
}
export declare const ExternalLink: ComponentType<ExternalLinkProps>;
export type SidebarIcon = string | ComponentType<{ size: number; color: string }>;
export type SidebarIcon = PluginIcon;
export interface SidebarRowProps {
/**
* Tells rows of one item apart when the item renders several: "bot-2". Unique within the item.
* Omit it when the item renders one row.
*/
id?: string;
/** A Lucide icon name or a component. */
/** A Lucide icon name, inline SVG, or a component. */
icon?: SidebarIcon;
/** Defaults to the item's registered title. */
label?: string;
+2 -1
View File
@@ -1,5 +1,6 @@
import type { PluginText } from "./text.js";
import type { JsonValue } from "@getpaseo/protocol/agent-types";
import type { PluginSerializableIcon } from "./icons.js";
import type { PluginRpcContract } from "./rpc.js";
export interface PluginTheme {
@@ -74,7 +75,7 @@ export interface PluginThemeContribution<Text extends PluginText = string> {
export interface PluginAttachmentSourceContribution<Text extends PluginText = string> {
id: string;
title: Text;
icon: string;
icon: PluginSerializableIcon;
pickerTitle: Text;
searchPlaceholder: Text;
search: PluginRpcContract;
+53
View File
@@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
import { findSvgIconProblem } from "./icons.js";
describe("findSvgIconProblem", () => {
it.each([
["a plain SVG", '<svg viewBox="0 0 24 24"><path d="M0 0h24v24z" /></svg>'],
["leading whitespace", '\n <svg viewBox="0 0 24 24"></svg>'],
[
"a fragment reference",
'<svg><defs><path id="mark" d="M0 0h1v1z" /></defs><use href="#mark" /></svg>',
],
["currentColor fills", '<svg fill="currentColor"><circle r="4" /></svg>'],
])("accepts %s", (_name, svg) => {
expect(findSvgIconProblem(svg)).toBeNull();
});
it.each([
["a non-SVG document", "hello", "not an SVG document"],
["an <svgx> element", "<svgx></svgx>", "not an SVG document"],
["a script", "<svg><script /></svg>", "script elements are not allowed"],
["a foreign object", "<svg><foreignObject /></svg>", "foreignObject elements are not allowed"],
["a style", "<svg><style /></svg>", "style elements are not allowed"],
[
"an event handler",
'<svg><path onclick="run()" /></svg>',
"event-handler attributes are not allowed",
],
[
"a javascript URL",
'<svg><a href="javascript:run()" /></svg>',
"javascript URLs are not allowed",
],
[
"an external href",
'<svg><use href="https://example.com/icon.svg" /></svg>',
"external href references are not allowed",
],
[
"an external xlink:href",
"<svg><image xlink:href=icon.png /></svg>",
"external href references are not allowed",
],
["markup over 64 KiB", `<svg>${" ".repeat(64 * 1024)}</svg>`, "exceeds 64 KiB"],
])("rejects %s", (_name, svg, reason) => {
expect(findSvgIconProblem(svg)).toBe(reason);
});
it("measures the size in UTF-8 bytes", () => {
const multibyte = "é".repeat(32 * 1024);
expect(findSvgIconProblem(`<svg>${multibyte}</svg>`)).toBe("exceeds 64 KiB");
});
});
+38
View File
@@ -0,0 +1,38 @@
/** What a component icon receives from the surface that draws it. */
export interface PluginIconProps {
size: number;
color: string;
}
/** Inline SVG markup. Paseo validates it when the contribution registers. */
export interface PluginSvgIcon {
svg: string;
}
/** An icon that can be stored or sent: a Lucide icon name, or inline SVG. */
export type PluginSerializableIcon = string | PluginSvgIcon;
export const PLUGIN_SVG_ICON_MAX_BYTES = 64 * 1024;
const EXTERNAL_HREF = /\s(?:href|xlink:href)\s*=\s*(?:(["'])(.*?)\1|([^\s>]+))/gi;
/**
* Why Paseo refuses to render this SVG, or null when it is a self-contained document.
* The daemon applies it to provider and usage-source icon files; the app to inline plugin icons.
*/
export function findSvgIconProblem(svg: string): string | null {
if (new TextEncoder().encode(svg).byteLength > PLUGIN_SVG_ICON_MAX_BYTES) {
return "exceeds 64 KiB";
}
if (!/^\s*<svg(?:\s|>)/i.test(svg)) return "not an SVG document";
if (/<script(?:\s|>)/i.test(svg)) return "script elements are not allowed";
if (/<foreignObject(?:\s|>)/i.test(svg)) return "foreignObject elements are not allowed";
if (/<style(?:\s|>)/i.test(svg)) return "style elements are not allowed";
if (/\son[a-z0-9_-]*\s*=/i.test(svg)) return "event-handler attributes are not allowed";
if (/javascript\s*:/i.test(svg)) return "javascript URLs are not allowed";
for (const match of svg.matchAll(EXTERNAL_HREF)) {
const href = match[2] ?? match[3] ?? "";
if (!href.startsWith("#")) return "external href references are not allowed";
}
return null;
}
+7
View File
@@ -22,3 +22,10 @@ export {
export { defineRpc, type PluginRpcContract, type RpcInput, type RpcOutput } from "./rpc.js";
export type { PluginText, PluginMessage } from "./text.js";
export {
findSvgIconProblem,
PLUGIN_SVG_ICON_MAX_BYTES,
type PluginIconProps,
type PluginSerializableIcon,
type PluginSvgIcon,
} from "./icons.js";