@webmcpui/react 0.3.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/README.md +90 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +153 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @webmcpui/react
|
|
2
|
+
|
|
3
|
+
Idiomatic, typed **React** components for [webmcpui](https://webmcpui.com) —
|
|
4
|
+
WebMCP-native, accessible, shadcn/Tailwind-aligned.
|
|
5
|
+
|
|
6
|
+
Each component wraps the corresponding [`@webmcpui/core`](https://www.npmjs.com/package/@webmcpui/core)
|
|
7
|
+
custom element via [`@lit/react`](https://www.npmjs.com/package/@lit/react), so
|
|
8
|
+
the WebMCP tool exposure, form association, and accessibility live **once** (in
|
|
9
|
+
core) and you get typed props, `ref` forwarding, and `on*` event handlers.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @webmcpui/react @webmcpui/core react react-dom
|
|
15
|
+
# optional theme (shadcn-aligned):
|
|
16
|
+
pnpm add @webmcpui/tokens
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Button, Input, Dialog, Tabs } from '@webmcpui/react';
|
|
23
|
+
import '@webmcpui/tokens/css'; // omit for an unstyled baseline (see below)
|
|
24
|
+
|
|
25
|
+
function Example() {
|
|
26
|
+
const [email, setEmail] = React.useState('');
|
|
27
|
+
const [open, setOpen] = React.useState(false);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
<Button variant="primary" onClick={() => setOpen(true)}>Book</Button>
|
|
32
|
+
|
|
33
|
+
{/* form control — expose it and an agent can fill it */}
|
|
34
|
+
<Input label="Email" type="email" value={email}
|
|
35
|
+
onInput={(e) => setEmail(e.currentTarget.value)} expose />
|
|
36
|
+
|
|
37
|
+
{/* the agent opens it; the human confirms */}
|
|
38
|
+
<Dialog open={open} label="Confirm" onClose={() => setOpen(false)} expose>
|
|
39
|
+
<Button variant="primary" onClick={() => setOpen(false)}>Confirm</Button>
|
|
40
|
+
</Dialog>
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Every component takes `expose` (+ optional `toolName` / `toolDescription`) to
|
|
47
|
+
register its [WebMCP](https://webmcpui.com/docs/webmcp) tool — a click, a fill,
|
|
48
|
+
an open — that an agent can call. With no agent present it's a no-op.
|
|
49
|
+
|
|
50
|
+
## Components
|
|
51
|
+
|
|
52
|
+
`Button` · `Input` · `Dialog` · `Tabs` — more land each release as the core kit
|
|
53
|
+
grows. Props mirror the [element attributes](https://webmcpui.com/docs) (camelCased):
|
|
54
|
+
`variant`, `size`, `value`, `type`, `open`, `active`, `disabled`, `expose`, `toolName`, …
|
|
55
|
+
|
|
56
|
+
Imperative handles come through the `ref` — e.g. `dialogRef.current.show()`.
|
|
57
|
+
|
|
58
|
+
## Styling
|
|
59
|
+
|
|
60
|
+
Themed through the [design tokens](https://www.npmjs.com/package/@webmcpui/tokens)
|
|
61
|
+
(CSS custom properties, shadcn-aligned, light + dark). Two modes:
|
|
62
|
+
|
|
63
|
+
- **Themed** — `import '@webmcpui/tokens/css'` once at your app root.
|
|
64
|
+
- **Unstyled** — don't import the tokens CSS. The elements render with neutral
|
|
65
|
+
inline fallbacks; style them yourself via the CSS custom properties or the
|
|
66
|
+
`::part()` selectors each element exposes.
|
|
67
|
+
|
|
68
|
+
## Server rendering (Next.js, Remix, …)
|
|
69
|
+
|
|
70
|
+
These are **client-rendered custom elements** — importing them evaluates
|
|
71
|
+
`class extends HTMLElement`, which has no meaning on the server. In an SSR/RSC
|
|
72
|
+
framework, load them client-side:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
'use client';
|
|
76
|
+
import dynamic from 'next/dynamic';
|
|
77
|
+
const Button = dynamic(() => import('@webmcpui/react').then((m) => m.Button), {
|
|
78
|
+
ssr: false,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
(`'use client'` alone isn't enough — Next still renders client components on the
|
|
83
|
+
server. Use `ssr: false`, or add a DOM shim such as
|
|
84
|
+
[`@lit-labs/ssr-dom-shim`](https://www.npmjs.com/package/@lit-labs/ssr-dom-shim)
|
|
85
|
+
if you want them in the server render.) The elements upgrade and hydrate on the
|
|
86
|
+
client normally.
|
|
87
|
+
|
|
88
|
+
## Docs
|
|
89
|
+
|
|
90
|
+
Full docs, live demos, and `llms.txt` at **[webmcpui.com](https://webmcpui.com)**.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as _lit_react from '@lit/react';
|
|
2
|
+
import { WmcpButton, WmcpInput, WmcpDialog, WmcpTabs, WmcpSwitch, WmcpBadge, WmcpSeparator, WmcpTooltip, WmcpAlert, WmcpProgress, WmcpAvatar } from '@webmcpui/core';
|
|
3
|
+
export { WmcpAlertVariant, WmcpBadgeVariant, WmcpButtonSize, WmcpButtonType, WmcpButtonVariant, WmcpInputType } from '@webmcpui/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `<Button>` — an idiomatic, typed React wrapper over `<wmcp-button>`.
|
|
7
|
+
*
|
|
8
|
+
* All the behavior (form-associated submit/reset, WebMCP action exposure, a11y)
|
|
9
|
+
* lives in `@webmcpui/core`; this adds React ergonomics: typed props
|
|
10
|
+
* (`variant`, `size`, `type`, `disabled`, `expose`, `toolName`, …), `ref`
|
|
11
|
+
* forwarding to the element, and the composed `click` surfaced as `onClick`.
|
|
12
|
+
*
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { Button } from '@webmcpui/react';
|
|
15
|
+
* import '@webmcpui/tokens/css';
|
|
16
|
+
*
|
|
17
|
+
* <Button variant="primary" onClick={save}>Save</Button>
|
|
18
|
+
* <Button expose toolName="book_appointment">Book</Button>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const Button: _lit_react.ReactWebComponent<WmcpButton, {
|
|
22
|
+
onClick: string;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `<Input>` — a typed React wrapper over `<wmcp-input>`. Form association,
|
|
27
|
+
* Standard Schema validation, and WebMCP `fill_*` exposure live in core; this
|
|
28
|
+
* surfaces the element's props (`value`, `type`, `label`, `required`, `schema`,
|
|
29
|
+
* `expose`, …) plus `onInput` / `onChange`. Control it with `value` + `onInput`.
|
|
30
|
+
*/
|
|
31
|
+
declare const Input: _lit_react.ReactWebComponent<WmcpInput, {
|
|
32
|
+
onInput: string;
|
|
33
|
+
onChange: string;
|
|
34
|
+
}>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `<Dialog>` — a typed React wrapper over `<wmcp-dialog>`. The modal behavior
|
|
38
|
+
* (native `<dialog>`, focus trap, WebMCP `open_*` exposure) lives in core.
|
|
39
|
+
* Drive it with the `open` prop or a `ref` (`ref.current.show()` / `.close()`);
|
|
40
|
+
* `onOpen` / `onClose` fire on state changes.
|
|
41
|
+
*/
|
|
42
|
+
declare const Dialog: _lit_react.ReactWebComponent<WmcpDialog, {
|
|
43
|
+
onOpen: string;
|
|
44
|
+
onClose: string;
|
|
45
|
+
}>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `<Tabs>` — a typed React wrapper over `<wmcp-tabs>`. Holds the persistent
|
|
49
|
+
* `active` tab and exposes the WebMCP `switch_*` tool (in core). Pass the
|
|
50
|
+
* panels as children (`<section tab="…" tab-label="…">`); read/track the active
|
|
51
|
+
* tab via the `active` prop and `onChange`.
|
|
52
|
+
*/
|
|
53
|
+
declare const Tabs: _lit_react.ReactWebComponent<WmcpTabs, {
|
|
54
|
+
onChange: string;
|
|
55
|
+
}>;
|
|
56
|
+
|
|
57
|
+
/** `<Switch>` — a typed React wrapper over `<wmcp-switch>` (boolean form
|
|
58
|
+
* control, WebMCP `fill_*` exposure in core). Control with `checked` + `onChange`. */
|
|
59
|
+
declare const Switch: _lit_react.ReactWebComponent<WmcpSwitch, {
|
|
60
|
+
onInput: string;
|
|
61
|
+
onChange: string;
|
|
62
|
+
}>;
|
|
63
|
+
|
|
64
|
+
/** `<Badge>` — a presentational status pill (`variant` + children). No WebMCP tool. */
|
|
65
|
+
declare const Badge: _lit_react.ReactWebComponent<WmcpBadge, {}>;
|
|
66
|
+
|
|
67
|
+
/** `<Separator>` — a presentational divider (`orientation`). No WebMCP tool. */
|
|
68
|
+
declare const Separator: _lit_react.ReactWebComponent<WmcpSeparator, {}>;
|
|
69
|
+
|
|
70
|
+
/** `<Tooltip>` — a typed React wrapper over `<wmcp-Tooltip>`. */
|
|
71
|
+
declare const Tooltip: _lit_react.ReactWebComponent<WmcpTooltip, {
|
|
72
|
+
onOpen: string;
|
|
73
|
+
onClose: string;
|
|
74
|
+
}>;
|
|
75
|
+
|
|
76
|
+
/** `<Alert>` — a typed React wrapper over `<wmcp-Alert>`. */
|
|
77
|
+
declare const Alert: _lit_react.ReactWebComponent<WmcpAlert, {}>;
|
|
78
|
+
|
|
79
|
+
/** `<Progress>` — a typed React wrapper over `<wmcp-Progress>`. */
|
|
80
|
+
declare const Progress: _lit_react.ReactWebComponent<WmcpProgress, {}>;
|
|
81
|
+
|
|
82
|
+
/** `<Avatar>` — a typed React wrapper over `<wmcp-Avatar>`. */
|
|
83
|
+
declare const Avatar: _lit_react.ReactWebComponent<WmcpAvatar, {}>;
|
|
84
|
+
|
|
85
|
+
export { Alert, Avatar, Badge, Button, Dialog, Input, Progress, Separator, Switch, Tabs, Tooltip };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// src/button.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { createComponent } from "@lit/react";
|
|
4
|
+
import { WmcpButton } from "@webmcpui/core";
|
|
5
|
+
|
|
6
|
+
// src/define.ts
|
|
7
|
+
function defineOnce(tagName, elementClass) {
|
|
8
|
+
if (typeof customElements === "undefined") return;
|
|
9
|
+
if (!customElements.get(tagName)) {
|
|
10
|
+
customElements.define(tagName, elementClass);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/button.tsx
|
|
15
|
+
defineOnce(WmcpButton.tagName, WmcpButton);
|
|
16
|
+
var Button = createComponent({
|
|
17
|
+
tagName: WmcpButton.tagName,
|
|
18
|
+
elementClass: WmcpButton,
|
|
19
|
+
react: React,
|
|
20
|
+
events: {
|
|
21
|
+
onClick: "click"
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Button.displayName = "Button";
|
|
25
|
+
|
|
26
|
+
// src/input.tsx
|
|
27
|
+
import * as React2 from "react";
|
|
28
|
+
import { createComponent as createComponent2 } from "@lit/react";
|
|
29
|
+
import { WmcpInput } from "@webmcpui/core";
|
|
30
|
+
defineOnce(WmcpInput.tagName, WmcpInput);
|
|
31
|
+
var Input = createComponent2({
|
|
32
|
+
tagName: WmcpInput.tagName,
|
|
33
|
+
elementClass: WmcpInput,
|
|
34
|
+
react: React2,
|
|
35
|
+
events: {
|
|
36
|
+
onInput: "input",
|
|
37
|
+
onChange: "change"
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
Input.displayName = "Input";
|
|
41
|
+
|
|
42
|
+
// src/dialog.tsx
|
|
43
|
+
import * as React3 from "react";
|
|
44
|
+
import { createComponent as createComponent3 } from "@lit/react";
|
|
45
|
+
import { WmcpDialog } from "@webmcpui/core";
|
|
46
|
+
defineOnce(WmcpDialog.tagName, WmcpDialog);
|
|
47
|
+
var Dialog = createComponent3({
|
|
48
|
+
tagName: WmcpDialog.tagName,
|
|
49
|
+
elementClass: WmcpDialog,
|
|
50
|
+
react: React3,
|
|
51
|
+
events: {
|
|
52
|
+
onOpen: "open",
|
|
53
|
+
onClose: "close"
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
Dialog.displayName = "Dialog";
|
|
57
|
+
|
|
58
|
+
// src/tabs.tsx
|
|
59
|
+
import * as React4 from "react";
|
|
60
|
+
import { createComponent as createComponent4 } from "@lit/react";
|
|
61
|
+
import { WmcpTabs } from "@webmcpui/core";
|
|
62
|
+
defineOnce(WmcpTabs.tagName, WmcpTabs);
|
|
63
|
+
var Tabs = createComponent4({
|
|
64
|
+
tagName: WmcpTabs.tagName,
|
|
65
|
+
elementClass: WmcpTabs,
|
|
66
|
+
react: React4,
|
|
67
|
+
events: {
|
|
68
|
+
onChange: "change"
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
Tabs.displayName = "Tabs";
|
|
72
|
+
|
|
73
|
+
// src/switch.tsx
|
|
74
|
+
import * as React5 from "react";
|
|
75
|
+
import { createComponent as createComponent5 } from "@lit/react";
|
|
76
|
+
import { WmcpSwitch } from "@webmcpui/core";
|
|
77
|
+
defineOnce(WmcpSwitch.tagName, WmcpSwitch);
|
|
78
|
+
var Switch = createComponent5({
|
|
79
|
+
tagName: WmcpSwitch.tagName,
|
|
80
|
+
elementClass: WmcpSwitch,
|
|
81
|
+
react: React5,
|
|
82
|
+
events: { onInput: "input", onChange: "change" }
|
|
83
|
+
});
|
|
84
|
+
Switch.displayName = "Switch";
|
|
85
|
+
|
|
86
|
+
// src/badge.tsx
|
|
87
|
+
import * as React6 from "react";
|
|
88
|
+
import { createComponent as createComponent6 } from "@lit/react";
|
|
89
|
+
import { WmcpBadge } from "@webmcpui/core";
|
|
90
|
+
defineOnce(WmcpBadge.tagName, WmcpBadge);
|
|
91
|
+
var Badge = createComponent6({
|
|
92
|
+
tagName: WmcpBadge.tagName,
|
|
93
|
+
elementClass: WmcpBadge,
|
|
94
|
+
react: React6
|
|
95
|
+
});
|
|
96
|
+
Badge.displayName = "Badge";
|
|
97
|
+
|
|
98
|
+
// src/separator.tsx
|
|
99
|
+
import * as React7 from "react";
|
|
100
|
+
import { createComponent as createComponent7 } from "@lit/react";
|
|
101
|
+
import { WmcpSeparator } from "@webmcpui/core";
|
|
102
|
+
defineOnce(WmcpSeparator.tagName, WmcpSeparator);
|
|
103
|
+
var Separator = createComponent7({
|
|
104
|
+
tagName: WmcpSeparator.tagName,
|
|
105
|
+
elementClass: WmcpSeparator,
|
|
106
|
+
react: React7
|
|
107
|
+
});
|
|
108
|
+
Separator.displayName = "Separator";
|
|
109
|
+
|
|
110
|
+
// src/tooltip.tsx
|
|
111
|
+
import * as React8 from "react";
|
|
112
|
+
import { createComponent as createComponent8 } from "@lit/react";
|
|
113
|
+
import { WmcpTooltip } from "@webmcpui/core";
|
|
114
|
+
defineOnce(WmcpTooltip.tagName, WmcpTooltip);
|
|
115
|
+
var Tooltip = createComponent8({ tagName: WmcpTooltip.tagName, elementClass: WmcpTooltip, react: React8, events: { onOpen: "open", onClose: "close" } });
|
|
116
|
+
Tooltip.displayName = "Tooltip";
|
|
117
|
+
|
|
118
|
+
// src/alert.tsx
|
|
119
|
+
import * as React9 from "react";
|
|
120
|
+
import { createComponent as createComponent9 } from "@lit/react";
|
|
121
|
+
import { WmcpAlert } from "@webmcpui/core";
|
|
122
|
+
defineOnce(WmcpAlert.tagName, WmcpAlert);
|
|
123
|
+
var Alert = createComponent9({ tagName: WmcpAlert.tagName, elementClass: WmcpAlert, react: React9 });
|
|
124
|
+
Alert.displayName = "Alert";
|
|
125
|
+
|
|
126
|
+
// src/progress.tsx
|
|
127
|
+
import * as React10 from "react";
|
|
128
|
+
import { createComponent as createComponent10 } from "@lit/react";
|
|
129
|
+
import { WmcpProgress } from "@webmcpui/core";
|
|
130
|
+
defineOnce(WmcpProgress.tagName, WmcpProgress);
|
|
131
|
+
var Progress = createComponent10({ tagName: WmcpProgress.tagName, elementClass: WmcpProgress, react: React10 });
|
|
132
|
+
Progress.displayName = "Progress";
|
|
133
|
+
|
|
134
|
+
// src/avatar.tsx
|
|
135
|
+
import * as React11 from "react";
|
|
136
|
+
import { createComponent as createComponent11 } from "@lit/react";
|
|
137
|
+
import { WmcpAvatar } from "@webmcpui/core";
|
|
138
|
+
defineOnce(WmcpAvatar.tagName, WmcpAvatar);
|
|
139
|
+
var Avatar = createComponent11({ tagName: WmcpAvatar.tagName, elementClass: WmcpAvatar, react: React11 });
|
|
140
|
+
Avatar.displayName = "Avatar";
|
|
141
|
+
export {
|
|
142
|
+
Alert,
|
|
143
|
+
Avatar,
|
|
144
|
+
Badge,
|
|
145
|
+
Button,
|
|
146
|
+
Dialog,
|
|
147
|
+
Input,
|
|
148
|
+
Progress,
|
|
149
|
+
Separator,
|
|
150
|
+
Switch,
|
|
151
|
+
Tabs,
|
|
152
|
+
Tooltip
|
|
153
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webmcpui/react",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Idiomatic, typed React components for webmcpui — WebMCP-native, accessible, shadcn/Tailwind-aligned. Wraps @webmcpui/core.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Gary Pfaff (Pfaff Digital)",
|
|
7
|
+
"homepage": "https://webmcpui.com",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/webmcpui/webmcpui.git",
|
|
11
|
+
"directory": "packages/react"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/webmcpui/webmcpui/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"webmcp",
|
|
18
|
+
"react",
|
|
19
|
+
"ai-agents",
|
|
20
|
+
"components",
|
|
21
|
+
"shadcn",
|
|
22
|
+
"web-components"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"clean": "rm -rf dist"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@lit/react": "^1.0.7"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@webmcpui/core": ">=0.3.0",
|
|
47
|
+
"react": ">=18",
|
|
48
|
+
"react-dom": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^19.0.0",
|
|
52
|
+
"@types/react-dom": "^19.0.0",
|
|
53
|
+
"@webmcpui/core": "workspace:*",
|
|
54
|
+
"react": "^19.0.0",
|
|
55
|
+
"react-dom": "^19.0.0",
|
|
56
|
+
"tsup": "^8.3.5",
|
|
57
|
+
"typescript": "^5.7.2"
|
|
58
|
+
}
|
|
59
|
+
}
|