@webmcpui/core 0.2.0 → 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 +46 -24
- package/dist/index.d.ts +160 -2
- package/dist/index.js +522 -1
- package/dist/webmcpui.global.js +279 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
# @webmcpui/core
|
|
2
2
|
|
|
3
|
-
Framework-agnostic, WebMCP-native custom elements.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
subclass that supplies its control and specifics.
|
|
3
|
+
Framework-agnostic, WebMCP-native custom elements. Every `<wmcp-*>` element is a
|
|
4
|
+
proper, accessible HTML control first and, when you opt in, also registers an
|
|
5
|
+
imperative [WebMCP](https://webmcpui.com/docs/webmcp) tool an agent can call.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
**Two families of primitives:**
|
|
8
|
+
|
|
9
|
+
- **Form controls** expose a _value_ an agent can set — `<wmcp-input>`,
|
|
10
|
+
`<wmcp-textarea>`, `<wmcp-select>`, `<wmcp-checkbox>`, `<wmcp-radio>` /
|
|
11
|
+
`<wmcp-radio-group>`. Shared behavior (form association via `ElementInternals`,
|
|
12
|
+
Standard Schema validation, a11y, theming) lives in a `WmcpFormControl` base.
|
|
13
|
+
- **Interaction primitives** expose an _action_ an agent can trigger —
|
|
14
|
+
`<wmcp-button>`, `<wmcp-dialog>`, `<wmcp-menu>`, `<wmcp-tabs>`,
|
|
15
|
+
`<wmcp-popover>` — or, for `<wmcp-toast>`, a _reading_ an agent can perceive.
|
|
16
|
+
They share a `WmcpAction` / `WmcpExposable` base.
|
|
9
17
|
|
|
10
18
|
One source of truth (vanilla custom elements built with [Lit](https://lit.dev)),
|
|
11
19
|
two distribution channels: an ESM package for build tools, and a single-file
|
|
@@ -21,11 +29,12 @@ pnpm add @webmcpui/core @webmcpui/tokens
|
|
|
21
29
|
import { defineComponents } from '@webmcpui/core';
|
|
22
30
|
import '@webmcpui/tokens/css'; // the theme tokens (CSS custom properties)
|
|
23
31
|
|
|
24
|
-
defineComponents(); // registers
|
|
32
|
+
defineComponents(); // registers every <wmcp-*> element
|
|
25
33
|
```
|
|
26
34
|
|
|
27
35
|
```html
|
|
28
36
|
<wmcp-input label="Email" name="email" type="email"></wmcp-input>
|
|
37
|
+
<wmcp-button variant="primary">Save</wmcp-button>
|
|
29
38
|
```
|
|
30
39
|
|
|
31
40
|
Importing the package does **not** register elements — you call
|
|
@@ -45,7 +54,7 @@ For Webflow / WordPress / hand-written HTML — one tag, elements auto-register:
|
|
|
45
54
|
|
|
46
55
|
See `examples/plain-html.html` for a working local version.
|
|
47
56
|
|
|
48
|
-
## Standard Schema validation
|
|
57
|
+
## Standard Schema validation (form controls)
|
|
49
58
|
|
|
50
59
|
Bring any [Standard Schema](https://standardschema.dev) validator — Zod,
|
|
51
60
|
Valibot, ArkType — set it as the `schema` property. No bespoke schema language.
|
|
@@ -59,51 +68,64 @@ input.schema = z.string().email('Enter a valid email');
|
|
|
59
68
|
|
|
60
69
|
Validation runs on input and during native form validation; failures set
|
|
61
70
|
`aria-invalid`, render an error message in a live region, and propagate to the
|
|
62
|
-
containing `<form>` via ElementInternals
|
|
63
|
-
|
|
64
|
-
> **Note:** Standard Schema validates values but does not emit JSON Schema, so
|
|
65
|
-
> the WebMCP tool's parameter schema is derived from the input `type`, not from
|
|
66
|
-
> the validator. Richer tool schemas are a future enhancement.
|
|
71
|
+
containing `<form>` via `ElementInternals`.
|
|
67
72
|
|
|
68
73
|
## WebMCP exposure
|
|
69
74
|
|
|
70
|
-
Opt in with `expose`. The element registers an imperative WebMCP tool
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
first.
|
|
75
|
+
Opt in with `expose`. The element registers an imperative WebMCP tool on connect
|
|
76
|
+
and unregisters on disconnect. It is feature-detected — preferring
|
|
77
|
+
`document.modelContext` (canonical as of the Chrome 149+ origin trial) and
|
|
78
|
+
falling back to the deprecated `navigator.modelContext` — and a complete no-op
|
|
79
|
+
when no host is present, so the element is always a good control first.
|
|
75
80
|
|
|
76
81
|
```html
|
|
82
|
+
<!-- form control → a "fill" tool that sets a value -->
|
|
77
83
|
<wmcp-input label="Email" name="email" expose></wmcp-input>
|
|
78
|
-
|
|
84
|
+
|
|
85
|
+
<!-- interaction primitive → an "action" tool the agent can trigger -->
|
|
86
|
+
<wmcp-button tool-name="book_appointment" expose>Book</wmcp-button>
|
|
87
|
+
|
|
88
|
+
<!-- a menu → a parameterized action (the agent picks which item) -->
|
|
89
|
+
<wmcp-menu name="row_action" label="Actions" expose>
|
|
90
|
+
<option value="edit">Edit</option>
|
|
91
|
+
<option value="delete">Delete</option>
|
|
92
|
+
</wmcp-menu>
|
|
79
93
|
```
|
|
80
94
|
|
|
95
|
+
Consequential steps stay a deliberate human action: an agent can _set_ a value
|
|
96
|
+
or _open_ a dialog, but submitting/confirming is the person's to make.
|
|
97
|
+
|
|
81
98
|
## Testing without a real agent
|
|
82
99
|
|
|
83
|
-
No mainstream agent calls WebMCP yet, so `@webmcpui/core/testing` ships a
|
|
84
|
-
host to exercise exposure end to end
|
|
100
|
+
No mainstream agent calls WebMCP broadly yet, so `@webmcpui/core/testing` ships a
|
|
101
|
+
fake host to exercise exposure end to end:
|
|
85
102
|
|
|
86
103
|
```ts
|
|
87
104
|
import { installFakeAgent } from '@webmcpui/core/testing';
|
|
88
105
|
|
|
89
106
|
const agent = installFakeAgent();
|
|
90
|
-
// ... connect a <wmcp-input expose> ...
|
|
107
|
+
// ... connect a <wmcp-input expose> / <wmcp-button expose> ...
|
|
91
108
|
await agent.call('fill_email', { value: 'agent@webmcpui.com' });
|
|
109
|
+
await agent.call('click_button');
|
|
92
110
|
agent.restore();
|
|
93
111
|
```
|
|
94
112
|
|
|
113
|
+
## Documentation
|
|
114
|
+
|
|
115
|
+
Full docs, live demos for every element, and `llms.txt` at
|
|
116
|
+
**[webmcpui.com](https://webmcpui.com)**.
|
|
117
|
+
|
|
95
118
|
## Build & test
|
|
96
119
|
|
|
97
120
|
```bash
|
|
98
121
|
pnpm build # tsup → dist/ (ESM + IIFE + d.ts)
|
|
99
122
|
pnpm typecheck # tsc --noEmit
|
|
100
|
-
pnpm test # @web/test-runner in real Chromium
|
|
101
|
-
# validation a11y, WebMCP exposure)
|
|
123
|
+
pnpm test # @web/test-runner in real Chromium
|
|
102
124
|
pnpm test:smoke # node smoke check against the built dist
|
|
103
125
|
```
|
|
104
126
|
|
|
105
127
|
Tests run in a genuine browser via the Playwright launcher — form-associated
|
|
106
|
-
custom elements and ElementInternals don't work under jsdom. First run needs
|
|
128
|
+
custom elements and `ElementInternals` don't work under jsdom. First run needs
|
|
107
129
|
the browser binary:
|
|
108
130
|
|
|
109
131
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -693,7 +693,7 @@ type WmcpPopoverTrigger = 'click' | 'hover';
|
|
|
693
693
|
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
694
694
|
*/
|
|
695
695
|
declare class WmcpPopover extends WmcpAction {
|
|
696
|
-
static readonly tagName
|
|
696
|
+
static readonly tagName: string;
|
|
697
697
|
static styles: CSSResultGroup;
|
|
698
698
|
/** Whether the panel is open (reflected). */
|
|
699
699
|
open: boolean;
|
|
@@ -786,13 +786,164 @@ declare class WmcpToast extends WmcpExposable {
|
|
|
786
786
|
render(): TemplateResult;
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
+
/**
|
|
790
|
+
* `<wmcp-switch>` — a form-associated, agent-operable toggle.
|
|
791
|
+
*
|
|
792
|
+
* A boolean control like `<wmcp-checkbox>`, but presented as a switch
|
|
793
|
+
* (`role="switch"`) — on/off rather than checked/unchecked. Its state is the
|
|
794
|
+
* boolean `checked`; `value` is the string submitted to the form *when on*.
|
|
795
|
+
* (checkbox and switch are two boolean controls now — a shared
|
|
796
|
+
* `WmcpBooleanControl` base is a future extraction.)
|
|
797
|
+
*
|
|
798
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
799
|
+
*/
|
|
800
|
+
declare class WmcpSwitch extends WmcpFormControl {
|
|
801
|
+
static readonly tagName = "wmcp-switch";
|
|
802
|
+
static styles: CSSResultGroup;
|
|
803
|
+
/** Whether the switch is on. */
|
|
804
|
+
checked: boolean;
|
|
805
|
+
private defaultChecked;
|
|
806
|
+
constructor();
|
|
807
|
+
protected get controlNoun(): string;
|
|
808
|
+
connectedCallback(): void;
|
|
809
|
+
protected getFormValue(): string | File | FormData | null;
|
|
810
|
+
protected get validationValue(): unknown;
|
|
811
|
+
protected get isEmpty(): boolean;
|
|
812
|
+
protected get requiredMessageDefault(): string;
|
|
813
|
+
protected toolInputSchema(): JSONSchema;
|
|
814
|
+
protected applyAgentValue(args: Record<string, unknown>): Promise<void>;
|
|
815
|
+
protected stateDescription(): string;
|
|
816
|
+
formResetCallback(): void;
|
|
817
|
+
private onToggle;
|
|
818
|
+
protected renderControl(): TemplateResult;
|
|
819
|
+
render(): TemplateResult;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/** Visual variants `<wmcp-badge>` supports (shadcn-aligned). */
|
|
823
|
+
type WmcpBadgeVariant = 'primary' | 'secondary' | 'destructive' | 'outline';
|
|
824
|
+
/**
|
|
825
|
+
* `<wmcp-badge>` — a small status/label pill. Purely presentational: it exposes
|
|
826
|
+
* no WebMCP tool (an agent reads its text from the accessibility tree), so it
|
|
827
|
+
* extends `LitElement` directly rather than an exposure base.
|
|
828
|
+
*
|
|
829
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
830
|
+
*/
|
|
831
|
+
declare class WmcpBadge extends LitElement {
|
|
832
|
+
static readonly tagName = "wmcp-badge";
|
|
833
|
+
static styles: CSSResultGroup;
|
|
834
|
+
/** Visual variant. */
|
|
835
|
+
variant: WmcpBadgeVariant;
|
|
836
|
+
render(): TemplateResult;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* `<wmcp-separator>` — a thin rule dividing content. Presentational; exposes no
|
|
841
|
+
* WebMCP tool. `role="separator"` (decorative unless it separates focusable
|
|
842
|
+
* groups). Set `orientation="vertical"` for a vertical divider.
|
|
843
|
+
*
|
|
844
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
845
|
+
*/
|
|
846
|
+
declare class WmcpSeparator extends LitElement {
|
|
847
|
+
static readonly tagName = "wmcp-separator";
|
|
848
|
+
static styles: CSSResultGroup;
|
|
849
|
+
/** Divider direction. */
|
|
850
|
+
orientation: 'horizontal' | 'vertical';
|
|
851
|
+
connectedCallback(): void;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* `<wmcp-tooltip>` — a hover/focus tooltip. A thin preset of
|
|
856
|
+
* {@link WmcpPopover}: the same anchored-panel machinery, defaulted to
|
|
857
|
+
* `trigger="hover"` (so it gets `role="tooltip"` + `aria-describedby` and opens
|
|
858
|
+
* on hover/focus). Put the trigger in the `trigger` slot and the text in the
|
|
859
|
+
* default slot.
|
|
860
|
+
*
|
|
861
|
+
* ```html
|
|
862
|
+
* <wmcp-tooltip>
|
|
863
|
+
* <button slot="trigger" aria-label="Copy">⧉</button>
|
|
864
|
+
* Copy to clipboard
|
|
865
|
+
* </wmcp-tooltip>
|
|
866
|
+
* ```
|
|
867
|
+
*
|
|
868
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
869
|
+
*/
|
|
870
|
+
declare class WmcpTooltip extends WmcpPopover {
|
|
871
|
+
static readonly tagName = "wmcp-tooltip";
|
|
872
|
+
constructor();
|
|
873
|
+
protected get defaultNameSuffix(): string;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/** Severity variants `<wmcp-alert>` supports. */
|
|
877
|
+
type WmcpAlertVariant = 'info' | 'success' | 'warning' | 'error';
|
|
878
|
+
/**
|
|
879
|
+
* `<wmcp-alert>` — an inline callout for a persistent message. Presentational
|
|
880
|
+
* (no WebMCP tool; an agent reads it from the a11y tree). Gets `role="alert"`
|
|
881
|
+
* for `error`/`warning`, `role="status"` otherwise. Optional `title`; the
|
|
882
|
+
* message is the default slot.
|
|
883
|
+
*
|
|
884
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
885
|
+
*/
|
|
886
|
+
declare class WmcpAlert extends LitElement {
|
|
887
|
+
static readonly tagName = "wmcp-alert";
|
|
888
|
+
static styles: CSSResultGroup;
|
|
889
|
+
/** Severity. */
|
|
890
|
+
variant: WmcpAlertVariant;
|
|
891
|
+
/** Optional bold heading above the message. */
|
|
892
|
+
title: string;
|
|
893
|
+
connectedCallback(): void;
|
|
894
|
+
render(): TemplateResult;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* `<wmcp-progress>` — a determinate or indeterminate progress bar.
|
|
899
|
+
* Presentational (no WebMCP tool). `role="progressbar"` with `aria-valuenow` /
|
|
900
|
+
* `aria-valuemax` wired from `value` / `max`; omit `value` (or set
|
|
901
|
+
* `indeterminate`) for an animated indeterminate bar.
|
|
902
|
+
*
|
|
903
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
904
|
+
*/
|
|
905
|
+
declare class WmcpProgress extends LitElement {
|
|
906
|
+
static readonly tagName = "wmcp-progress";
|
|
907
|
+
static styles: CSSResultGroup;
|
|
908
|
+
/** Current value; leave unset for indeterminate. */
|
|
909
|
+
value?: number;
|
|
910
|
+
/** Maximum value. */
|
|
911
|
+
max: number;
|
|
912
|
+
/** Force the indeterminate (animated) state. */
|
|
913
|
+
indeterminate: boolean;
|
|
914
|
+
private get isIndeterminate();
|
|
915
|
+
updated(): void;
|
|
916
|
+
render(): TemplateResult;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* `<wmcp-avatar>` — a user/entity avatar. Presentational (no WebMCP tool).
|
|
921
|
+
* Shows the `src` image; if it's missing or fails to load, falls back to the
|
|
922
|
+
* `fallback` text (e.g. initials). `alt` provides the accessible name.
|
|
923
|
+
*
|
|
924
|
+
* Not auto-registered — call `defineComponents()` (or load the CDN bundle).
|
|
925
|
+
*/
|
|
926
|
+
declare class WmcpAvatar extends LitElement {
|
|
927
|
+
static readonly tagName = "wmcp-avatar";
|
|
928
|
+
static styles: CSSResultGroup;
|
|
929
|
+
/** Image URL. */
|
|
930
|
+
src: string;
|
|
931
|
+
/** Accessible name for the image. */
|
|
932
|
+
alt: string;
|
|
933
|
+
/** Text shown when there's no image (e.g. initials). */
|
|
934
|
+
fallback: string;
|
|
935
|
+
private failed;
|
|
936
|
+
willUpdate(changed: Map<string, unknown>): void;
|
|
937
|
+
render(): TemplateResult;
|
|
938
|
+
}
|
|
939
|
+
|
|
789
940
|
/**
|
|
790
941
|
* Register all webmcpui custom elements. Idempotent — safe to call more than
|
|
791
942
|
* once and safe alongside the CDN bundle (already-defined tags are skipped).
|
|
792
943
|
*/
|
|
793
944
|
declare function defineComponents(): void;
|
|
794
945
|
|
|
795
|
-
export { JSONSchema, StandardSchemaV1, type ValidationOutcome, WebMCPToolResult, WmcpAction, WmcpButton, type WmcpButtonSize, type WmcpButtonType, type WmcpButtonVariant, WmcpCheckbox, WmcpDialog, WmcpExposable, WmcpFormControl, WmcpInput, type WmcpInputType, WmcpMenu, type WmcpMenuItem, WmcpPopover, type WmcpPopoverPlacement, type WmcpPopoverTrigger, WmcpRadio, WmcpRadioGroup, type WmcpRadioOption, WmcpSelect, type WmcpSelectItem, type WmcpSelectOption, type WmcpSelectOptionGroup, type WmcpTabInfo, WmcpTabs, WmcpTextarea, WmcpToast, type WmcpToastOptions, type WmcpToastVariant, defineComponents, isStandardSchema, textFieldStyles, validateStandard };
|
|
946
|
+
export { JSONSchema, StandardSchemaV1, type ValidationOutcome, WebMCPToolResult, WmcpAction, WmcpAlert, type WmcpAlertVariant, WmcpAvatar, WmcpBadge, type WmcpBadgeVariant, WmcpButton, type WmcpButtonSize, type WmcpButtonType, type WmcpButtonVariant, WmcpCheckbox, WmcpDialog, WmcpExposable, WmcpFormControl, WmcpInput, type WmcpInputType, WmcpMenu, type WmcpMenuItem, WmcpPopover, type WmcpPopoverPlacement, type WmcpPopoverTrigger, WmcpProgress, WmcpRadio, WmcpRadioGroup, type WmcpRadioOption, WmcpSelect, type WmcpSelectItem, type WmcpSelectOption, type WmcpSelectOptionGroup, WmcpSeparator, WmcpSwitch, type WmcpTabInfo, WmcpTabs, WmcpTextarea, WmcpToast, type WmcpToastOptions, type WmcpToastVariant, WmcpTooltip, defineComponents, isStandardSchema, textFieldStyles, validateStandard };
|
|
796
947
|
|
|
797
948
|
declare global {
|
|
798
949
|
interface HTMLElementTagNameMap {
|
|
@@ -808,5 +959,12 @@ declare global {
|
|
|
808
959
|
'wmcp-tabs': import('./index.js').WmcpTabs;
|
|
809
960
|
'wmcp-popover': import('./index.js').WmcpPopover;
|
|
810
961
|
'wmcp-toast': import('./index.js').WmcpToast;
|
|
962
|
+
'wmcp-switch': import('./index.js').WmcpSwitch;
|
|
963
|
+
'wmcp-badge': import('./index.js').WmcpBadge;
|
|
964
|
+
'wmcp-separator': import('./index.js').WmcpSeparator;
|
|
965
|
+
'wmcp-tooltip': import('./index.js').WmcpTooltip;
|
|
966
|
+
'wmcp-alert': import('./index.js').WmcpAlert;
|
|
967
|
+
'wmcp-progress': import('./index.js').WmcpProgress;
|
|
968
|
+
'wmcp-avatar': import('./index.js').WmcpAvatar;
|
|
811
969
|
}
|
|
812
970
|
}
|