@proteos/component-sdk 0.18.1

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/LICENSE ADDED
@@ -0,0 +1,40 @@
1
+ PROPRIETARY AND CONFIDENTIAL
2
+
3
+ Copyright (c) 2026 Proteos. All rights reserved.
4
+
5
+ This software, including all source code, object code, documentation, designs,
6
+ and any other materials contained in this repository (the "Software"), is the
7
+ proprietary and confidential property of Proteos.
8
+
9
+ NO LICENSE IS GRANTED. The Software is made available solely for internal use
10
+ by Proteos and its authorized employees, contractors, and agents under the
11
+ terms of their respective agreements with Proteos.
12
+
13
+ Without the express prior written permission of Proteos, you may not, in whole
14
+ or in part:
15
+
16
+ 1. copy, reproduce, mirror, host, or store the Software;
17
+ 2. modify, adapt, translate, or create derivative works of the Software;
18
+ 3. distribute, publish, transmit, sublicense, sell, rent, lease, or
19
+ otherwise transfer or make the Software available to any third party;
20
+ 4. reverse engineer, decompile, disassemble, or attempt to derive the
21
+ source code, structure, or organization of any compiled portion of the
22
+ Software, except to the extent that such activity is expressly permitted
23
+ by applicable law notwithstanding this restriction;
24
+ 5. remove, obscure, or alter any proprietary notices, labels, or marks
25
+ contained in the Software; or
26
+ 6. use the Software, or any information derived from it, to develop or
27
+ improve a competing product or service.
28
+
29
+ Any unauthorized use, reproduction, or disclosure of the Software constitutes
30
+ a material breach of this license, may infringe Proteos' intellectual property
31
+ rights, and may violate applicable laws.
32
+
33
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT
36
+ SHALL PROTEOS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
37
+ IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
38
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39
+
40
+ For licensing inquiries, contact: legal@proteos.io
@@ -0,0 +1,12 @@
1
+ // src/protocol.ts
2
+ var MESSAGE_SOURCE = "proteos-component-runtime";
3
+ function isHostMessage(data) {
4
+ return typeof data === "object" && data !== null && data.source === MESSAGE_SOURCE && typeof data.type === "string";
5
+ }
6
+ function isRuntimeMessage(data) {
7
+ return typeof data === "object" && data !== null && data.source === MESSAGE_SOURCE && typeof data.type === "string";
8
+ }
9
+
10
+ export { MESSAGE_SOURCE, isHostMessage, isRuntimeMessage };
11
+ //# sourceMappingURL=chunk-NMXHDDL6.js.map
12
+ //# sourceMappingURL=chunk-NMXHDDL6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";AAUO,IAAM,cAAA,GAAiB;AA4EvB,SAAS,cAAc,IAAA,EAA8C;AAC1E,EAAA,OACE,OAAO,IAAA,KAAS,QAAA,IAChB,IAAA,KAAS,IAAA,IACR,KAA8B,MAAA,KAAW,cAAA,IAC1C,OAAQ,IAAA,CAA4B,IAAA,KAAS,QAAA;AAEjD;AAEO,SAAS,iBAAiB,IAAA,EAAiD;AAChF,EAAA,OACE,OAAO,IAAA,KAAS,QAAA,IAChB,IAAA,KAAS,IAAA,IACR,KAA8B,MAAA,KAAW,cAAA,IAC1C,OAAQ,IAAA,CAA4B,IAAA,KAAS,QAAA;AAEjD","file":"chunk-NMXHDDL6.js","sourcesContent":["// postMessage protocol between the host page and the component-runtime iframe.\n// This is the single source of truth for the wire contract: the host renderer\n// (clients/web .../component-frame.tsx), the runtime shell\n// (clients/web/component-runtime/shell.tsx), and the author-facing hooks\n// (this package's RuntimeProvider / useNavigate) all import these same types so\n// every end stays in lockstep.\n//\n// Every message carries `source: MESSAGE_SOURCE` so we can ignore the unrelated\n// postMessage traffic that shares the window (OIDC silent-renew, Vite HMR, …).\n\nexport const MESSAGE_SOURCE = 'proteos-component-runtime' as const\n\nexport interface PageContext {\n record?: Record<string, unknown>\n entity?: { slug: string; [key: string]: unknown }\n params?: Record<string, unknown>\n [key: string]: unknown\n}\n\n// ── Host → runtime ──────────────────────────────────────────────────────────\n\nexport interface InitMessage {\n type: 'INIT'\n /** Raw bearer token (the OIDC `id_token`). The runtime's ProteosClient\n * prepends `Bearer ` when building the Authorization header, so the host\n * sends the token verbatim — NOT a full `Bearer …` header value. */\n authToken: string\n /** API origin the bundle endpoint + SDK calls resolve against. */\n apiBaseUrl: string\n /** Resolved props for the component (Liquid templating happens host-side). */\n props: Record<string, unknown>\n pageCtx: PageContext\n}\n\nexport interface AuthRefreshMessage {\n type: 'AUTH_REFRESH'\n token: string\n}\n\nexport interface DataInvalidateMessage {\n type: 'DATA_INVALIDATE'\n queryKey?: unknown[]\n}\n\nexport type HostMessage = InitMessage | AuthRefreshMessage | DataInvalidateMessage\n\n// ── Runtime → host ──────────────────────────────────────────────────────────\n\nexport interface ReadyMessage {\n type: 'READY'\n}\n\nexport interface ResizeMessage {\n type: 'RESIZE'\n height: number\n}\n\nexport interface NavigateMessage {\n type: 'NAVIGATE'\n to: string\n}\n\n/** Open an in-app path in a peek (slide-over) panel instead of full-page\n * navigation. Same `/…` in-app path grammar as NAVIGATE; the host decides\n * what can peek (today: platform pages) and falls back to NAVIGATE otherwise. */\nexport interface OpenPeekMessage {\n type: 'OPEN_PEEK'\n to: string\n}\n\nexport interface ErrorMessage {\n type: 'ERROR'\n message: string\n stack?: string\n}\n\nexport type RuntimeMessage =\n | ReadyMessage\n | ResizeMessage\n | NavigateMessage\n | OpenPeekMessage\n | ErrorMessage\n\n// Wire envelope: the message plus the source discriminator.\nexport type Envelope<T> = T & { source: typeof MESSAGE_SOURCE }\n\nexport function isHostMessage(data: unknown): data is Envelope<HostMessage> {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as { source?: unknown }).source === MESSAGE_SOURCE &&\n typeof (data as { type?: unknown }).type === 'string'\n )\n}\n\nexport function isRuntimeMessage(data: unknown): data is Envelope<RuntimeMessage> {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as { source?: unknown }).source === MESSAGE_SOURCE &&\n typeof (data as { type?: unknown }).type === 'string'\n )\n}\n"]}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ // src/protocol.ts
4
+ var MESSAGE_SOURCE = "proteos-component-runtime";
5
+ function isHostMessage(data) {
6
+ return typeof data === "object" && data !== null && data.source === MESSAGE_SOURCE && typeof data.type === "string";
7
+ }
8
+ function isRuntimeMessage(data) {
9
+ return typeof data === "object" && data !== null && data.source === MESSAGE_SOURCE && typeof data.type === "string";
10
+ }
11
+
12
+ exports.MESSAGE_SOURCE = MESSAGE_SOURCE;
13
+ exports.isHostMessage = isHostMessage;
14
+ exports.isRuntimeMessage = isRuntimeMessage;
15
+ //# sourceMappingURL=chunk-SMAZA2KE.cjs.map
16
+ //# sourceMappingURL=chunk-SMAZA2KE.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";;;AAUO,IAAM,cAAA,GAAiB;AA4EvB,SAAS,cAAc,IAAA,EAA8C;AAC1E,EAAA,OACE,OAAO,IAAA,KAAS,QAAA,IAChB,IAAA,KAAS,IAAA,IACR,KAA8B,MAAA,KAAW,cAAA,IAC1C,OAAQ,IAAA,CAA4B,IAAA,KAAS,QAAA;AAEjD;AAEO,SAAS,iBAAiB,IAAA,EAAiD;AAChF,EAAA,OACE,OAAO,IAAA,KAAS,QAAA,IAChB,IAAA,KAAS,IAAA,IACR,KAA8B,MAAA,KAAW,cAAA,IAC1C,OAAQ,IAAA,CAA4B,IAAA,KAAS,QAAA;AAEjD","file":"chunk-SMAZA2KE.cjs","sourcesContent":["// postMessage protocol between the host page and the component-runtime iframe.\n// This is the single source of truth for the wire contract: the host renderer\n// (clients/web .../component-frame.tsx), the runtime shell\n// (clients/web/component-runtime/shell.tsx), and the author-facing hooks\n// (this package's RuntimeProvider / useNavigate) all import these same types so\n// every end stays in lockstep.\n//\n// Every message carries `source: MESSAGE_SOURCE` so we can ignore the unrelated\n// postMessage traffic that shares the window (OIDC silent-renew, Vite HMR, …).\n\nexport const MESSAGE_SOURCE = 'proteos-component-runtime' as const\n\nexport interface PageContext {\n record?: Record<string, unknown>\n entity?: { slug: string; [key: string]: unknown }\n params?: Record<string, unknown>\n [key: string]: unknown\n}\n\n// ── Host → runtime ──────────────────────────────────────────────────────────\n\nexport interface InitMessage {\n type: 'INIT'\n /** Raw bearer token (the OIDC `id_token`). The runtime's ProteosClient\n * prepends `Bearer ` when building the Authorization header, so the host\n * sends the token verbatim — NOT a full `Bearer …` header value. */\n authToken: string\n /** API origin the bundle endpoint + SDK calls resolve against. */\n apiBaseUrl: string\n /** Resolved props for the component (Liquid templating happens host-side). */\n props: Record<string, unknown>\n pageCtx: PageContext\n}\n\nexport interface AuthRefreshMessage {\n type: 'AUTH_REFRESH'\n token: string\n}\n\nexport interface DataInvalidateMessage {\n type: 'DATA_INVALIDATE'\n queryKey?: unknown[]\n}\n\nexport type HostMessage = InitMessage | AuthRefreshMessage | DataInvalidateMessage\n\n// ── Runtime → host ──────────────────────────────────────────────────────────\n\nexport interface ReadyMessage {\n type: 'READY'\n}\n\nexport interface ResizeMessage {\n type: 'RESIZE'\n height: number\n}\n\nexport interface NavigateMessage {\n type: 'NAVIGATE'\n to: string\n}\n\n/** Open an in-app path in a peek (slide-over) panel instead of full-page\n * navigation. Same `/…` in-app path grammar as NAVIGATE; the host decides\n * what can peek (today: platform pages) and falls back to NAVIGATE otherwise. */\nexport interface OpenPeekMessage {\n type: 'OPEN_PEEK'\n to: string\n}\n\nexport interface ErrorMessage {\n type: 'ERROR'\n message: string\n stack?: string\n}\n\nexport type RuntimeMessage =\n | ReadyMessage\n | ResizeMessage\n | NavigateMessage\n | OpenPeekMessage\n | ErrorMessage\n\n// Wire envelope: the message plus the source discriminator.\nexport type Envelope<T> = T & { source: typeof MESSAGE_SOURCE }\n\nexport function isHostMessage(data: unknown): data is Envelope<HostMessage> {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as { source?: unknown }).source === MESSAGE_SOURCE &&\n typeof (data as { type?: unknown }).type === 'string'\n )\n}\n\nexport function isRuntimeMessage(data: unknown): data is Envelope<RuntimeMessage> {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as { source?: unknown }).source === MESSAGE_SOURCE &&\n typeof (data as { type?: unknown }).type === 'string'\n )\n}\n"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,121 @@
1
+ 'use strict';
2
+
3
+ var chunkSMAZA2KE_cjs = require('./chunk-SMAZA2KE.cjs');
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ var RuntimeContext = react.createContext(null);
8
+ function postNavigate(to) {
9
+ const envelope = { source: chunkSMAZA2KE_cjs.MESSAGE_SOURCE, type: "NAVIGATE", to };
10
+ window.parent?.postMessage(envelope, "*");
11
+ }
12
+ function postOpenPeek(to) {
13
+ const envelope = { source: chunkSMAZA2KE_cjs.MESSAGE_SOURCE, type: "OPEN_PEEK", to };
14
+ window.parent?.postMessage(envelope, "*");
15
+ }
16
+ function navigate(to, options) {
17
+ if (options?.peek) postOpenPeek(to);
18
+ else postNavigate(to);
19
+ }
20
+ function RuntimeProvider({ value, children }) {
21
+ const ctx = react.useMemo(() => ({ ...value, navigate }), [value]);
22
+ return /* @__PURE__ */ jsxRuntime.jsx(RuntimeContext.Provider, { value: ctx, children });
23
+ }
24
+ function useRuntime() {
25
+ const ctx = react.useContext(RuntimeContext);
26
+ if (!ctx) {
27
+ throw new Error(
28
+ "@proteos/component-sdk: hooks must run inside the Proteos component runtime. This usually means the component is rendered outside its iframe, or a second copy of @proteos/component-sdk was bundled instead of using the runtime-provided one (keep it external)."
29
+ );
30
+ }
31
+ return ctx;
32
+ }
33
+ function useSdk() {
34
+ return useRuntime().sdk;
35
+ }
36
+ function useProps() {
37
+ return useRuntime().props;
38
+ }
39
+ function usePageContext() {
40
+ return useRuntime().pageCtx;
41
+ }
42
+ function useNavigate() {
43
+ return useRuntime().navigate;
44
+ }
45
+ function useApiBaseUrl() {
46
+ return useRuntime().apiBaseUrl;
47
+ }
48
+ function useAuthToken() {
49
+ return useRuntime().getToken;
50
+ }
51
+ function readHostLocation() {
52
+ const empty = { pathname: null, orgId: null, appBasePath: null };
53
+ try {
54
+ const parentWindow = window.parent;
55
+ if (!parentWindow || parentWindow === window) return empty;
56
+ const pathname = parentWindow.location.pathname;
57
+ const appMatch = pathname.match(/^\/org\/[^/]+\/app\/[^/]+/);
58
+ const orgMatch = pathname.match(/^\/org\/([^/]+)\//);
59
+ return {
60
+ pathname,
61
+ orgId: orgMatch ? orgMatch[1] ?? null : null,
62
+ appBasePath: appMatch ? appMatch[0] : null
63
+ };
64
+ } catch {
65
+ return empty;
66
+ }
67
+ }
68
+ function useHostLocation() {
69
+ const [loc] = react.useState(readHostLocation);
70
+ return loc;
71
+ }
72
+ function useFillViewportHeight(options = {}) {
73
+ const { bottomMargin = 24, minHeight = 320 } = options;
74
+ const [height, setHeight] = react.useState(null);
75
+ react.useEffect(() => {
76
+ function compute() {
77
+ try {
78
+ const frame = window.frameElement;
79
+ const parentWindow = window.parent;
80
+ if (!frame || !parentWindow || parentWindow === window) return;
81
+ const available = parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin;
82
+ setHeight(Math.max(available, minHeight));
83
+ } catch {
84
+ setHeight(null);
85
+ }
86
+ }
87
+ compute();
88
+ try {
89
+ window.parent.addEventListener("resize", compute);
90
+ return () => window.parent.removeEventListener("resize", compute);
91
+ } catch {
92
+ return;
93
+ }
94
+ }, [bottomMargin, minHeight]);
95
+ return height;
96
+ }
97
+
98
+ Object.defineProperty(exports, "MESSAGE_SOURCE", {
99
+ enumerable: true,
100
+ get: function () { return chunkSMAZA2KE_cjs.MESSAGE_SOURCE; }
101
+ });
102
+ Object.defineProperty(exports, "isHostMessage", {
103
+ enumerable: true,
104
+ get: function () { return chunkSMAZA2KE_cjs.isHostMessage; }
105
+ });
106
+ Object.defineProperty(exports, "isRuntimeMessage", {
107
+ enumerable: true,
108
+ get: function () { return chunkSMAZA2KE_cjs.isRuntimeMessage; }
109
+ });
110
+ exports.RuntimeProvider = RuntimeProvider;
111
+ exports.useApiBaseUrl = useApiBaseUrl;
112
+ exports.useAuthToken = useAuthToken;
113
+ exports.useFillViewportHeight = useFillViewportHeight;
114
+ exports.useHostLocation = useHostLocation;
115
+ exports.useNavigate = useNavigate;
116
+ exports.usePageContext = usePageContext;
117
+ exports.useProps = useProps;
118
+ exports.useRuntime = useRuntime;
119
+ exports.useSdk = useSdk;
120
+ //# sourceMappingURL=index.cjs.map
121
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":["createContext","MESSAGE_SOURCE","useMemo","useContext","useState","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). */\n getToken: () => string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / data / functions / meta). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}
@@ -0,0 +1,134 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { AccountClient, AgentClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
+ import { PageContext } from './protocol.cjs';
5
+ export { AuthRefreshMessage, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, NavigateMessage, OpenPeekMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.cjs';
6
+
7
+ /** Options for {@link RuntimeContextValue.navigate}. */
8
+ interface NavigateOptions {
9
+ /** Open the target in a peek (slide-over) panel instead of full-page. */
10
+ peek?: boolean;
11
+ }
12
+ /**
13
+ * The authenticated `@proteos/sdk` clients the runtime injects. Same instances
14
+ * the host app uses — pre-wired with a refreshing bearer token, so a component
15
+ * never touches auth headers.
16
+ */
17
+ interface ComponentSdk {
18
+ account: AccountClient;
19
+ agents: AgentClient;
20
+ data: DataClient;
21
+ functions: FunctionsClient;
22
+ knowledge: KnowledgeClient;
23
+ meta: MetaClient;
24
+ storage: StorageClient;
25
+ }
26
+ /**
27
+ * The raw runtime payload the shell hands a component at INIT. The shell builds
28
+ * this; component authors read it through the hooks.
29
+ */
30
+ interface RuntimeValue {
31
+ sdk: ComponentSdk;
32
+ /** Liquid-resolved props (a snapshot — not a live binding). */
33
+ props: Record<string, unknown>;
34
+ /** Page context snapshot: the host record, entity, and URL params. */
35
+ pageCtx: PageContext;
36
+ /** API origin SDK calls + asset URLs resolve against. */
37
+ apiBaseUrl: string;
38
+ /** Current bearer token getter (escape hatch for raw fetches). */
39
+ getToken: () => string;
40
+ }
41
+ /** Runtime value plus the derived helpers the hooks expose. */
42
+ interface RuntimeContextValue extends RuntimeValue {
43
+ /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or
44
+ * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */
45
+ navigate: (to: string, options?: NavigateOptions) => void;
46
+ }
47
+ /**
48
+ * Provides the runtime value + derived helpers to a component subtree. Mounted
49
+ * by the component-runtime shell around the loaded component — authors never
50
+ * render this themselves. Lives in `@proteos/component-sdk` (a shared,
51
+ * import-mapped singleton) so the context the shell provides is the very same
52
+ * context the component's hooks read, across the bundle boundary.
53
+ */
54
+ declare function RuntimeProvider({ value, children }: {
55
+ value: RuntimeValue;
56
+ children: ReactNode;
57
+ }): react_jsx_runtime.JSX.Element;
58
+
59
+ declare global {
60
+ interface Window {
61
+ __PROTEOS_RUNTIME__?: {
62
+ apiBaseUrl: string;
63
+ getToken: () => string;
64
+ props: Record<string, unknown>;
65
+ pageCtx: PageContext;
66
+ sdk: ComponentSdk;
67
+ };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,
73
+ * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a
74
+ * clear error if used outside the component runtime.
75
+ */
76
+ declare function useRuntime(): RuntimeContextValue;
77
+ /** The authenticated SDK clients (account / data / functions / meta). */
78
+ declare function useSdk(): ComponentSdk;
79
+ /** The component's Liquid-resolved props (a snapshot, not a live binding). */
80
+ declare function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T;
81
+ /**
82
+ * The full page context: host `record`, `entity`, and URL `params`. The
83
+ * `record` is a snapshot taken at mount (`undefined` on record-less platform
84
+ * pages) — fetch via `useSdk().data` for anything that must stay fresh.
85
+ */
86
+ declare function usePageContext(): PageContext;
87
+ /**
88
+ * Navigate the host SPA to an in-app path, e.g.
89
+ * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external
90
+ * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.
91
+ *
92
+ * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead
93
+ * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host
94
+ * peeks what it can (today: platform pages) and falls back to full navigation.
95
+ */
96
+ declare function useNavigate(): (to: string, options?: NavigateOptions) => void;
97
+ /** The API origin SDK calls resolve against (for building raw asset URLs). */
98
+ declare function useApiBaseUrl(): string;
99
+ /**
100
+ * A getter for the current bearer token. Returns a function (not the token)
101
+ * because the token is refreshed in place — read it at call time for a raw
102
+ * `fetch`. Most components never need this; prefer `useSdk()`.
103
+ */
104
+ declare function useAuthToken(): () => string;
105
+ interface HostLocation {
106
+ /** The host tab's pathname (same-origin read), or null if unavailable. */
107
+ pathname: string | null;
108
+ /** The org id parsed from `/org/<orgId>/…`, or null. */
109
+ orgId: string | null;
110
+ /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */
111
+ appBasePath: string | null;
112
+ }
113
+ /**
114
+ * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`
115
+ * prefix needed to build navigation targets on platform pages. Read once on
116
+ * mount (the iframe re-inits when the host route changes).
117
+ */
118
+ declare function useHostLocation(): HostLocation;
119
+ interface FillViewportOptions {
120
+ /** Gap left below the component (px). Default 24. */
121
+ bottomMargin?: number;
122
+ /** Floor for the computed height (px). Default 320. */
123
+ minHeight?: number;
124
+ }
125
+ /**
126
+ * Compute a "fill the rest of the viewport" height for full-bleed layouts
127
+ * (boards, canvases). The runtime auto-sizes the iframe to its content, so a
128
+ * component can't use its own `vh` units (circular). The iframe is same-origin,
129
+ * so this measures the parent viewport minus the iframe's offset instead.
130
+ * Returns `null` when it can't measure (fall back to natural height).
131
+ */
132
+ declare function useFillViewportHeight(options?: FillViewportOptions): number | null;
133
+
134
+ export { type ComponentSdk, type FillViewportOptions, type HostLocation, type NavigateOptions, PageContext, type RuntimeContextValue, RuntimeProvider, type RuntimeValue, useApiBaseUrl, useAuthToken, useFillViewportHeight, useHostLocation, useNavigate, usePageContext, useProps, useRuntime, useSdk };
@@ -0,0 +1,134 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { AccountClient, AgentClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
+ import { PageContext } from './protocol.js';
5
+ export { AuthRefreshMessage, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, NavigateMessage, OpenPeekMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.js';
6
+
7
+ /** Options for {@link RuntimeContextValue.navigate}. */
8
+ interface NavigateOptions {
9
+ /** Open the target in a peek (slide-over) panel instead of full-page. */
10
+ peek?: boolean;
11
+ }
12
+ /**
13
+ * The authenticated `@proteos/sdk` clients the runtime injects. Same instances
14
+ * the host app uses — pre-wired with a refreshing bearer token, so a component
15
+ * never touches auth headers.
16
+ */
17
+ interface ComponentSdk {
18
+ account: AccountClient;
19
+ agents: AgentClient;
20
+ data: DataClient;
21
+ functions: FunctionsClient;
22
+ knowledge: KnowledgeClient;
23
+ meta: MetaClient;
24
+ storage: StorageClient;
25
+ }
26
+ /**
27
+ * The raw runtime payload the shell hands a component at INIT. The shell builds
28
+ * this; component authors read it through the hooks.
29
+ */
30
+ interface RuntimeValue {
31
+ sdk: ComponentSdk;
32
+ /** Liquid-resolved props (a snapshot — not a live binding). */
33
+ props: Record<string, unknown>;
34
+ /** Page context snapshot: the host record, entity, and URL params. */
35
+ pageCtx: PageContext;
36
+ /** API origin SDK calls + asset URLs resolve against. */
37
+ apiBaseUrl: string;
38
+ /** Current bearer token getter (escape hatch for raw fetches). */
39
+ getToken: () => string;
40
+ }
41
+ /** Runtime value plus the derived helpers the hooks expose. */
42
+ interface RuntimeContextValue extends RuntimeValue {
43
+ /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or
44
+ * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */
45
+ navigate: (to: string, options?: NavigateOptions) => void;
46
+ }
47
+ /**
48
+ * Provides the runtime value + derived helpers to a component subtree. Mounted
49
+ * by the component-runtime shell around the loaded component — authors never
50
+ * render this themselves. Lives in `@proteos/component-sdk` (a shared,
51
+ * import-mapped singleton) so the context the shell provides is the very same
52
+ * context the component's hooks read, across the bundle boundary.
53
+ */
54
+ declare function RuntimeProvider({ value, children }: {
55
+ value: RuntimeValue;
56
+ children: ReactNode;
57
+ }): react_jsx_runtime.JSX.Element;
58
+
59
+ declare global {
60
+ interface Window {
61
+ __PROTEOS_RUNTIME__?: {
62
+ apiBaseUrl: string;
63
+ getToken: () => string;
64
+ props: Record<string, unknown>;
65
+ pageCtx: PageContext;
66
+ sdk: ComponentSdk;
67
+ };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,
73
+ * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a
74
+ * clear error if used outside the component runtime.
75
+ */
76
+ declare function useRuntime(): RuntimeContextValue;
77
+ /** The authenticated SDK clients (account / data / functions / meta). */
78
+ declare function useSdk(): ComponentSdk;
79
+ /** The component's Liquid-resolved props (a snapshot, not a live binding). */
80
+ declare function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T;
81
+ /**
82
+ * The full page context: host `record`, `entity`, and URL `params`. The
83
+ * `record` is a snapshot taken at mount (`undefined` on record-less platform
84
+ * pages) — fetch via `useSdk().data` for anything that must stay fresh.
85
+ */
86
+ declare function usePageContext(): PageContext;
87
+ /**
88
+ * Navigate the host SPA to an in-app path, e.g.
89
+ * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external
90
+ * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.
91
+ *
92
+ * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead
93
+ * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host
94
+ * peeks what it can (today: platform pages) and falls back to full navigation.
95
+ */
96
+ declare function useNavigate(): (to: string, options?: NavigateOptions) => void;
97
+ /** The API origin SDK calls resolve against (for building raw asset URLs). */
98
+ declare function useApiBaseUrl(): string;
99
+ /**
100
+ * A getter for the current bearer token. Returns a function (not the token)
101
+ * because the token is refreshed in place — read it at call time for a raw
102
+ * `fetch`. Most components never need this; prefer `useSdk()`.
103
+ */
104
+ declare function useAuthToken(): () => string;
105
+ interface HostLocation {
106
+ /** The host tab's pathname (same-origin read), or null if unavailable. */
107
+ pathname: string | null;
108
+ /** The org id parsed from `/org/<orgId>/…`, or null. */
109
+ orgId: string | null;
110
+ /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */
111
+ appBasePath: string | null;
112
+ }
113
+ /**
114
+ * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`
115
+ * prefix needed to build navigation targets on platform pages. Read once on
116
+ * mount (the iframe re-inits when the host route changes).
117
+ */
118
+ declare function useHostLocation(): HostLocation;
119
+ interface FillViewportOptions {
120
+ /** Gap left below the component (px). Default 24. */
121
+ bottomMargin?: number;
122
+ /** Floor for the computed height (px). Default 320. */
123
+ minHeight?: number;
124
+ }
125
+ /**
126
+ * Compute a "fill the rest of the viewport" height for full-bleed layouts
127
+ * (boards, canvases). The runtime auto-sizes the iframe to its content, so a
128
+ * component can't use its own `vh` units (circular). The iframe is same-origin,
129
+ * so this measures the parent viewport minus the iframe's offset instead.
130
+ * Returns `null` when it can't measure (fall back to natural height).
131
+ */
132
+ declare function useFillViewportHeight(options?: FillViewportOptions): number | null;
133
+
134
+ export { type ComponentSdk, type FillViewportOptions, type HostLocation, type NavigateOptions, PageContext, type RuntimeContextValue, RuntimeProvider, type RuntimeValue, useApiBaseUrl, useAuthToken, useFillViewportHeight, useHostLocation, useNavigate, usePageContext, useProps, useRuntime, useSdk };
package/dist/index.js ADDED
@@ -0,0 +1,99 @@
1
+ import { MESSAGE_SOURCE } from './chunk-NMXHDDL6.js';
2
+ export { MESSAGE_SOURCE, isHostMessage, isRuntimeMessage } from './chunk-NMXHDDL6.js';
3
+ import { createContext, useMemo, useContext, useState, useEffect } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var RuntimeContext = createContext(null);
7
+ function postNavigate(to) {
8
+ const envelope = { source: MESSAGE_SOURCE, type: "NAVIGATE", to };
9
+ window.parent?.postMessage(envelope, "*");
10
+ }
11
+ function postOpenPeek(to) {
12
+ const envelope = { source: MESSAGE_SOURCE, type: "OPEN_PEEK", to };
13
+ window.parent?.postMessage(envelope, "*");
14
+ }
15
+ function navigate(to, options) {
16
+ if (options?.peek) postOpenPeek(to);
17
+ else postNavigate(to);
18
+ }
19
+ function RuntimeProvider({ value, children }) {
20
+ const ctx = useMemo(() => ({ ...value, navigate }), [value]);
21
+ return /* @__PURE__ */ jsx(RuntimeContext.Provider, { value: ctx, children });
22
+ }
23
+ function useRuntime() {
24
+ const ctx = useContext(RuntimeContext);
25
+ if (!ctx) {
26
+ throw new Error(
27
+ "@proteos/component-sdk: hooks must run inside the Proteos component runtime. This usually means the component is rendered outside its iframe, or a second copy of @proteos/component-sdk was bundled instead of using the runtime-provided one (keep it external)."
28
+ );
29
+ }
30
+ return ctx;
31
+ }
32
+ function useSdk() {
33
+ return useRuntime().sdk;
34
+ }
35
+ function useProps() {
36
+ return useRuntime().props;
37
+ }
38
+ function usePageContext() {
39
+ return useRuntime().pageCtx;
40
+ }
41
+ function useNavigate() {
42
+ return useRuntime().navigate;
43
+ }
44
+ function useApiBaseUrl() {
45
+ return useRuntime().apiBaseUrl;
46
+ }
47
+ function useAuthToken() {
48
+ return useRuntime().getToken;
49
+ }
50
+ function readHostLocation() {
51
+ const empty = { pathname: null, orgId: null, appBasePath: null };
52
+ try {
53
+ const parentWindow = window.parent;
54
+ if (!parentWindow || parentWindow === window) return empty;
55
+ const pathname = parentWindow.location.pathname;
56
+ const appMatch = pathname.match(/^\/org\/[^/]+\/app\/[^/]+/);
57
+ const orgMatch = pathname.match(/^\/org\/([^/]+)\//);
58
+ return {
59
+ pathname,
60
+ orgId: orgMatch ? orgMatch[1] ?? null : null,
61
+ appBasePath: appMatch ? appMatch[0] : null
62
+ };
63
+ } catch {
64
+ return empty;
65
+ }
66
+ }
67
+ function useHostLocation() {
68
+ const [loc] = useState(readHostLocation);
69
+ return loc;
70
+ }
71
+ function useFillViewportHeight(options = {}) {
72
+ const { bottomMargin = 24, minHeight = 320 } = options;
73
+ const [height, setHeight] = useState(null);
74
+ useEffect(() => {
75
+ function compute() {
76
+ try {
77
+ const frame = window.frameElement;
78
+ const parentWindow = window.parent;
79
+ if (!frame || !parentWindow || parentWindow === window) return;
80
+ const available = parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin;
81
+ setHeight(Math.max(available, minHeight));
82
+ } catch {
83
+ setHeight(null);
84
+ }
85
+ }
86
+ compute();
87
+ try {
88
+ window.parent.addEventListener("resize", compute);
89
+ return () => window.parent.removeEventListener("resize", compute);
90
+ } catch {
91
+ return;
92
+ }
93
+ }, [bottomMargin, minHeight]);
94
+ return height;
95
+ }
96
+
97
+ export { RuntimeProvider, useApiBaseUrl, useAuthToken, useFillViewportHeight, useHostLocation, useNavigate, usePageContext, useProps, useRuntime, useSdk };
98
+ //# sourceMappingURL=index.js.map
99
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). */\n getToken: () => string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / data / functions / meta). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}