@proteos/component-sdk 0.42.0 → 0.42.2

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.
@@ -9,5 +9,5 @@ function isRuntimeMessage(data) {
9
9
  }
10
10
 
11
11
  export { COMPONENT_OVERLAY_Z_INDEX, MESSAGE_SOURCE, isHostMessage, isRuntimeMessage };
12
- //# sourceMappingURL=chunk-FSPIGFIQ.js.map
13
- //# sourceMappingURL=chunk-FSPIGFIQ.js.map
12
+ //# sourceMappingURL=chunk-2EAOQNQB.js.map
13
+ //# sourceMappingURL=chunk-2EAOQNQB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";AAUO,IAAM,cAAA,GAAiB;AAuBvB,IAAM,yBAAA,GAA4B;AAkKlC,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-FSPIGFIQ.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\n/**\n * z-index the component iframe is promoted to while one of its own overlays\n * (modal, popover, menu, select, tooltip) is open. The iframe goes\n * `position: fixed; inset: 0` at this z so the overlay — which portals to the\n * IFRAME's body and would otherwise clip at the frame's box — can paint over\n * the rest of the page.\n *\n * Host z ladder this slots into:\n * 50 @proteos/ui Modal / Tooltip / ImageLightbox (default tier)\n * 1000+ full-page panel stack (scrim 1000, panels 1001+n)\n * 1090 peek scrim 1100 peek panel, ask-proteos window\n * 1150 ← THIS\n * 1200 menu popover, command palette, action dialog, component modal\n * 1300 select popover\n *\n * Above the peek/full-page surfaces a component can live on, below the global\n * host chrome. Note the cap: inside a peek (a `fixed` + z-index ancestor) the\n * promoted iframe paints within that 1100 stacking context — it covers the\n * peek's own content and everything under it, but host chrome at 1200+ still\n * wins. That is the intended layering, not a bug.\n */\nexport const COMPONENT_OVERLAY_Z_INDEX = 1150\n\n/** Viewport-relative box of the iframe's in-flow placeholder, in CSS px. */\nexport interface OverlayRect {\n top: number\n left: number\n width: number\n height: number\n}\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 * Empty string in public mode (`isPublic: true`). */\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 /** PUBLIC mode: the component renders on an unauthenticated public page.\n * The shell fetches the bundle from the public endpoint (no bearer) and\n * injects a restricted sdk — only `functions.actions.invokePublic` reaches\n * the platform. Requires `orgId`. */\n isPublic?: boolean\n /** Org id for public mode — public endpoints carry the org in the path\n * because there is no token to scope from. */\n orgId?: string\n /** Set when this frame is the CONTENT of a host component modal (opened by\n * another component via OPEN_MODAL). The component reads it through\n * `useModalHost()` and closes with a result by posting MODAL_RESULT with\n * this id. Absent on ordinary page-hosted frames. */\n modalRequestId?: string\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\n/** Where the iframe's in-flow box sits in the host viewport. Sent while the\n * frame is promoted (OVERLAY_STATE open) so the runtime can keep its content\n * parked at the original rect while the iframe itself covers the viewport —\n * and re-sent when the host window resizes under an open overlay. */\nexport interface OverlayRectMessage {\n type: 'OVERLAY_RECT'\n rect: OverlayRect\n}\n\n/** Resolution of an OPEN_MODAL request: the host modal closed. `result` is the\n * value the modal's component passed to MODAL_RESULT, and is absent when the\n * modal was dismissed (backdrop / Esc / ×). */\nexport interface ModalClosedMessage {\n type: 'MODAL_CLOSED'\n requestId: string\n result?: unknown\n}\n\nexport type HostMessage =\n | InitMessage\n | AuthRefreshMessage\n | DataInvalidateMessage\n | OverlayRectMessage\n | ModalClosedMessage\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\n/** The runtime has (or no longer has) an overlay open and needs the host to\n * promote (or restore) the iframe. See {@link COMPONENT_OVERLAY_Z_INDEX}.\n *\n * Same-origin today, so the runtime applies the promotion styles to its own\n * `window.frameElement` synchronously (pre-paint, no flicker) and this message\n * is the host's cue to MIRROR that state into React — gate RESIZE, hold the\n * placeholder height, start posting OVERLAY_RECT. When components move to a\n * dedicated origin the runtime can no longer touch the frame and this message\n * becomes the actuation instead; the runtime hides its overlay until the\n * answering OVERLAY_RECT arrives. */\nexport interface OverlayStateMessage {\n type: 'OVERLAY_STATE'\n open: boolean\n}\n\n/** Ask the host to open ANOTHER component in a central modal, above everything\n * this frame could reach on its own. The host answers with MODAL_CLOSED\n * carrying the same `requestId`. */\nexport interface OpenModalMessage {\n type: 'OPEN_MODAL'\n /** Correlates the eventual MODAL_CLOSED. Generated by the opener. */\n requestId: string\n /** Slug of the component to mount inside the modal. */\n componentSlug: string\n /** Props for that component (already literal values — no Liquid). */\n props?: Record<string, unknown>\n /** Optional modal heading. */\n title?: string\n}\n\n/** Posted by the component INSIDE a host modal to close it with a value. The\n * `requestId` is the one INIT carried as `modalRequestId`. */\nexport interface ModalResultMessage {\n type: 'MODAL_RESULT'\n requestId: string\n result?: unknown\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 | OverlayStateMessage\n | OpenModalMessage\n | ModalResultMessage\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"]}
1
+ {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";AAUO,IAAM,cAAA,GAAiB;AAuBvB,IAAM,yBAAA,GAA4B;AAgLlC,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-2EAOQNQB.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\n/**\n * z-index the component iframe is promoted to while one of its own overlays\n * (modal, popover, menu, select, tooltip) is open. The iframe goes\n * `position: fixed; inset: 0` at this z so the overlay — which portals to the\n * IFRAME's body and would otherwise clip at the frame's box — can paint over\n * the rest of the page.\n *\n * Host z ladder this slots into:\n * 50 @proteos/ui Modal / Tooltip / ImageLightbox (default tier)\n * 1000+ full-page panel stack (scrim 1000, panels 1001+n)\n * 1090 peek scrim 1100 peek panel, ask-proteos window\n * 1150 ← THIS\n * 1200 menu popover, command palette, action dialog, component modal\n * 1300 select popover\n *\n * Above the peek/full-page surfaces a component can live on, below the global\n * host chrome. Note the cap: inside a peek (a `fixed` + z-index ancestor) the\n * promoted iframe paints within that 1100 stacking context — it covers the\n * peek's own content and everything under it, but host chrome at 1200+ still\n * wins. That is the intended layering, not a bug.\n */\nexport const COMPONENT_OVERLAY_Z_INDEX = 1150\n\n/** Viewport-relative box of the iframe's in-flow placeholder, in CSS px. */\nexport interface OverlayRect {\n top: number\n left: number\n width: number\n height: number\n}\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 * Empty string in public mode (`isPublic: true`). */\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 /** PUBLIC mode: the component renders on an unauthenticated public page.\n * The shell fetches the bundle from the public endpoint (no bearer) and\n * injects a restricted sdk — only `functions.actions.invokePublic` reaches\n * the platform. Requires `orgId`. */\n isPublic?: boolean\n /** Org id for public mode — public endpoints carry the org in the path\n * because there is no token to scope from. */\n orgId?: string\n /** Set when this frame is the CONTENT of a host component modal (opened by\n * another component via OPEN_MODAL). The component reads it through\n * `useModalHost()` and closes with a result by posting MODAL_RESULT with\n * this id. Absent on ordinary page-hosted frames. */\n modalRequestId?: string\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\n/** Where the iframe's in-flow box sits in the host viewport. Sent while the\n * frame is promoted (OVERLAY_STATE open) so the runtime can keep its content\n * parked at the original rect while the iframe itself covers the viewport —\n * and re-sent when the host window resizes under an open overlay. */\nexport interface OverlayRectMessage {\n type: 'OVERLAY_RECT'\n rect: OverlayRect\n}\n\n/** Resolution of an OPEN_MODAL request: the host modal closed. `result` is the\n * value the modal's component passed to MODAL_RESULT, and is absent when the\n * modal was dismissed (backdrop / Esc / ×). */\nexport interface ModalClosedMessage {\n type: 'MODAL_CLOSED'\n requestId: string\n result?: unknown\n}\n\nexport type HostMessage =\n | InitMessage\n | AuthRefreshMessage\n | DataInvalidateMessage\n | OverlayRectMessage\n | ModalClosedMessage\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\n/** The runtime has (or no longer has) an overlay open and needs the host to\n * promote (or restore) the iframe. See {@link COMPONENT_OVERLAY_Z_INDEX}.\n *\n * Same-origin today, so the runtime applies the promotion styles to its own\n * `window.frameElement` synchronously (pre-paint, no flicker) and this message\n * is the host's cue to MIRROR that state into React — gate RESIZE, hold the\n * placeholder height, start posting OVERLAY_RECT. When components move to a\n * dedicated origin the runtime can no longer touch the frame and this message\n * becomes the actuation instead; the runtime hides its overlay until the\n * answering OVERLAY_RECT arrives. */\nexport interface OverlayStateMessage {\n type: 'OVERLAY_STATE'\n open: boolean\n}\n\n/** Ask the host to open ANOTHER component in a central modal, above everything\n * this frame could reach on its own. The host answers with MODAL_CLOSED\n * carrying the same `requestId`. */\nexport interface OpenModalMessage {\n type: 'OPEN_MODAL'\n /** Correlates the eventual MODAL_CLOSED. Generated by the opener. */\n requestId: string\n /** Slug of the component to mount inside the modal. */\n componentSlug: string\n /** Props for that component (already literal values — no Liquid). */\n props?: Record<string, unknown>\n /** Optional modal heading. */\n title?: string\n}\n\n/** Escape was pressed with focus inside the iframe, and nothing in the runtime\n * consumed it.\n *\n * Keyboard events don't cross the iframe boundary, and react-aria binds its\n * Escape handling to the overlay element in its own React tree — so a\n * host-rendered dialog CANNOT see Escape once the user has clicked into a\n * component. The runtime forwards it so the host can dismiss on the user's\n * behalf. Not sent while the runtime has its own overlay open: that overlay\n * owns Escape. */\nexport interface EscapePressedMessage {\n type: 'ESCAPE_PRESSED'\n}\n\n/** Posted by the component INSIDE a host modal to close it with a value. The\n * `requestId` is the one INIT carried as `modalRequestId`. */\nexport interface ModalResultMessage {\n type: 'MODAL_RESULT'\n requestId: string\n result?: unknown\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 | OverlayStateMessage\n | OpenModalMessage\n | ModalResultMessage\n | EscapePressedMessage\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"]}
@@ -14,5 +14,5 @@ exports.COMPONENT_OVERLAY_Z_INDEX = COMPONENT_OVERLAY_Z_INDEX;
14
14
  exports.MESSAGE_SOURCE = MESSAGE_SOURCE;
