@rainbow-robotics/plugin-ui 0.1.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.
Files changed (42) hide show
  1. package/README.md +85 -0
  2. package/build-browser.mjs +84 -0
  3. package/build-dist.mjs +42 -0
  4. package/dist/connect.d.ts +12 -0
  5. package/dist/connect.d.ts.map +1 -0
  6. package/dist/connect.js +29 -0
  7. package/dist/connect.js.map +7 -0
  8. package/dist/elements.d.ts +195 -0
  9. package/dist/elements.d.ts.map +1 -0
  10. package/dist/elements.js +115 -0
  11. package/dist/elements.js.map +7 -0
  12. package/dist/manifest.d.ts +65 -0
  13. package/dist/manifest.d.ts.map +1 -0
  14. package/dist/manifest.js +29 -0
  15. package/dist/manifest.js.map +7 -0
  16. package/dist/react.d.ts +47 -0
  17. package/dist/react.d.ts.map +1 -0
  18. package/dist/react.js +57 -0
  19. package/dist/react.js.map +7 -0
  20. package/dist/sdk.d.ts +14 -0
  21. package/dist/sdk.d.ts.map +1 -0
  22. package/dist/sdk.js +23 -0
  23. package/dist/sdk.js.map +7 -0
  24. package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-AMCIKVG7.js +1 -0
  25. package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-GJWPOWHG.js +1 -0
  26. package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-JRCDA3EG.js +1 -0
  27. package/dist-browser/@rainbow-robotics/plugin-ui/connect.js +1 -0
  28. package/dist-browser/@rainbow-robotics/plugin-ui/elements.js +1 -0
  29. package/dist-browser/@rainbow-robotics/plugin-ui/react.js +1 -0
  30. package/dist-browser/@rainbow-robotics/plugin-ui/sdk.js +1 -0
  31. package/dist-browser/vendor/react-dom-client.js +1 -0
  32. package/dist-browser/vendor/react-jsx-dev-runtime.js +1 -0
  33. package/dist-browser/vendor/react-jsx-runtime.js +1 -0
  34. package/dist-browser/vendor/react-runtime.js +65 -0
  35. package/dist-browser/vendor/react.js +1 -0
  36. package/package.json +73 -0
  37. package/src/connect.ts +68 -0
  38. package/src/elements.ts +257 -0
  39. package/src/host.tsx +343 -0
  40. package/src/manifest.ts +92 -0
  41. package/src/react.tsx +131 -0
  42. package/src/sdk.ts +41 -0
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # @rainbow-robotics/plugin-ui
2
+
3
+ Muscat plugin UI **contract** + sandbox/host bindings.
4
+
5
+ External plugin source imports this package as `@rainbow-robotics/plugin-ui/*`, but
6
+ `muscat-pk build` keeps it **external**. A plugin ZIP must not contain this
7
+ runtime. Muscat/robot and preview-host provide their own matching
8
+ `@rainbow-robotics/plugin-ui` browser runtime and render the real rb-components on the
9
+ host side.
10
+
11
+ ## Architecture
12
+
13
+ ```
14
+ sandbox (untrusted plugin) host (nexus / Muscat)
15
+ ───────────────────────── ─────────────────────
16
+ import { Slider, Button, useRb } import { PluginContent } from
17
+ from "@rainbow-robotics/plugin-ui/react" "@rainbow-robotics/plugin-ui/host"
18
+
19
+ <Slider/> → <rb-slider> ──mutations──▶ RemoteReceiver → RB_COMPONENT_MAP
20
+ → real RBSlider (rb-components)
21
+ rb.action(id, payload) ──thread call──▶ host RbSdk.action → POST /plugin/:id/action
22
+ host event (onChange…) ──thread call──▶ author onChange (RemoteEvent.detail)
23
+ ```
24
+
25
+ - **Isolation**: the plugin runs in an `allow-scripts` iframe (opaque origin).
26
+ - **Transport**: `@quilted/threads` (`ThreadWindow`). The **sandbox initiates**
27
+ the handshake by calling the host's exported `connect()` — threads does not
28
+ buffer a call made before the other side is listening, and the host has been
29
+ listening since it mounted the iframe.
30
+ - **Rendering**: `@remote-dom/core` + `@remote-dom/react`. The sandbox streams
31
+ DOM mutations via `RemoteMutationObserver`; the host mirrors them with
32
+ `RemoteReceiver` + `RemoteRootRenderer`.
33
+
34
+ ## Entry points
35
+
36
+ | Export | Used by | Notes |
37
+ |---|---|---|
38
+ | `./react` | plugin (sandbox) | author bindings: `Slider`, `Button`, `IconButton`, `Text`, `TextInput`, `Switch`, `Select`, `useRb` |
39
+ | `./connect` | plugin (sandbox) | `connect(App)` bootstrap, called from `sandbox.html` |
40
+ | `./sdk` | plugin (sandbox) | `useRb()`, `RbSdk` types |
41
+ | `./elements` | both | rb-\* element contract |
42
+ | `./host` | nexus only | `PluginContent`, `RB_COMPONENT_MAP` (maps rb-\* → real rb-components) |
43
+ | `./manifest` | nexus + rby2 | manifest schema (single source of truth) |
44
+
45
+ The plugin's production bundle must only import `./react` (+ `./connect`,
46
+ `./sdk`); `./host` pulls in rb-components and is host-only.
47
+
48
+ ## rb-\* contract → rb-components mapping
49
+
50
+ | element | host component | event prop |
51
+ |---|---|---|
52
+ | `rb-slider` | `RBSlider` | `onChange` (number) |
53
+ | `rb-button` | `RBLabelButton` | `onPress` |
54
+ | `rb-icon-button` | `RBIconButton` (icon from `RBIcons`) | `onPress` |
55
+ | `rb-text` | plain text | — |
56
+ | `rb-text-input` | `RBTextInput` | `onInput` (string) |
57
+ | `rb-switch` | `RBSwitch` | `onChange` (boolean) |
58
+ | `rb-select` | `RBSelectBox` | `onChange` (string) |
59
+
60
+ > ⚠️ Author bindings and the host **must** declare matching `eventProps`.
61
+ > `createRemoteComponent` / `createRemoteComponentRenderer` only treat a prop as
62
+ > an event listener when it is in `eventProps`; they do **not** auto-derive from
63
+ > the element's `remoteEvents`.
64
+
65
+ ## Verified versions
66
+
67
+ `@remote-dom/core@^1.11` · `@remote-dom/react@^1.2` · `@quilted/threads@^4`.
68
+ Notable corrections vs. early design notes: `RemoteMutationObserver` is from
69
+ `@remote-dom/core/elements` (not `/core`); there is no `@remote-dom/core/messaging`
70
+ — threading lives in `@quilted/threads`.
71
+
72
+ ## Demo (M1 end-to-end check)
73
+
74
+ `demo/` is a standalone vite harness (excluded from build/lint/types). It serves
75
+ a host page + sandbox page and verifies the full round-trip in a real browser:
76
+
77
+ ```bash
78
+ # from repo root
79
+ node_modules/.bin/vite --config packages/rb-plugin-kit/demo/vite.config.ts
80
+ # then, with the server on :5199:
81
+ node packages/rb-plugin-kit/demo/e2e.mjs
82
+ ```
83
+
84
+ The demo renders unstyled (no Tailwind/postcss pipeline); styling is validated
85
+ in nexus.
@@ -0,0 +1,84 @@
1
+ // Builds @rainbow-robotics/plugin-ui as browser ESM for the sandbox import map.
2
+ // Output: dist-browser/@rainbow-robotics/plugin-ui/{connect,react,sdk,elements}.js
3
+ // dist-browser/vendor/react-runtime.js
4
+ //
5
+ // Consumed by:
6
+ // - nexus (vite plugin emits dist-browser/ → dist/plugin-runtime/)
7
+ // - preview-host (serves dist-browser/ at /plugin-runtime/)
8
+ //
9
+ // Run: node libraries/plugin-ui/build-browser.mjs
10
+ import { build } from "esbuild";
11
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
12
+ import { dirname, resolve } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ const src = resolve(here, "src");
17
+ const out = resolve(here, "dist-browser");
18
+ const repoRoot = resolve(here, "../..");
19
+
20
+ const define = { "process.env.NODE_ENV": JSON.stringify("production") };
21
+ const shared = {
22
+ bundle: true,
23
+ format: "esm",
24
+ platform: "browser",
25
+ target: "es2020",
26
+ minify: true,
27
+ sourcemap: false,
28
+ define,
29
+ logLevel: "warning",
30
+ };
31
+
32
+ rmSync(out, { recursive: true, force: true });
33
+ mkdirSync(resolve(out, "@rainbow-robotics/plugin-ui"), { recursive: true });
34
+ mkdirSync(resolve(out, "vendor"), { recursive: true });
35
+
36
+ // Plugin-UI entry points (react / react-dom provided by vendor bundle below)
37
+ await build({
38
+ ...shared,
39
+ entryPoints: {
40
+ connect: resolve(src, "connect.ts"),
41
+ react: resolve(src, "react.tsx"),
42
+ sdk: resolve(src, "sdk.ts"),
43
+ elements: resolve(src, "elements.ts"),
44
+ },
45
+ outdir: resolve(out, "@rainbow-robotics/plugin-ui"),
46
+ entryNames: "[name]",
47
+ chunkNames: "chunks/[name]-[hash]",
48
+ splitting: true,
49
+ external: ["react", "react-dom/client"],
50
+ });
51
+
52
+ // Single vendor bundle: React + ReactDOM (sandbox loads this once via import map)
53
+ const reactShim = `
54
+ import React from "react";
55
+ import * as ReactClient from "react-dom/client";
56
+ import * as JsxRuntime from "react/jsx-runtime";
57
+ import * as JsxDevRuntime from "react/jsx-dev-runtime";
58
+ export default React;
59
+ export const { Children, Fragment, Profiler, StrictMode, Suspense,
60
+ cloneElement, createContext, createElement, createRef, forwardRef,
61
+ isValidElement, lazy, memo, startTransition, useCallback, useContext,
62
+ useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle,
63
+ useInsertionEffect, useLayoutEffect, useMemo, useReducer, useRef,
64
+ useState, useSyncExternalStore, useTransition, version } = React;
65
+ export const { createRoot, hydrateRoot } = ReactClient;
66
+ export const { jsx, jsxs } = JsxRuntime;
67
+ export const { jsxDEV } = JsxDevRuntime;
68
+ `;
69
+
70
+ await build({
71
+ ...shared,
72
+ stdin: { contents: reactShim, resolveDir: repoRoot, loader: "js" },
73
+ outfile: resolve(out, "vendor", "react-runtime.js"),
74
+ });
75
+
76
+ // Aliases so all standard React specifiers map to the single vendor file
77
+ for (const name of ["react", "react-jsx-runtime", "react-jsx-dev-runtime", "react-dom-client"]) {
78
+ writeFileSync(
79
+ resolve(out, "vendor", `${name}.js`),
80
+ 'export * from "./react-runtime.js"; export { default } from "./react-runtime.js";\n',
81
+ );
82
+ }
83
+
84
+ console.log("[plugin-ui] dist-browser ready →", out);
package/build-dist.mjs ADDED
@@ -0,0 +1,42 @@
1
+ // Builds @rainbow-robotics/plugin-ui for npm consumers (plugin authors).
2
+ // Output: dist/*.js (ESM, deps external) + dist/*.d.ts (via tsc)
3
+ //
4
+ // host.tsx is intentionally excluded — it depends on @repo/rb-components
5
+ // which is a Muscat-internal package. External devs never import ./host.
6
+ //
7
+ // Run: node libraries/plugin-ui/build-dist.mjs
8
+ import { build } from "esbuild";
9
+ import { execSync } from "node:child_process";
10
+ import { rmSync } from "node:fs";
11
+ import { dirname, resolve } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const here = dirname(fileURLToPath(import.meta.url));
15
+
16
+ rmSync(resolve(here, "dist"), { recursive: true, force: true });
17
+
18
+ // JS: transpile only (no bundling — consumers resolve deps themselves)
19
+ await build({
20
+ entryPoints: {
21
+ connect: resolve(here, "src/connect.ts"),
22
+ react: resolve(here, "src/react.tsx"),
23
+ sdk: resolve(here, "src/sdk.ts"),
24
+ elements: resolve(here, "src/elements.ts"),
25
+ manifest: resolve(here, "src/manifest.ts"),
26
+ },
27
+ outdir: resolve(here, "dist"),
28
+ format: "esm",
29
+ bundle: false, // each file transpiled independently, deps stay as imports
30
+ platform: "neutral",
31
+ target: "es2022",
32
+ sourcemap: true,
33
+ logLevel: "warning",
34
+ });
35
+
36
+ // Types: tsc --emitDeclarationOnly
37
+ execSync("node ../../node_modules/typescript/bin/tsc -p tsconfig.build.json --emitDeclarationOnly --noEmit false", {
38
+ cwd: here,
39
+ stdio: "inherit",
40
+ });
41
+
42
+ console.log("[plugin-ui] dist/ ready");
@@ -0,0 +1,12 @@
1
+ import { type ComponentType } from "react";
2
+ /**
3
+ * Mount a plugin. Call this once from the sandbox entry (sandbox.html), passing
4
+ * the plugin's root component.
5
+ *
6
+ * @example
7
+ * import { connect } from "@rainbow-robotics/plugin-ui/connect";
8
+ * import App from "./content";
9
+ * connect(App);
10
+ */
11
+ export declare function connect(App: ComponentType): void;
12
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAc1D;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAwBhD"}
@@ -0,0 +1,29 @@
1
+ import { RemoteMutationObserver } from "@remote-dom/core/elements";
2
+ import { ThreadWindow } from "@quilted/threads";
3
+ import { createElement } from "react";
4
+ import { createRoot } from "react-dom/client";
5
+ import { defineElements } from "./elements";
6
+ import { RbContext } from "./sdk";
7
+ function connect(App) {
8
+ defineElements();
9
+ const host = ThreadWindow.parent.import({
10
+ targetOrigin: "*"
11
+ });
12
+ void host.connect().then(({ connection, action, notify }) => {
13
+ const rb = {
14
+ action: (id, payload) => Promise.resolve(action(id, payload)),
15
+ notify: (message, type) => notify(message, type)
16
+ };
17
+ const root = document.createElement("remote-root");
18
+ document.body.append(root);
19
+ const observer = new RemoteMutationObserver(connection);
20
+ observer.observe(root);
21
+ createRoot(root).render(
22
+ createElement(RbContext.Provider, { value: rb }, createElement(App))
23
+ );
24
+ });
25
+ }
26
+ export {
27
+ connect
28
+ };
29
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/connect.ts"],
4
+ "sourcesContent": ["/**\n * Sandbox bootstrap \u2014 runs *inside* the plugin iframe.\n *\n * The sandbox initiates the handshake (the iframe is the side that knows when it\n * is ready): it imports the host's `connect()` and calls it. The host responds\n * with a `RemoteConnection` (its `receiver.connection`, ferried by\n * @quilted/threads) plus the host SDK. We then render the plugin's React tree\n * into a detached root and let `RemoteMutationObserver` stream every DOM\n * mutation to the host, where the real rb-components live.\n *\n * The child-initiates-handshake pattern is required because @quilted/threads\n * does not buffer a call made before the other side is listening; the host has\n * been listening since it mounted the iframe, so a call *from* the sandbox is\n * always delivered.\n *\n * Verified against @remote-dom/core@1.11.x + @quilted/threads@4.x.\n */\nimport { RemoteMutationObserver } from \"@remote-dom/core/elements\";\nimport type { RemoteConnection } from \"@remote-dom/core\";\nimport { ThreadWindow } from \"@quilted/threads\";\nimport { createElement, type ComponentType } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { defineElements } from \"./elements\";\nimport { RbContext, type RbSdk } from \"./sdk\";\n\n/** What the host exposes to the sandbox. */\ninterface HostExports {\n connect: () => Promise<{\n connection: RemoteConnection;\n action: (id: string, payload?: unknown) => Promise<unknown> | unknown;\n notify: (message: string, type?: string) => void;\n }>;\n}\n\n/**\n * Mount a plugin. Call this once from the sandbox entry (sandbox.html), passing\n * the plugin's root component.\n *\n * @example\n * import { connect } from \"@rainbow-robotics/plugin-ui/connect\";\n * import App from \"./content\";\n * connect(App);\n */\nexport function connect(App: ComponentType): void {\n defineElements();\n\n const host = ThreadWindow.parent.import<HostExports>({\n targetOrigin: \"*\",\n });\n\n void host.connect().then(({ connection, action, notify }) => {\n const rb: RbSdk = {\n action: (id, payload) => Promise.resolve(action(id, payload)),\n notify: (message, type) => notify(message, type as string | undefined),\n };\n\n const root = document.createElement(\"remote-root\");\n\n document.body.append(root);\n\n const observer = new RemoteMutationObserver(connection);\n observer.observe(root);\n\n createRoot(root).render(\n createElement(RbContext.Provider, { value: rb }, createElement(App)),\n );\n });\n}\n"],
5
+ "mappings": "AAiBA,SAAS,8BAA8B;AAEvC,SAAS,oBAAoB;AAC7B,SAAS,qBAAyC;AAClD,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,iBAA6B;AAoB/B,SAAS,QAAQ,KAA0B;AAChD,iBAAe;AAEf,QAAM,OAAO,aAAa,OAAO,OAAoB;AAAA,IACnD,cAAc;AAAA,EAChB,CAAC;AAED,OAAK,KAAK,QAAQ,EAAE,KAAK,CAAC,EAAE,YAAY,QAAQ,OAAO,MAAM;AAC3D,UAAM,KAAY;AAAA,MAChB,QAAQ,CAAC,IAAI,YAAY,QAAQ,QAAQ,OAAO,IAAI,OAAO,CAAC;AAAA,MAC5D,QAAQ,CAAC,SAAS,SAAS,OAAO,SAAS,IAA0B;AAAA,IACvE;AAEA,UAAM,OAAO,SAAS,cAAc,aAAa;AAEjD,aAAS,KAAK,OAAO,IAAI;AAEzB,UAAM,WAAW,IAAI,uBAAuB,UAAU;AACtD,aAAS,QAAQ,IAAI;AAErB,eAAW,IAAI,EAAE;AAAA,MACf,cAAc,UAAU,UAAU,EAAE,OAAO,GAAG,GAAG,cAAc,GAAG,CAAC;AAAA,IACrE;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,195 @@
1
+ /**
2
+ * rb-* remote element contract — shared by the sandbox (plugin author) and the
3
+ * nexus host. This is the *stable* surface: it must only ever grow additively
4
+ * (new elements / new optional properties), never break existing shapes.
5
+ *
6
+ * Verified against @remote-dom/core@1.11.x:
7
+ * - `RemoteElement` lives in `@remote-dom/core/elements`
8
+ * - static `remoteProperties` (data) + static `remoteEvents` (callbacks)
9
+ */
10
+ import { RemoteElement } from "@remote-dom/core/elements";
11
+ type RbNoMethods = Record<never, never>;
12
+ type RbNoSlots = Record<never, never>;
13
+ type RbNoEvents = Record<never, never>;
14
+ export interface RbSliderProps {
15
+ value?: number;
16
+ min?: number;
17
+ max?: number;
18
+ step?: number;
19
+ disabled?: boolean;
20
+ }
21
+ export interface RbButtonProps {
22
+ label?: string;
23
+ variant?: string;
24
+ size?: string;
25
+ disabled?: boolean;
26
+ }
27
+ export interface RbIconButtonProps {
28
+ icon?: string;
29
+ variant?: string;
30
+ size?: string;
31
+ disabled?: boolean;
32
+ }
33
+ export type RbTextProps = Record<never, never>;
34
+ export interface RbTextInputProps {
35
+ value?: string;
36
+ placeholder?: string;
37
+ disabled?: boolean;
38
+ }
39
+ export interface RbSwitchProps {
40
+ checked?: boolean;
41
+ disabled?: boolean;
42
+ }
43
+ /** Option shape carried by `rb-select`'s `options` property. */
44
+ export interface RbSelectOption {
45
+ value: string;
46
+ label: string;
47
+ }
48
+ export interface RbSelectProps {
49
+ value?: string;
50
+ options?: RbSelectOption[];
51
+ placeholder?: string;
52
+ disabled?: boolean;
53
+ }
54
+ export interface RbSliderEvents {
55
+ change(detail: number): void;
56
+ }
57
+ export interface RbPressEvents {
58
+ press(): void;
59
+ }
60
+ export interface RbTextInputEvents {
61
+ input(detail: string): void;
62
+ }
63
+ export interface RbSwitchEvents {
64
+ change(detail: boolean): void;
65
+ }
66
+ export interface RbSelectEvents {
67
+ change(detail: string): void;
68
+ }
69
+ /** Slider → host renders RBSlider (Radix array value, single-thumb contract). */
70
+ export declare class RbSliderElement extends RemoteElement<RbSliderProps, RbNoMethods, RbNoSlots, RbSliderEvents> {
71
+ static get remoteProperties(): {
72
+ value: {
73
+ type: NumberConstructor;
74
+ };
75
+ min: {
76
+ type: NumberConstructor;
77
+ };
78
+ max: {
79
+ type: NumberConstructor;
80
+ };
81
+ step: {
82
+ type: NumberConstructor;
83
+ };
84
+ disabled: {
85
+ type: BooleanConstructor;
86
+ };
87
+ };
88
+ static get remoteEvents(): readonly ["change"];
89
+ }
90
+ /** Button → host renders RBLabelButton. */
91
+ export declare class RbButtonElement extends RemoteElement<RbButtonProps, RbNoMethods, RbNoSlots, RbPressEvents> {
92
+ static get remoteProperties(): {
93
+ label: {
94
+ type: StringConstructor;
95
+ };
96
+ variant: {
97
+ type: StringConstructor;
98
+ };
99
+ size: {
100
+ type: StringConstructor;
101
+ };
102
+ disabled: {
103
+ type: BooleanConstructor;
104
+ };
105
+ };
106
+ static get remoteEvents(): readonly ["press"];
107
+ }
108
+ /** Icon button → host renders RBIconButton with an icon resolved from RBIcons. */
109
+ export declare class RbIconButtonElement extends RemoteElement<RbIconButtonProps, RbNoMethods, RbNoSlots, RbPressEvents> {
110
+ static get remoteProperties(): {
111
+ icon: {
112
+ type: StringConstructor;
113
+ };
114
+ variant: {
115
+ type: StringConstructor;
116
+ };
117
+ size: {
118
+ type: StringConstructor;
119
+ };
120
+ disabled: {
121
+ type: BooleanConstructor;
122
+ };
123
+ };
124
+ static get remoteEvents(): readonly ["press"];
125
+ }
126
+ /** Plain text — renders its children as text on the host. */
127
+ export declare class RbTextElement extends RemoteElement<RbTextProps, RbNoMethods, RbNoSlots, RbNoEvents> {
128
+ static get remoteProperties(): {};
129
+ }
130
+ /** Text input → host renders RBTextInput. */
131
+ export declare class RbTextInputElement extends RemoteElement<RbTextInputProps, RbNoMethods, RbNoSlots, RbTextInputEvents> {
132
+ static get remoteProperties(): {
133
+ value: {
134
+ type: StringConstructor;
135
+ };
136
+ placeholder: {
137
+ type: StringConstructor;
138
+ };
139
+ disabled: {
140
+ type: BooleanConstructor;
141
+ };
142
+ };
143
+ static get remoteEvents(): readonly ["input"];
144
+ }
145
+ /** Switch → host renders RBSwitch. */
146
+ export declare class RbSwitchElement extends RemoteElement<RbSwitchProps, RbNoMethods, RbNoSlots, RbSwitchEvents> {
147
+ static get remoteProperties(): {
148
+ checked: {
149
+ type: BooleanConstructor;
150
+ };
151
+ disabled: {
152
+ type: BooleanConstructor;
153
+ };
154
+ };
155
+ static get remoteEvents(): readonly ["change"];
156
+ }
157
+ /** Select → host renders RBSelectBox. `options` is `[{value,label}]`. */
158
+ export declare class RbSelectElement extends RemoteElement<RbSelectProps, RbNoMethods, RbNoSlots, RbSelectEvents> {
159
+ static get remoteProperties(): {
160
+ value: {
161
+ type: StringConstructor;
162
+ };
163
+ options: {
164
+ type: ArrayConstructor;
165
+ };
166
+ placeholder: {
167
+ type: StringConstructor;
168
+ };
169
+ disabled: {
170
+ type: BooleanConstructor;
171
+ };
172
+ };
173
+ static get remoteEvents(): readonly ["change"];
174
+ }
175
+ /** Custom element tag names in the contract. */
176
+ export declare const RB_ELEMENT_NAMES: readonly ["rb-slider", "rb-button", "rb-icon-button", "rb-text", "rb-text-input", "rb-switch", "rb-select"];
177
+ export type RbElementName = (typeof RB_ELEMENT_NAMES)[number];
178
+ declare global {
179
+ interface HTMLElementTagNameMap {
180
+ "rb-slider": RbSliderElement;
181
+ "rb-button": RbButtonElement;
182
+ "rb-icon-button": RbIconButtonElement;
183
+ "rb-text": RbTextElement;
184
+ "rb-text-input": RbTextInputElement;
185
+ "rb-switch": RbSwitchElement;
186
+ "rb-select": RbSelectElement;
187
+ }
188
+ }
189
+ /**
190
+ * Registers the rb-* custom elements. Safe to call multiple times; only the
191
+ * first call defines anything (subsequent calls are a no-op).
192
+ */
193
+ export declare function defineElements(): void;
194
+ export {};
195
+ //# sourceMappingURL=elements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { RemoteElement } from "@remote-dom/core/elements";
2
+ class RbSliderElement extends RemoteElement {
3
+ static get remoteProperties() {
4
+ return {
5
+ value: { type: Number },
6
+ min: { type: Number },
7
+ max: { type: Number },
8
+ step: { type: Number },
9
+ disabled: { type: Boolean }
10
+ };
11
+ }
12
+ static get remoteEvents() {
13
+ return ["change"];
14
+ }
15
+ }
16
+ class RbButtonElement extends RemoteElement {
17
+ static get remoteProperties() {
18
+ return {
19
+ label: { type: String },
20
+ variant: { type: String },
21
+ size: { type: String },
22
+ disabled: { type: Boolean }
23
+ };
24
+ }
25
+ static get remoteEvents() {
26
+ return ["press"];
27
+ }
28
+ }
29
+ class RbIconButtonElement extends RemoteElement {
30
+ static get remoteProperties() {
31
+ return {
32
+ icon: { type: String },
33
+ variant: { type: String },
34
+ size: { type: String },
35
+ disabled: { type: Boolean }
36
+ };
37
+ }
38
+ static get remoteEvents() {
39
+ return ["press"];
40
+ }
41
+ }
42
+ class RbTextElement extends RemoteElement {
43
+ static get remoteProperties() {
44
+ return {};
45
+ }
46
+ }
47
+ class RbTextInputElement extends RemoteElement {
48
+ static get remoteProperties() {
49
+ return {
50
+ value: { type: String },
51
+ placeholder: { type: String },
52
+ disabled: { type: Boolean }
53
+ };
54
+ }
55
+ static get remoteEvents() {
56
+ return ["input"];
57
+ }
58
+ }
59
+ class RbSwitchElement extends RemoteElement {
60
+ static get remoteProperties() {
61
+ return {
62
+ checked: { type: Boolean },
63
+ disabled: { type: Boolean }
64
+ };
65
+ }
66
+ static get remoteEvents() {
67
+ return ["change"];
68
+ }
69
+ }
70
+ class RbSelectElement extends RemoteElement {
71
+ static get remoteProperties() {
72
+ return {
73
+ value: { type: String },
74
+ options: { type: Array },
75
+ placeholder: { type: String },
76
+ disabled: { type: Boolean }
77
+ };
78
+ }
79
+ static get remoteEvents() {
80
+ return ["change"];
81
+ }
82
+ }
83
+ const RB_ELEMENT_NAMES = [
84
+ "rb-slider",
85
+ "rb-button",
86
+ "rb-icon-button",
87
+ "rb-text",
88
+ "rb-text-input",
89
+ "rb-switch",
90
+ "rb-select"
91
+ ];
92
+ let defined = false;
93
+ function defineElements() {
94
+ if (defined || typeof customElements === "undefined") return;
95
+ defined = true;
96
+ customElements.define("rb-slider", RbSliderElement);
97
+ customElements.define("rb-button", RbButtonElement);
98
+ customElements.define("rb-icon-button", RbIconButtonElement);
99
+ customElements.define("rb-text", RbTextElement);
100
+ customElements.define("rb-text-input", RbTextInputElement);
101
+ customElements.define("rb-switch", RbSwitchElement);
102
+ customElements.define("rb-select", RbSelectElement);
103
+ }
104
+ export {
105
+ RB_ELEMENT_NAMES,
106
+ RbButtonElement,
107
+ RbIconButtonElement,
108
+ RbSelectElement,
109
+ RbSliderElement,
110
+ RbSwitchElement,
111
+ RbTextElement,
112
+ RbTextInputElement,
113
+ defineElements
114
+ };
115
+ //# sourceMappingURL=elements.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/elements.ts"],
4
+ "sourcesContent": ["/**\n * rb-* remote element contract \u2014 shared by the sandbox (plugin author) and the\n * nexus host. This is the *stable* surface: it must only ever grow additively\n * (new elements / new optional properties), never break existing shapes.\n *\n * Verified against @remote-dom/core@1.11.x:\n * - `RemoteElement` lives in `@remote-dom/core/elements`\n * - static `remoteProperties` (data) + static `remoteEvents` (callbacks)\n */\nimport { RemoteElement } from \"@remote-dom/core/elements\";\n\ntype RbNoMethods = Record<never, never>;\ntype RbNoSlots = Record<never, never>;\ntype RbNoEvents = Record<never, never>;\n\nexport interface RbSliderProps {\n value?: number;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n}\n\nexport interface RbButtonProps {\n label?: string;\n variant?: string;\n size?: string;\n disabled?: boolean;\n}\n\nexport interface RbIconButtonProps {\n icon?: string;\n variant?: string;\n size?: string;\n disabled?: boolean;\n}\n\nexport type RbTextProps = Record<never, never>;\n\nexport interface RbTextInputProps {\n value?: string;\n placeholder?: string;\n disabled?: boolean;\n}\n\nexport interface RbSwitchProps {\n checked?: boolean;\n disabled?: boolean;\n}\n\n/** Option shape carried by `rb-select`'s `options` property. */\nexport interface RbSelectOption {\n value: string;\n label: string;\n}\n\nexport interface RbSelectProps {\n value?: string;\n options?: RbSelectOption[];\n placeholder?: string;\n disabled?: boolean;\n}\n\nexport interface RbSliderEvents {\n change(detail: number): void;\n}\n\nexport interface RbPressEvents {\n press(): void;\n}\n\nexport interface RbTextInputEvents {\n input(detail: string): void;\n}\n\nexport interface RbSwitchEvents {\n change(detail: boolean): void;\n}\n\nexport interface RbSelectEvents {\n change(detail: string): void;\n}\n\n/** Slider \u2192 host renders RBSlider (Radix array value, single-thumb contract). */\nexport class RbSliderElement extends RemoteElement<\n RbSliderProps,\n RbNoMethods,\n RbNoSlots,\n RbSliderEvents\n> {\n static get remoteProperties() {\n return {\n value: { type: Number },\n min: { type: Number },\n max: { type: Number },\n step: { type: Number },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"change\"] as const;\n }\n}\n\n/** Button \u2192 host renders RBLabelButton. */\nexport class RbButtonElement extends RemoteElement<\n RbButtonProps,\n RbNoMethods,\n RbNoSlots,\n RbPressEvents\n> {\n static get remoteProperties() {\n return {\n label: { type: String },\n variant: { type: String },\n size: { type: String },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"press\"] as const;\n }\n}\n\n/** Icon button \u2192 host renders RBIconButton with an icon resolved from RBIcons. */\nexport class RbIconButtonElement extends RemoteElement<\n RbIconButtonProps,\n RbNoMethods,\n RbNoSlots,\n RbPressEvents\n> {\n static get remoteProperties() {\n return {\n icon: { type: String },\n variant: { type: String },\n size: { type: String },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"press\"] as const;\n }\n}\n\n/** Plain text \u2014 renders its children as text on the host. */\nexport class RbTextElement extends RemoteElement<\n RbTextProps,\n RbNoMethods,\n RbNoSlots,\n RbNoEvents\n> {\n static get remoteProperties() {\n return {};\n }\n}\n\n/** Text input \u2192 host renders RBTextInput. */\nexport class RbTextInputElement extends RemoteElement<\n RbTextInputProps,\n RbNoMethods,\n RbNoSlots,\n RbTextInputEvents\n> {\n static get remoteProperties() {\n return {\n value: { type: String },\n placeholder: { type: String },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"input\"] as const;\n }\n}\n\n/** Switch \u2192 host renders RBSwitch. */\nexport class RbSwitchElement extends RemoteElement<\n RbSwitchProps,\n RbNoMethods,\n RbNoSlots,\n RbSwitchEvents\n> {\n static get remoteProperties() {\n return {\n checked: { type: Boolean },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"change\"] as const;\n }\n}\n\n/** Select \u2192 host renders RBSelectBox. `options` is `[{value,label}]`. */\nexport class RbSelectElement extends RemoteElement<\n RbSelectProps,\n RbNoMethods,\n RbNoSlots,\n RbSelectEvents\n> {\n static get remoteProperties() {\n return {\n value: { type: String },\n options: { type: Array },\n placeholder: { type: String },\n disabled: { type: Boolean },\n };\n }\n static get remoteEvents() {\n return [\"change\"] as const;\n }\n}\n\n/** Custom element tag names in the contract. */\nexport const RB_ELEMENT_NAMES = [\n \"rb-slider\",\n \"rb-button\",\n \"rb-icon-button\",\n \"rb-text\",\n \"rb-text-input\",\n \"rb-switch\",\n \"rb-select\",\n] as const;\n\nexport type RbElementName = (typeof RB_ELEMENT_NAMES)[number];\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"rb-slider\": RbSliderElement;\n \"rb-button\": RbButtonElement;\n \"rb-icon-button\": RbIconButtonElement;\n \"rb-text\": RbTextElement;\n \"rb-text-input\": RbTextInputElement;\n \"rb-switch\": RbSwitchElement;\n \"rb-select\": RbSelectElement;\n }\n}\n\nlet defined = false;\n\n/**\n * Registers the rb-* custom elements. Safe to call multiple times; only the\n * first call defines anything (subsequent calls are a no-op).\n */\nexport function defineElements(): void {\n if (defined || typeof customElements === \"undefined\") return;\n\n defined = true;\n\n customElements.define(\"rb-slider\", RbSliderElement);\n customElements.define(\"rb-button\", RbButtonElement);\n customElements.define(\"rb-icon-button\", RbIconButtonElement);\n customElements.define(\"rb-text\", RbTextElement);\n customElements.define(\"rb-text-input\", RbTextInputElement);\n customElements.define(\"rb-switch\", RbSwitchElement);\n customElements.define(\"rb-select\", RbSelectElement);\n}\n"],
5
+ "mappings": "AASA,SAAS,qBAAqB;AA2EvB,MAAM,wBAAwB,cAKnC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,OAAO,EAAE,MAAM,OAAO;AAAA,MACtB,KAAK,EAAE,MAAM,OAAO;AAAA,MACpB,KAAK,EAAE,MAAM,OAAO;AAAA,MACpB,MAAM,EAAE,MAAM,OAAO;AAAA,MACrB,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,QAAQ;AAAA,EAClB;AACF;AAGO,MAAM,wBAAwB,cAKnC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,OAAO,EAAE,MAAM,OAAO;AAAA,MACtB,SAAS,EAAE,MAAM,OAAO;AAAA,MACxB,MAAM,EAAE,MAAM,OAAO;AAAA,MACrB,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,OAAO;AAAA,EACjB;AACF;AAGO,MAAM,4BAA4B,cAKvC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,MAAM,EAAE,MAAM,OAAO;AAAA,MACrB,SAAS,EAAE,MAAM,OAAO;AAAA,MACxB,MAAM,EAAE,MAAM,OAAO;AAAA,MACrB,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,OAAO;AAAA,EACjB;AACF;AAGO,MAAM,sBAAsB,cAKjC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO,CAAC;AAAA,EACV;AACF;AAGO,MAAM,2BAA2B,cAKtC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,OAAO,EAAE,MAAM,OAAO;AAAA,MACtB,aAAa,EAAE,MAAM,OAAO;AAAA,MAC5B,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,OAAO;AAAA,EACjB;AACF;AAGO,MAAM,wBAAwB,cAKnC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,SAAS,EAAE,MAAM,QAAQ;AAAA,MACzB,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,QAAQ;AAAA,EAClB;AACF;AAGO,MAAM,wBAAwB,cAKnC;AAAA,EACA,WAAW,mBAAmB;AAC5B,WAAO;AAAA,MACL,OAAO,EAAE,MAAM,OAAO;AAAA,MACtB,SAAS,EAAE,MAAM,MAAM;AAAA,MACvB,aAAa,EAAE,MAAM,OAAO;AAAA,MAC5B,UAAU,EAAE,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,eAAe;AACxB,WAAO,CAAC,QAAQ;AAAA,EAClB;AACF;AAGO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgBA,IAAI,UAAU;AAMP,SAAS,iBAAuB;AACrC,MAAI,WAAW,OAAO,mBAAmB,YAAa;AAEtD,YAAU;AAEV,iBAAe,OAAO,aAAa,eAAe;AAClD,iBAAe,OAAO,aAAa,eAAe;AAClD,iBAAe,OAAO,kBAAkB,mBAAmB;AAC3D,iBAAe,OAAO,WAAW,aAAa;AAC9C,iBAAe,OAAO,iBAAiB,kBAAkB;AACzD,iBAAe,OAAO,aAAa,eAAe;AAClD,iBAAe,OAAO,aAAa,eAAe;AACpD;",
6
+ "names": []
7
+ }