@protolabsai/ui 0.18.0 → 0.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protolabsai/ui",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
@@ -22,10 +22,13 @@
22
22
  "./menu": "./src/menu.tsx",
23
23
  "./app-shell": "./src/app-shell.tsx",
24
24
  "./theming": "./src/theming.tsx",
25
- "./styles.css": "./src/styles.css"
25
+ "./styles.css": "./src/styles.css",
26
+ "./plugin-kit.css": "./dist/plugin-kit.css",
27
+ "./plugin-kit.js": "./src/plugin-kit.js"
26
28
  },
27
29
  "files": [
28
- "src"
30
+ "src",
31
+ "dist"
29
32
  ],
30
33
  "dependencies": {
31
34
  "@dnd-kit/core": "^6.3.1",
@@ -54,6 +57,8 @@
54
57
  "vite": "^6.0.0"
55
58
  },
56
59
  "scripts": {
60
+ "build": "node scripts/build-plugin-kit.mjs",
61
+ "build:plugin-kit": "node scripts/build-plugin-kit.mjs",
57
62
  "storybook": "storybook dev -p 6006 --no-open",
58
63
  "build-storybook": "storybook build -o storybook-static",
59
64
  "typecheck": "tsc --noEmit"
@@ -47,7 +47,10 @@ function Sample() {
47
47
  export const LiveEditor: Story = {
48
48
  render: () => (
49
49
  <div style={{ display: "flex", gap: 24, alignItems: "flex-start", padding: 24, flexWrap: "wrap" }}>
50
- <ThemePanel />
50
+ {/* The panel fills its container — the host sizes it (here a 400×560 box). */}
51
+ <div style={{ width: 400, height: 560 }}>
52
+ <ThemePanel />
53
+ </div>
51
54
  <div style={{ flex: "1 1 360px" }}>
52
55
  <Sample />
53
56
  </div>
@@ -0,0 +1,70 @@
1
+ // @protolabsai/ui/plugin-kit — the ADR 0026 console handshake for protoAgent
2
+ // plugin iframe pages. Replaces the broken substring stub that shipped copy-pasted
3
+ // across plugins (it only mapped bg/accent onto private vars and dropped every other
4
+ // token). This applies the console's FULL --pl-* theme bundle to :root and captures
5
+ // the bearer token for same-origin API calls.
6
+ //
7
+ // Two ways to use it (no build step required for either):
8
+ // 1. <script type="module">: import { initPluginView } from ".../plugin-kit.js"
9
+ // 2. classic <script src=".../plugin-kit.js">: use the window.protoPluginView global
10
+ // Or just inline the snippet from docs/how-to/build-a-plugin-view.md.
11
+
12
+ let token = null;
13
+ const listeners = new Set();
14
+
15
+ /** Apply only DS custom properties from a theme map to :root — a stray key can
16
+ * never set an arbitrary CSS property. */
17
+ function applyTheme(theme) {
18
+ if (!theme || typeof theme !== "object") return;
19
+ const root = document.documentElement;
20
+ for (const [k, v] of Object.entries(theme)) {
21
+ if (k.startsWith("--pl-")) root.style.setProperty(k, String(v));
22
+ }
23
+ }
24
+
25
+ function onMessage(e) {
26
+ const d = e && e.data;
27
+ if (!d || d.type !== "protoagent:init") return;
28
+ if (d.token) token = d.token;
29
+ applyTheme(d.theme);
30
+ for (const fn of listeners) {
31
+ try {
32
+ fn({ token, theme: d.theme });
33
+ } catch (_) {
34
+ /* a listener throwing must not break the handshake */
35
+ }
36
+ }
37
+ }
38
+
39
+ /** Start listening for the console handshake. Call once on load. `onInit` (optional)
40
+ * fires every time the console (re)sends tokens/theme — e.g. on a live theme switch.
41
+ * Returns a small handle with the current token. */
42
+ export function initPluginView(onInit) {
43
+ if (typeof onInit === "function") listeners.add(onInit);
44
+ window.addEventListener("message", onMessage);
45
+ // Announce readiness so a console that waits for it sends the init eagerly.
46
+ try {
47
+ window.parent && window.parent.postMessage({ type: "protoagent:ready" }, "*");
48
+ } catch (_) {
49
+ /* sandboxed / no parent */
50
+ }
51
+ return { getToken };
52
+ }
53
+
54
+ /** The captured bearer token (null until the handshake delivers one). */
55
+ export function getToken() {
56
+ return token;
57
+ }
58
+
59
+ /** Same-origin fetch with the bearer token attached when present. */
60
+ export function apiFetch(input, init) {
61
+ const opts = init || {};
62
+ const headers = new Headers(opts.headers || {});
63
+ if (token) headers.set("Authorization", "Bearer " + token);
64
+ return fetch(input, { ...opts, headers });
65
+ }
66
+
67
+ // Expose a global for classic <script src> (no-build) pages that can't use imports.
68
+ if (typeof window !== "undefined") {
69
+ window.protoPluginView = { initPluginView, getToken, apiFetch };
70
+ }
@@ -5,7 +5,7 @@
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  width: 100%;
8
- max-width: 440px;
8
+ height: 100%;
9
9
  color: var(--pl-color-fg);
10
10
  font-size: 13px;
11
11
  background: var(--pl-color-bg-raised);
@@ -71,8 +71,9 @@
71
71
  .pl-theme-panel__groups {
72
72
  display: flex;
73
73
  flex-direction: column;
74
+ flex: 1;
75
+ min-height: 0;
74
76
  gap: var(--pl-space-4);
75
- max-height: 460px;
76
77
  padding: var(--pl-space-3);
77
78
  overflow-y: auto;
78
79
  }