15
15
  exports.isHostMessage = isHostMessage;
16
16
  exports.isRuntimeMessage = isRuntimeMessage;
17
- //# sourceMappingURL=chunk-6WN2QCSK.cjs.map
18
- //# sourceMappingURL=chunk-6WN2QCSK.cjs.map
17
+ //# sourceMappingURL=chunk-P4MKRWPA.cjs.map
18
+ //# sourceMappingURL=chunk-P4MKRWPA.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";;;AAUO,IAAM,cAAA,GAAiB;AAuBvB,IAAM,yBAAA,GAA4B;AAkKlC,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-6WN2QCSK.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\n/**\n * z-index the component iframe is promoted to while one of its own overlays\n * (modal, popover, menu, select, tooltip) is open. The iframe goes\n * `position: fixed; inset: 0` at this z so the overlay — which portals to the\n * IFRAME's body and would otherwise clip at the frame's box — can paint over\n * the rest of the page.\n *\n * Host z ladder this slots into:\n * 50 @proteos/ui Modal / Tooltip / ImageLightbox (default tier)\n * 1000+ full-page panel stack (scrim 1000, panels 1001+n)\n * 1090 peek scrim 1100 peek panel, ask-proteos window\n * 1150 ← THIS\n * 1200 menu popover, command palette, action dialog, component modal\n * 1300 select popover\n *\n * Above the peek/full-page surfaces a component can live on, below the global\n * host chrome. Note the cap: inside a peek (a `fixed` + z-index ancestor) the\n * promoted iframe paints within that 1100 stacking context — it covers the\n * peek's own content and everything under it, but host chrome at 1200+ still\n * wins. That is the intended layering, not a bug.\n */\nexport const COMPONENT_OVERLAY_Z_INDEX = 1150\n\n/** Viewport-relative box of the iframe's in-flow placeholder, in CSS px. */\nexport interface OverlayRect {\n top: number\n left: number\n width: number\n height: number\n}\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 * Empty string in public mode (`isPublic: true`). */\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 /** PUBLIC mode: the component renders on an unauthenticated public page.\n * The shell fetches the bundle from the public endpoint (no bearer) and\n * injects a restricted sdk — only `functions.actions.invokePublic` reaches\n * the platform. Requires `orgId`. */\n isPublic?: boolean\n /** Org id for public mode — public endpoints carry the org in the path\n * because there is no token to scope from. */\n orgId?: string\n /** Set when this frame is the CONTENT of a host component modal (opened by\n * another component via OPEN_MODAL). The component reads it through\n * `useModalHost()` and closes with a result by posting MODAL_RESULT with\n * this id. Absent on ordinary page-hosted frames. */\n modalRequestId?: string\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\n/** Where the iframe's in-flow box sits in the host viewport. Sent while the\n * frame is promoted (OVERLAY_STATE open) so the runtime can keep its content\n * parked at the original rect while the iframe itself covers the viewport —\n * and re-sent when the host window resizes under an open overlay. */\nexport interface OverlayRectMessage {\n type: 'OVERLAY_RECT'\n rect: OverlayRect\n}\n\n/** Resolution of an OPEN_MODAL request: the host modal closed. `result` is the\n * value the modal's component passed to MODAL_RESULT, and is absent when the\n * modal was dismissed (backdrop / Esc / ×). */\nexport interface ModalClosedMessage {\n type: 'MODAL_CLOSED'\n requestId: string\n result?: unknown\n}\n\nexport type HostMessage =\n | InitMessage\n | AuthRefreshMessage\n | DataInvalidateMessage\n | OverlayRectMessage\n | ModalClosedMessage\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\n/** The runtime has (or no longer has) an overlay open and needs the host to\n * promote (or restore) the iframe. See {@link COMPONENT_OVERLAY_Z_INDEX}.\n *\n * Same-origin today, so the runtime applies the promotion styles to its own\n * `window.frameElement` synchronously (pre-paint, no flicker) and this message\n * is the host's cue to MIRROR that state into React — gate RESIZE, hold the\n * placeholder height, start posting OVERLAY_RECT. When components move to a\n * dedicated origin the runtime can no longer touch the frame and this message\n * becomes the actuation instead; the runtime hides its overlay until the\n * answering OVERLAY_RECT arrives. */\nexport interface OverlayStateMessage {\n type: 'OVERLAY_STATE'\n open: boolean\n}\n\n/** Ask the host to open ANOTHER component in a central modal, above everything\n * this frame could reach on its own. The host answers with MODAL_CLOSED\n * carrying the same `requestId`. */\nexport interface OpenModalMessage {\n type: 'OPEN_MODAL'\n /** Correlates the eventual MODAL_CLOSED. Generated by the opener. */\n requestId: string\n /** Slug of the component to mount inside the modal. */\n componentSlug: string\n /** Props for that component (already literal values — no Liquid). */\n props?: Record<string, unknown>\n /** Optional modal heading. */\n title?: string\n}\n\n/** Posted by the component INSIDE a host modal to close it with a value. The\n * `requestId` is the one INIT carried as `modalRequestId`. */\nexport interface ModalResultMessage {\n type: 'MODAL_RESULT'\n requestId: string\n result?: unknown\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 | OverlayStateMessage\n | OpenModalMessage\n | ModalResultMessage\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"]}
1
+ {"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":";;;AAUO,IAAM,cAAA,GAAiB;AAuBvB,IAAM,yBAAA,GAA4B;AAgLlC,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-P4MKRWPA.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\n/**\n * z-index the component iframe is promoted to while one of its own overlays\n * (modal, popover, menu, select, tooltip) is open. The iframe goes\n * `position: fixed; inset: 0` at this z so the overlay — which portals to the\n * IFRAME's body and would otherwise clip at the frame's box — can paint over\n * the rest of the page.\n *\n * Host z ladder this slots into:\n * 50 @proteos/ui Modal / Tooltip / ImageLightbox (default tier)\n * 1000+ full-page panel stack (scrim 1000, panels 1001+n)\n * 1090 peek scrim 1100 peek panel, ask-proteos window\n * 1150 ← THIS\n * 1200 menu popover, command palette, action dialog, component modal\n * 1300 select popover\n *\n * Above the peek/full-page surfaces a component can live on, below the global\n * host chrome. Note the cap: inside a peek (a `fixed` + z-index ancestor) the\n * promoted iframe paints within that 1100 stacking context — it covers the\n * peek's own content and everything under it, but host chrome at 1200+ still\n * wins. That is the intended layering, not a bug.\n */\nexport const COMPONENT_OVERLAY_Z_INDEX = 1150\n\n/** Viewport-relative box of the iframe's in-flow placeholder, in CSS px. */\nexport interface OverlayRect {\n top: number\n left: number\n width: number\n height: number\n}\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 * Empty string in public mode (`isPublic: true`). */\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 /** PUBLIC mode: the component renders on an unauthenticated public page.\n * The shell fetches the bundle from the public endpoint (no bearer) and\n * injects a restricted sdk — only `functions.actions.invokePublic` reaches\n * the platform. Requires `orgId`. */\n isPublic?: boolean\n /** Org id for public mode — public endpoints carry the org in the path\n * because there is no token to scope from. */\n orgId?: string\n /** Set when this frame is the CONTENT of a host component modal (opened by\n * another component via OPEN_MODAL). The component reads it through\n * `useModalHost()` and closes with a result by posting MODAL_RESULT with\n * this id. Absent on ordinary page-hosted frames. */\n modalRequestId?: string\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\n/** Where the iframe's in-flow box sits in the host viewport. Sent while the\n * frame is promoted (OVERLAY_STATE open) so the runtime can keep its content\n * parked at the original rect while the iframe itself covers the viewport —\n * and re-sent when the host window resizes under an open overlay. */\nexport interface OverlayRectMessage {\n type: 'OVERLAY_RECT'\n rect: OverlayRect\n}\n\n/** Resolution of an OPEN_MODAL request: the host modal closed. `result` is the\n * value the modal's component passed to MODAL_RESULT, and is absent when the\n * modal was dismissed (backdrop / Esc / ×). */\nexport interface ModalClosedMessage {\n type: 'MODAL_CLOSED'\n requestId: string\n result?: unknown\n}\n\nexport type HostMessage =\n | InitMessage\n | AuthRefreshMessage\n | DataInvalidateMessage\n | OverlayRectMessage\n | ModalClosedMessage\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\n/** The runtime has (or no longer has) an overlay open and needs the host to\n * promote (or restore) the iframe. See {@link COMPONENT_OVERLAY_Z_INDEX}.\n *\n * Same-origin today, so the runtime applies the promotion styles to its own\n * `window.frameElement` synchronously (pre-paint, no flicker) and this message\n * is the host's cue to MIRROR that state into React — gate RESIZE, hold the\n * placeholder height, start posting OVERLAY_RECT. When components move to a\n * dedicated origin the runtime can no longer touch the frame and this message\n * becomes the actuation instead; the runtime hides its overlay until the\n * answering OVERLAY_RECT arrives. */\nexport interface OverlayStateMessage {\n type: 'OVERLAY_STATE'\n open: boolean\n}\n\n/** Ask the host to open ANOTHER component in a central modal, above everything\n * this frame could reach on its own. The host answers with MODAL_CLOSED\n * carrying the same `requestId`. */\nexport interface OpenModalMessage {\n type: 'OPEN_MODAL'\n /** Correlates the eventual MODAL_CLOSED. Generated by the opener. */\n requestId: string\n /** Slug of the component to mount inside the modal. */\n componentSlug: string\n /** Props for that component (already literal values — no Liquid). */\n props?: Record<string, unknown>\n /** Optional modal heading. */\n title?: string\n}\n\n/** Escape was pressed with focus inside the iframe, and nothing in the runtime\n * consumed it.\n *\n * Keyboard events don't cross the iframe boundary, and react-aria binds its\n * Escape handling to the overlay element in its own React tree — so a\n * host-rendered dialog CANNOT see Escape once the user has clicked into a\n * component. The runtime forwards it so the host can dismiss on the user's\n * behalf. Not sent while the runtime has its own overlay open: that overlay\n * owns Escape. */\nexport interface EscapePressedMessage {\n type: 'ESCAPE_PRESSED'\n}\n\n/** Posted by the component INSIDE a host modal to close it with a value. The\n * `requestId` is the one INIT carried as `modalRequestId`. */\nexport interface ModalResultMessage {\n type: 'MODAL_RESULT'\n requestId: string\n result?: unknown\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 | OverlayStateMessage\n | OpenModalMessage\n | ModalResultMessage\n | EscapePressedMessage\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 CHANGED
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var chunk6WN2QCSK_cjs = require('./chunk-6WN2QCSK.cjs');
3
+ var chunkP4MKRWPA_cjs = require('./chunk-P4MKRWPA.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
7
  var RuntimeContext = react.createContext(null);
8
8
  function postNavigate(to) {
9
- const envelope = { source: chunk6WN2QCSK_cjs.MESSAGE_SOURCE, type: "NAVIGATE", to };
9
+ const envelope = { source: chunkP4MKRWPA_cjs.MESSAGE_SOURCE, type: "NAVIGATE", to };
10
10
  window.parent?.postMessage(envelope, "*");
11
11
  }
12
12
  function postOpenPeek(to) {
13
- const envelope = { source: chunk6WN2QCSK_cjs.MESSAGE_SOURCE, type: "OPEN_PEEK", to };
13
+ const envelope = { source: chunkP4MKRWPA_cjs.MESSAGE_SOURCE, type: "OPEN_PEEK", to };
14
14
  window.parent?.postMessage(envelope, "*");
15
15
  }
16
16
  function navigate(to, options) {
@@ -24,7 +24,7 @@ function ensureModalListener() {
24
24
  modalListenerAttached = true;
25
25
  window.addEventListener("message", (event) => {
26
26
  const data = event.data;
27
- if (!chunk6WN2QCSK_cjs.isHostMessage(data) || data.type !== "MODAL_CLOSED") return;
27
+ if (!chunkP4MKRWPA_cjs.isHostMessage(data) || data.type !== "MODAL_CLOSED") return;
28
28
  const resolve = pendingModals.get(data.requestId);
29
29
  if (!resolve) return;
30
30
  pendingModals.delete(data.requestId);
@@ -41,7 +41,7 @@ function openModal(componentSlug, props, options) {
41
41
  ensureModalListener();
42
42
  const requestId = newRequestId();
43
43
  const envelope = {
44
- source: chunk6WN2QCSK_cjs.MESSAGE_SOURCE,
44
+ source: chunkP4MKRWPA_cjs.MESSAGE_SOURCE,
45
45
  type: "OPEN_MODAL",
46
46
  requestId,
47
47
  componentSlug,
@@ -55,7 +55,7 @@ function openModal(componentSlug, props, options) {
55
55
  }
56
56
  function postModalResult(requestId, result) {
57
57
  const envelope = {
58
- source: chunk6WN2QCSK_cjs.MESSAGE_SOURCE,
58
+ source: chunkP4MKRWPA_cjs.MESSAGE_SOURCE,
59
59
  type: "MODAL_RESULT",
60
60
  requestId,
61
61
  ...result !== void 0 ? { result } : {}
@@ -169,19 +169,19 @@ function useFillViewportHeight(options = {}) {
169
169
 
170
170
  Object.defineProperty(exports, "COMPONENT_OVERLAY_Z_INDEX", {
171
171
  enumerable: true,
172
- get: function () { return chunk6WN2QCSK_cjs.COMPONENT_OVERLAY_Z_INDEX; }
172
+ get: function () { return chunkP4MKRWPA_cjs.COMPONENT_OVERLAY_Z_INDEX; }
173
173
  });
174
174
  Object.defineProperty(exports, "MESSAGE_SOURCE", {
175
175
  enumerable: true,
176
- get: function () { return chunk6WN2QCSK_cjs.MESSAGE_SOURCE; }
176
+ get: function () { return chunkP4MKRWPA_cjs.MESSAGE_SOURCE; }
177
177
  });
178
178
  Object.defineProperty(exports, "isHostMessage", {
179
179
  enumerable: true,
180
- get: function () { return chunk6WN2QCSK_cjs.isHostMessage; }
180
+ get: function () { return chunkP4MKRWPA_cjs.isHostMessage; }
181
181
  });
182
182
  Object.defineProperty(exports, "isRuntimeMessage", {
183
183
  enumerable: true,
184
- get: function () { return chunk6WN2QCSK_cjs.isRuntimeMessage; }
184
+ get: function () { return chunkP4MKRWPA_cjs.isRuntimeMessage; }
185
185
  });
186
186
  exports.RuntimeProvider = RuntimeProvider;
187
187
  exports.useApiBaseUrl = useApiBaseUrl;
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { AccountClient, AgentClient, ConversationClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
4
  import { PageContext } from './protocol.cjs';
5
- export { AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, ModalClosedMessage, ModalResultMessage, NavigateMessage, OpenModalMessage, OpenPeekMessage, OverlayRect, OverlayRectMessage, OverlayStateMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.cjs';
5
+ export { AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, DataInvalidateMessage, Envelope, ErrorMessage, EscapePressedMessage, HostMessage, InitMessage, MESSAGE_SOURCE, ModalClosedMessage, ModalResultMessage, NavigateMessage, OpenModalMessage, OpenPeekMessage, OverlayRect, OverlayRectMessage, OverlayStateMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.cjs';
6
6
 
7
7
  /** Options for {@link RuntimeContextValue.navigate}. */
8
8
  interface NavigateOptions {
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { AccountClient, AgentClient, ConversationClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
4
  import { PageContext } from './protocol.js';
5
- export { AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, ModalClosedMessage, ModalResultMessage, NavigateMessage, OpenModalMessage, OpenPeekMessage, OverlayRect, OverlayRectMessage, OverlayStateMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.js';
5
+ export { AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, DataInvalidateMessage, Envelope, ErrorMessage, EscapePressedMessage, HostMessage, InitMessage, MESSAGE_SOURCE, ModalClosedMessage, ModalResultMessage, NavigateMessage, OpenModalMessage, OpenPeekMessage, OverlayRect, OverlayRectMessage, OverlayStateMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.js';
6
6
 
7
7
  /** Options for {@link RuntimeContextValue.navigate}. */
8
8
  interface NavigateOptions {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { MESSAGE_SOURCE, isHostMessage } from './chunk-FSPIGFIQ.js';
2
- export { COMPONENT_OVERLAY_Z_INDEX, MESSAGE_SOURCE, isHostMessage, isRuntimeMessage } from './chunk-FSPIGFIQ.js';
1
+ import { MESSAGE_SOURCE, isHostMessage } from './chunk-2EAOQNQB.js';
2
+ export { COMPONENT_OVERLAY_Z_INDEX, MESSAGE_SOURCE, isHostMessage, isRuntimeMessage } from './chunk-2EAOQNQB.js';
3
3
  import { createContext, useMemo, useContext, useCallback, useState, useEffect } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
package/dist/protocol.cjs CHANGED
@@ -1,24 +1,24 @@
1
1
  'use strict';
2
2
 
3
- var chunk6WN2QCSK_cjs = require('./chunk-6WN2QCSK.cjs');
3
+ var chunkP4MKRWPA_cjs = require('./chunk-P4MKRWPA.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "COMPONENT_OVERLAY_Z_INDEX", {
8
8
  enumerable: true,
9
- get: function () { return chunk6WN2QCSK_cjs.COMPONENT_OVERLAY_Z_INDEX; }
9
+ get: function () { return chunkP4MKRWPA_cjs.COMPONENT_OVERLAY_Z_INDEX; }
10
10
  });
11
11
  Object.defineProperty(exports, "MESSAGE_SOURCE", {
12
12
  enumerable: true,
13
- get: function () { return chunk6WN2QCSK_cjs.MESSAGE_SOURCE; }
13
+ get: function () { return chunkP4MKRWPA_cjs.MESSAGE_SOURCE; }
14
14
  });
15
15
  Object.defineProperty(exports, "isHostMessage", {
16
16
  enumerable: true,
17
- get: function () { return chunk6WN2QCSK_cjs.isHostMessage; }
17
+ get: function () { return chunkP4MKRWPA_cjs.isHostMessage; }
18
18
  });
19
19
  Object.defineProperty(exports, "isRuntimeMessage", {
20
20
  enumerable: true,
21
- get: function () { return chunk6WN2QCSK_cjs.isRuntimeMessage; }
21
+ get: function () { return chunkP4MKRWPA_cjs.isRuntimeMessage; }
22
22
  });
23
23
  //# sourceMappingURL=protocol.cjs.map
24
24
  //# sourceMappingURL=protocol.cjs.map
@@ -134,6 +134,18 @@ interface OpenModalMessage {
134
134
  /** Optional modal heading. */
135
135
  title?: string;
136
136
  }
137
+ /** Escape was pressed with focus inside the iframe, and nothing in the runtime
138
+ * consumed it.
139
+ *
140
+ * Keyboard events don't cross the iframe boundary, and react-aria binds its
141
+ * Escape handling to the overlay element in its own React tree — so a
142
+ * host-rendered dialog CANNOT see Escape once the user has clicked into a
143
+ * component. The runtime forwards it so the host can dismiss on the user's
144
+ * behalf. Not sent while the runtime has its own overlay open: that overlay
145
+ * owns Escape. */
146
+ interface EscapePressedMessage {
147
+ type: 'ESCAPE_PRESSED';
148
+ }
137
149
  /** Posted by the component INSIDE a host modal to close it with a value. The
138
150
  * `requestId` is the one INIT carried as `modalRequestId`. */
139
151
  interface ModalResultMessage {
@@ -146,11 +158,11 @@ interface ErrorMessage {
146
158
  message: string;
147
159
  stack?: string;
148
160
  }
149
- type RuntimeMessage = ReadyMessage | ResizeMessage | NavigateMessage | OpenPeekMessage | OverlayStateMessage | OpenModalMessage | ModalResultMessage | ErrorMessage;
161
+ type RuntimeMessage = ReadyMessage | ResizeMessage | NavigateMessage | OpenPeekMessage | OverlayStateMessage | OpenModalMessage | ModalResultMessage | EscapePressedMessage | ErrorMessage;
150
162
  type Envelope<T> = T & {
151
163
  source: typeof MESSAGE_SOURCE;
152
164
  };
153
165
  declare function isHostMessage(data: unknown): data is Envelope<HostMessage>;
154
166
  declare function isRuntimeMessage(data: unknown): data is Envelope<RuntimeMessage>;
155
167
 
156
- export { type AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, type DataInvalidateMessage, type Envelope, type ErrorMessage, type HostMessage, type InitMessage, MESSAGE_SOURCE, type ModalClosedMessage, type ModalResultMessage, type NavigateMessage, type OpenModalMessage, type OpenPeekMessage, type OverlayRect, type OverlayRectMessage, type OverlayStateMessage, type PageContext, type ReadyMessage, type ResizeMessage, type RuntimeMessage, isHostMessage, isRuntimeMessage };
168
+ export { type AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, type DataInvalidateMessage, type Envelope, type ErrorMessage, type EscapePressedMessage, type HostMessage, type InitMessage, MESSAGE_SOURCE, type ModalClosedMessage, type ModalResultMessage, type NavigateMessage, type OpenModalMessage, type OpenPeekMessage, type OverlayRect, type OverlayRectMessage, type OverlayStateMessage, type PageContext, type ReadyMessage, type ResizeMessage, type RuntimeMessage, isHostMessage, isRuntimeMessage };
@@ -134,6 +134,18 @@ interface OpenModalMessage {
134
134
  /** Optional modal heading. */
135
135
  title?: string;
136
136
  }
137
+ /** Escape was pressed with focus inside the iframe, and nothing in the runtime
138
+ * consumed it.
139
+ *
140
+ * Keyboard events don't cross the iframe boundary, and react-aria binds its
141
+ * Escape handling to the overlay element in its own React tree — so a
142
+ * host-rendered dialog CANNOT see Escape once the user has clicked into a
143
+ * component. The runtime forwards it so the host can dismiss on the user's
144
+ * behalf. Not sent while the runtime has its own overlay open: that overlay
145
+ * owns Escape. */
146
+ interface EscapePressedMessage {
147
+ type: 'ESCAPE_PRESSED';
148
+ }
137
149
  /** Posted by the component INSIDE a host modal to close it with a value. The
138
150
  * `requestId` is the one INIT carried as `modalRequestId`. */
139
151
  interface ModalResultMessage {
@@ -146,11 +158,11 @@ interface ErrorMessage {
146
158
  message: string;
147
159
  stack?: string;
148
160
  }
149
- type RuntimeMessage = ReadyMessage | ResizeMessage | NavigateMessage | OpenPeekMessage | OverlayStateMessage | OpenModalMessage | ModalResultMessage | ErrorMessage;
161
+ type RuntimeMessage = ReadyMessage | ResizeMessage | NavigateMessage | OpenPeekMessage | OverlayStateMessage | OpenModalMessage | ModalResultMessage | EscapePressedMessage | ErrorMessage;
150
162
  type Envelope<T> = T & {
151
163
  source: typeof MESSAGE_SOURCE;
152
164
  };
153
165
  declare function isHostMessage(data: unknown): data is Envelope<HostMessage>;
154
166
  declare function isRuntimeMessage(data: unknown): data is Envelope<RuntimeMessage>;
155
167
 
156
- export { type AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, type DataInvalidateMessage, type Envelope, type ErrorMessage, type HostMessage, type InitMessage, MESSAGE_SOURCE, type ModalClosedMessage, type ModalResultMessage, type NavigateMessage, type OpenModalMessage, type OpenPeekMessage, type OverlayRect, type OverlayRectMessage, type OverlayStateMessage, type PageContext, type ReadyMessage, type ResizeMessage, type RuntimeMessage, isHostMessage, isRuntimeMessage };
168
+ export { type AuthRefreshMessage, COMPONENT_OVERLAY_Z_INDEX, type DataInvalidateMessage, type Envelope, type ErrorMessage, type EscapePressedMessage, type HostMessage, type InitMessage, MESSAGE_SOURCE, type ModalClosedMessage, type ModalResultMessage, type NavigateMessage, type OpenModalMessage, type OpenPeekMessage, type OverlayRect, type OverlayRectMessage, type OverlayStateMessage, type PageContext, type ReadyMessage, type ResizeMessage, type RuntimeMessage, isHostMessage, isRuntimeMessage };
package/dist/protocol.js CHANGED
@@ -1,3 +1,3 @@
1
- export { COMPONENT_OVERLAY_Z_INDEX, MESSAGE_SOURCE, isHostMessage, isRuntimeMessage } from './chunk-FSPIGFIQ.js';
1
+ export { COMPONENT_OVERLAY_Z_INDEX, MESSAGE_SOURCE, isHostMessage, isRuntimeMessage } from './chunk-2EAOQNQB.js';
2
2
  //# sourceMappingURL=protocol.js.map
3
3
  //# sourceMappingURL=protocol.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteos/component-sdk",
3
- "version": "0.42.0",
3
+ "version": "0.42.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Typed runtime hooks for authoring Proteos custom components — the SDK you import inside a component bundle.",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  "src"
43
43
  ],
44
44
  "dependencies": {
45
- "@proteos/sdk": "^0.42.0"
45
+ "@proteos/sdk": "^0.42.2"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@tanstack/react-query": ">=5.0.0",
@@ -60,8 +60,8 @@
60
60
  "tsup": "^8.3.0",
61
61
  "typescript": "^6.0.3",
62
62
  "vitest": "^3.2.4",
63
- "@proteos/tsconfig": "0.0.0",
64
- "@proteos/biome-config": "0.0.0"
63
+ "@proteos/biome-config": "0.0.0",
64
+ "@proteos/tsconfig": "0.0.0"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "tsup",
package/src/index.ts CHANGED
@@ -37,6 +37,7 @@ export {
37
37
  type DataInvalidateMessage,
38
38
  type Envelope,
39
39
  type ErrorMessage,
40
+ type EscapePressedMessage,
40
41
  type HostMessage,
41
42
  type InitMessage,
42
43
  isHostMessage,
package/src/protocol.ts CHANGED
@@ -166,6 +166,19 @@ export interface OpenModalMessage {
166
166
  title?: string
167
167
  }
168
168
 
169
+ /** Escape was pressed with focus inside the iframe, and nothing in the runtime
170
+ * consumed it.
171
+ *
172
+ * Keyboard events don't cross the iframe boundary, and react-aria binds its
173
+ * Escape handling to the overlay element in its own React tree — so a
174
+ * host-rendered dialog CANNOT see Escape once the user has clicked into a
175
+ * component. The runtime forwards it so the host can dismiss on the user's
176
+ * behalf. Not sent while the runtime has its own overlay open: that overlay
177
+ * owns Escape. */
178
+ export interface EscapePressedMessage {
179
+ type: 'ESCAPE_PRESSED'
180
+ }
181
+
169
182
  /** Posted by the component INSIDE a host modal to close it with a value. The
170
183
  * `requestId` is the one INIT carried as `modalRequestId`. */
171
184
  export interface ModalResultMessage {
@@ -188,6 +201,7 @@ export type RuntimeMessage =
188
201
  | OverlayStateMessage
189
202
  | OpenModalMessage
190
203
  | ModalResultMessage
204
+ | EscapePressedMessage
191
205
  | ErrorMessage
192
206
 
193
207
  // Wire envelope: the message plus the source discriminator.