@bootdesk/chat-widget-bridge 0.3.4 → 0.3.6

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.
@@ -121,7 +121,12 @@
121
121
  } catch {
122
122
  }
123
123
  state.iframe.contentWindow.postMessage(
124
- { type: "chat-config", title: opts.title, placeholder: opts.placeholder, theme: { mode: savedTheme } },
124
+ {
125
+ type: "chat-config",
126
+ title: opts.title,
127
+ placeholder: opts.placeholder,
128
+ theme: { mode: savedTheme }
129
+ },
125
130
  "*"
126
131
  );
127
132
  });
@@ -169,8 +174,10 @@
169
174
  if (!state.initialized) return;
170
175
  if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);
171
176
  if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);
172
- if (state.overlay && state.overlay.parentNode) state.overlay.parentNode.removeChild(state.overlay);
173
- if (state.styleEl && state.styleEl.parentNode) state.styleEl.parentNode.removeChild(state.styleEl);
177
+ if (state.overlay && state.overlay.parentNode)
178
+ state.overlay.parentNode.removeChild(state.overlay);
179
+ if (state.styleEl && state.styleEl.parentNode)
180
+ state.styleEl.parentNode.removeChild(state.styleEl);
174
181
  window.removeEventListener("message", handleMessage);
175
182
  state.initialized = false;
176
183
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/embed-chat.js"],"sourcesContent":["(function () {\n \"use strict\";\n\n var DEFAULTS = {\n iframeSrc: \"/chat-iframe\",\n title: \"Chat\",\n placeholder: \"Type a message...\",\n buttonInnerHtml:\n '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>',\n buttonStyle: {\n position: \"fixed\",\n bottom: \"24px\",\n right: \"24px\",\n width: \"56px\",\n height: \"56px\",\n borderRadius: \"50%\",\n border: \"none\",\n background: \"var(--chat-primary, #6366f1)\",\n color: \"#fff\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 4px 16px rgba(0,0,0,0.2)\",\n zIndex: \"2147483646\",\n transition: \"transform 0.2s, opacity 0.2s\",\n },\n overlayStyle: {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,0.3)\",\n zIndex: \"2147483646\",\n opacity: \"0\",\n transition: \"opacity 0.2s\",\n pointerEvents: \"none\",\n },\n };\n\n var state = {\n opts: null,\n button: null,\n iframe: null,\n overlay: null,\n styleEl: null,\n isOpen: false,\n originalViewport: undefined,\n initialized: false,\n };\n\n function mergeStyles(base, overrides) {\n var result = {};\n for (var key in base) result[key] = base[key];\n if (overrides) {\n for (var k in overrides) result[k] = overrides[k];\n }\n return result;\n }\n\n function createButton() {\n var opts = state.opts;\n state.button = document.createElement(\"button\");\n state.button.setAttribute(\"data-embed-chat-btn\", \"\");\n state.button.setAttribute(\"aria-label\", \"Open chat\");\n state.button.setAttribute(\"aria-expanded\", \"false\");\n state.button.innerHTML = opts.buttonInnerHtml;\n Object.assign(state.button.style, mergeStyles(DEFAULTS.buttonStyle, opts.buttonStyle));\n state.button.addEventListener(\"mouseenter\", function () {\n state.button.style.transform = \"scale(1.05)\";\n });\n state.button.addEventListener(\"mouseleave\", function () {\n state.button.style.transform = \"\";\n });\n state.button.addEventListener(\"click\", toggle);\n state.button.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n document.body.appendChild(state.button);\n }\n\n function createOverlay() {\n var opts = state.opts;\n state.overlay = document.createElement(\"div\");\n state.overlay.setAttribute(\"data-embed-chat-overlay\", \"\");\n Object.assign(state.overlay.style, mergeStyles(DEFAULTS.overlayStyle, opts.overlayStyle));\n state.overlay.addEventListener(\"click\", toggle);\n document.body.appendChild(state.overlay);\n }\n\n function createIframe() {\n var opts = state.opts;\n state.iframe = document.createElement(\"iframe\");\n state.iframe.setAttribute(\"data-embed-chat-iframe\", \"\");\n state.iframe.setAttribute(\"title\", \"Chat Widget\");\n state.iframe.setAttribute(\"role\", \"dialog\");\n state.iframe.setAttribute(\"aria-modal\", \"true\");\n state.iframe.setAttribute(\"allow\", \"clipboard-write; microphone\");\n state.iframe.src = opts.iframeSrc;\n Object.assign(state.iframe.style, {\n position: \"fixed\",\n bottom: \"96px\",\n right: \"24px\",\n width: \"420px\",\n height: \"600px\",\n maxWidth: \"calc(100dvw - 48px)\",\n maxHeight: \"calc(100dvh - 120px)\",\n border: \"none\",\n borderRadius: \"16px\",\n boxShadow: \"0 8px 32px rgba(0,0,0,0.15)\",\n zIndex: \"2147483647\",\n opacity: \"0\",\n transform: \"translateY(16px) scale(0.96)\",\n transition: \"opacity 0.2s, transform 0.25s\",\n pointerEvents: \"none\",\n background: \"#fff\",\n });\n document.body.appendChild(state.iframe);\n\n state.iframe.addEventListener(\"load\", function () {\n var savedTheme = \"auto\";\n try {\n var stored = localStorage.getItem(\"chat-theme\");\n if (stored === \"light\" || stored === \"dark\" || stored === \"auto\") savedTheme = stored;\n } catch { /* unavailable */ }\n state.iframe.contentWindow.postMessage(\n { type: \"chat-config\", title: opts.title, placeholder: opts.placeholder, theme: { mode: savedTheme } },\n \"*\",\n );\n });\n }\n\n function toggle() {\n state.isOpen = !state.isOpen;\n var open = state.isOpen;\n\n state.button.setAttribute(\"aria-expanded\", String(open));\n state.iframe.style.opacity = open ? \"1\" : \"0\";\n state.iframe.style.transform = open ? \"translateY(0) scale(1)\" : \"translateY(16px) scale(0.96)\";\n state.iframe.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.overlay.style.opacity = open ? \"1\" : \"0\";\n state.overlay.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.button.style.transform = open ? \"scale(0)\" : \"\";\n state.button.style.opacity = open ? \"0\" : \"1\";\n state.button.style.pointerEvents = open ? \"none\" : \"auto\";\n\n document.body.style.overflow = open ? \"hidden\" : \"\";\n\n if (open) state.iframe.focus();\n }\n\n function handleMessage(event) {\n if (!state.iframe || event.source !== state.iframe.contentWindow) return;\n var data = event.data || {};\n if (data.type === \"chat-message\") {\n console.log(\"[Embed Chat] Message:\", data.text);\n }\n if (data.type === \"chat-close\") {\n toggle();\n }\n if (data.type === \"chat-viewport-config\") {\n var meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) return;\n var current = meta.getAttribute(\"content\") || \"\";\n if (data.content) {\n if (state.originalViewport === undefined) state.originalViewport = current;\n if (!current.includes(data.content)) {\n meta.setAttribute(\"content\", current + (current ? \", \" : \"\") + data.content);\n }\n } else {\n meta.setAttribute(\"content\", state.originalViewport ?? current);\n state.originalViewport = undefined;\n }\n }\n }\n\n function destroy() {\n if (!state.initialized) return;\n if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);\n if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);\n if (state.overlay && state.overlay.parentNode) state.overlay.parentNode.removeChild(state.overlay);\n if (state.styleEl && state.styleEl.parentNode) state.styleEl.parentNode.removeChild(state.styleEl);\n window.removeEventListener(\"message\", handleMessage);\n state.initialized = false;\n }\n\n function _initialize(opts) {\n if (document.querySelector(\"[data-embed-chat-btn]\")) return;\n\n state.opts = {};\n for (var key in DEFAULTS) {\n state.opts[key] = DEFAULTS[key];\n }\n if (opts) {\n for (var k in opts) {\n if (k === \"buttonStyle\" || k === \"overlayStyle\") {\n state.opts[k] = mergeStyles(state.opts[k] || {}, opts[k]);\n } else if (opts[k] !== undefined) {\n state.opts[k] = opts[k];\n }\n }\n }\n\n var style = document.createElement(\"style\");\n style.textContent =\n '@media (max-width: 799px) { [data-embed-chat-iframe] { width: 100dvw !important; height: 100dvh !important; bottom: 0 !important; right: 0 !important; max-width: none !important; max-height: none !important; border-radius: 0 !important; } [data-embed-chat-overlay] { display: none !important; } }';\n document.head.appendChild(style);\n state.styleEl = style;\n\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n state.initialized = true;\n }\n\n function initialize(opts) {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", function () { _initialize(opts); });\n } else {\n _initialize(opts);\n }\n }\n\n window.ChatSDK = { initialize: initialize, destroy: destroy };\n})();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/embed-chat.js"],"sourcesContent":["(function () {\n \"use strict\";\n\n var DEFAULTS = {\n iframeSrc: \"/chat-iframe\",\n title: \"Chat\",\n placeholder: \"Type a message...\",\n buttonInnerHtml:\n '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>',\n buttonStyle: {\n position: \"fixed\",\n bottom: \"24px\",\n right: \"24px\",\n width: \"56px\",\n height: \"56px\",\n borderRadius: \"50%\",\n border: \"none\",\n background: \"var(--chat-primary, #6366f1)\",\n color: \"#fff\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 4px 16px rgba(0,0,0,0.2)\",\n zIndex: \"2147483646\",\n transition: \"transform 0.2s, opacity 0.2s\",\n },\n overlayStyle: {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,0.3)\",\n zIndex: \"2147483646\",\n opacity: \"0\",\n transition: \"opacity 0.2s\",\n pointerEvents: \"none\",\n },\n };\n\n var state = {\n opts: null,\n button: null,\n iframe: null,\n overlay: null,\n styleEl: null,\n isOpen: false,\n originalViewport: undefined,\n initialized: false,\n };\n\n function mergeStyles(base, overrides) {\n var result = {};\n for (var key in base) result[key] = base[key];\n if (overrides) {\n for (var k in overrides) result[k] = overrides[k];\n }\n return result;\n }\n\n function createButton() {\n var opts = state.opts;\n state.button = document.createElement(\"button\");\n state.button.setAttribute(\"data-embed-chat-btn\", \"\");\n state.button.setAttribute(\"aria-label\", \"Open chat\");\n state.button.setAttribute(\"aria-expanded\", \"false\");\n state.button.innerHTML = opts.buttonInnerHtml;\n Object.assign(state.button.style, mergeStyles(DEFAULTS.buttonStyle, opts.buttonStyle));\n state.button.addEventListener(\"mouseenter\", function () {\n state.button.style.transform = \"scale(1.05)\";\n });\n state.button.addEventListener(\"mouseleave\", function () {\n state.button.style.transform = \"\";\n });\n state.button.addEventListener(\"click\", toggle);\n state.button.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n document.body.appendChild(state.button);\n }\n\n function createOverlay() {\n var opts = state.opts;\n state.overlay = document.createElement(\"div\");\n state.overlay.setAttribute(\"data-embed-chat-overlay\", \"\");\n Object.assign(state.overlay.style, mergeStyles(DEFAULTS.overlayStyle, opts.overlayStyle));\n state.overlay.addEventListener(\"click\", toggle);\n document.body.appendChild(state.overlay);\n }\n\n function createIframe() {\n var opts = state.opts;\n state.iframe = document.createElement(\"iframe\");\n state.iframe.setAttribute(\"data-embed-chat-iframe\", \"\");\n state.iframe.setAttribute(\"title\", \"Chat Widget\");\n state.iframe.setAttribute(\"role\", \"dialog\");\n state.iframe.setAttribute(\"aria-modal\", \"true\");\n state.iframe.setAttribute(\"allow\", \"clipboard-write; microphone\");\n state.iframe.src = opts.iframeSrc;\n Object.assign(state.iframe.style, {\n position: \"fixed\",\n bottom: \"96px\",\n right: \"24px\",\n width: \"420px\",\n height: \"600px\",\n maxWidth: \"calc(100dvw - 48px)\",\n maxHeight: \"calc(100dvh - 120px)\",\n border: \"none\",\n borderRadius: \"16px\",\n boxShadow: \"0 8px 32px rgba(0,0,0,0.15)\",\n zIndex: \"2147483647\",\n opacity: \"0\",\n transform: \"translateY(16px) scale(0.96)\",\n transition: \"opacity 0.2s, transform 0.25s\",\n pointerEvents: \"none\",\n background: \"#fff\",\n });\n document.body.appendChild(state.iframe);\n\n state.iframe.addEventListener(\"load\", function () {\n var savedTheme = \"auto\";\n try {\n var stored = localStorage.getItem(\"chat-theme\");\n if (stored === \"light\" || stored === \"dark\" || stored === \"auto\") savedTheme = stored;\n } catch {\n /* unavailable */\n }\n state.iframe.contentWindow.postMessage(\n {\n type: \"chat-config\",\n title: opts.title,\n placeholder: opts.placeholder,\n theme: { mode: savedTheme },\n },\n \"*\",\n );\n });\n }\n\n function toggle() {\n state.isOpen = !state.isOpen;\n var open = state.isOpen;\n\n state.button.setAttribute(\"aria-expanded\", String(open));\n state.iframe.style.opacity = open ? \"1\" : \"0\";\n state.iframe.style.transform = open ? \"translateY(0) scale(1)\" : \"translateY(16px) scale(0.96)\";\n state.iframe.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.overlay.style.opacity = open ? \"1\" : \"0\";\n state.overlay.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.button.style.transform = open ? \"scale(0)\" : \"\";\n state.button.style.opacity = open ? \"0\" : \"1\";\n state.button.style.pointerEvents = open ? \"none\" : \"auto\";\n\n document.body.style.overflow = open ? \"hidden\" : \"\";\n\n if (open) state.iframe.focus();\n }\n\n function handleMessage(event) {\n if (!state.iframe || event.source !== state.iframe.contentWindow) return;\n var data = event.data || {};\n if (data.type === \"chat-message\") {\n console.log(\"[Embed Chat] Message:\", data.text);\n }\n if (data.type === \"chat-close\") {\n toggle();\n }\n if (data.type === \"chat-viewport-config\") {\n var meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) return;\n var current = meta.getAttribute(\"content\") || \"\";\n if (data.content) {\n if (state.originalViewport === undefined) state.originalViewport = current;\n if (!current.includes(data.content)) {\n meta.setAttribute(\"content\", current + (current ? \", \" : \"\") + data.content);\n }\n } else {\n meta.setAttribute(\"content\", state.originalViewport ?? current);\n state.originalViewport = undefined;\n }\n }\n }\n\n function destroy() {\n if (!state.initialized) return;\n if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);\n if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);\n if (state.overlay && state.overlay.parentNode)\n state.overlay.parentNode.removeChild(state.overlay);\n if (state.styleEl && state.styleEl.parentNode)\n state.styleEl.parentNode.removeChild(state.styleEl);\n window.removeEventListener(\"message\", handleMessage);\n state.initialized = false;\n }\n\n function _initialize(opts) {\n if (document.querySelector(\"[data-embed-chat-btn]\")) return;\n\n state.opts = {};\n for (var key in DEFAULTS) {\n state.opts[key] = DEFAULTS[key];\n }\n if (opts) {\n for (var k in opts) {\n if (k === \"buttonStyle\" || k === \"overlayStyle\") {\n state.opts[k] = mergeStyles(state.opts[k] || {}, opts[k]);\n } else if (opts[k] !== undefined) {\n state.opts[k] = opts[k];\n }\n }\n }\n\n var style = document.createElement(\"style\");\n style.textContent =\n \"@media (max-width: 799px) { [data-embed-chat-iframe] { width: 100dvw !important; height: 100dvh !important; bottom: 0 !important; right: 0 !important; max-width: none !important; max-height: none !important; border-radius: 0 !important; } [data-embed-chat-overlay] { display: none !important; } }\";\n document.head.appendChild(style);\n state.styleEl = style;\n\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n state.initialized = true;\n }\n\n function initialize(opts) {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", function () {\n _initialize(opts);\n });\n } else {\n _initialize(opts);\n }\n }\n\n window.ChatSDK = { initialize: initialize, destroy: destroy };\n})();\n"],"mappings":"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","names":[]}
@@ -119,7 +119,12 @@
119
119
  } catch {
120
120
  }
121
121
  state.iframe.contentWindow.postMessage(
122
- { type: "chat-config", title: opts.title, placeholder: opts.placeholder, theme: { mode: savedTheme } },
122
+ {
123
+ type: "chat-config",
124
+ title: opts.title,
125
+ placeholder: opts.placeholder,
126
+ theme: { mode: savedTheme }
127
+ },
123
128
  "*"
124
129
  );
125
130
  });
@@ -167,8 +172,10 @@
167
172
  if (!state.initialized) return;
168
173
  if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);
169
174
  if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);
170
- if (state.overlay && state.overlay.parentNode) state.overlay.parentNode.removeChild(state.overlay);
171
- if (state.styleEl && state.styleEl.parentNode) state.styleEl.parentNode.removeChild(state.styleEl);
175
+ if (state.overlay && state.overlay.parentNode)
176
+ state.overlay.parentNode.removeChild(state.overlay);
177
+ if (state.styleEl && state.styleEl.parentNode)
178
+ state.styleEl.parentNode.removeChild(state.styleEl);
172
179
  window.removeEventListener("message", handleMessage);
173
180
  state.initialized = false;
174
181
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/embed-chat.js"],"sourcesContent":["(function () {\n \"use strict\";\n\n var DEFAULTS = {\n iframeSrc: \"/chat-iframe\",\n title: \"Chat\",\n placeholder: \"Type a message...\",\n buttonInnerHtml:\n '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>',\n buttonStyle: {\n position: \"fixed\",\n bottom: \"24px\",\n right: \"24px\",\n width: \"56px\",\n height: \"56px\",\n borderRadius: \"50%\",\n border: \"none\",\n background: \"var(--chat-primary, #6366f1)\",\n color: \"#fff\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 4px 16px rgba(0,0,0,0.2)\",\n zIndex: \"2147483646\",\n transition: \"transform 0.2s, opacity 0.2s\",\n },\n overlayStyle: {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,0.3)\",\n zIndex: \"2147483646\",\n opacity: \"0\",\n transition: \"opacity 0.2s\",\n pointerEvents: \"none\",\n },\n };\n\n var state = {\n opts: null,\n button: null,\n iframe: null,\n overlay: null,\n styleEl: null,\n isOpen: false,\n originalViewport: undefined,\n initialized: false,\n };\n\n function mergeStyles(base, overrides) {\n var result = {};\n for (var key in base) result[key] = base[key];\n if (overrides) {\n for (var k in overrides) result[k] = overrides[k];\n }\n return result;\n }\n\n function createButton() {\n var opts = state.opts;\n state.button = document.createElement(\"button\");\n state.button.setAttribute(\"data-embed-chat-btn\", \"\");\n state.button.setAttribute(\"aria-label\", \"Open chat\");\n state.button.setAttribute(\"aria-expanded\", \"false\");\n state.button.innerHTML = opts.buttonInnerHtml;\n Object.assign(state.button.style, mergeStyles(DEFAULTS.buttonStyle, opts.buttonStyle));\n state.button.addEventListener(\"mouseenter\", function () {\n state.button.style.transform = \"scale(1.05)\";\n });\n state.button.addEventListener(\"mouseleave\", function () {\n state.button.style.transform = \"\";\n });\n state.button.addEventListener(\"click\", toggle);\n state.button.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n document.body.appendChild(state.button);\n }\n\n function createOverlay() {\n var opts = state.opts;\n state.overlay = document.createElement(\"div\");\n state.overlay.setAttribute(\"data-embed-chat-overlay\", \"\");\n Object.assign(state.overlay.style, mergeStyles(DEFAULTS.overlayStyle, opts.overlayStyle));\n state.overlay.addEventListener(\"click\", toggle);\n document.body.appendChild(state.overlay);\n }\n\n function createIframe() {\n var opts = state.opts;\n state.iframe = document.createElement(\"iframe\");\n state.iframe.setAttribute(\"data-embed-chat-iframe\", \"\");\n state.iframe.setAttribute(\"title\", \"Chat Widget\");\n state.iframe.setAttribute(\"role\", \"dialog\");\n state.iframe.setAttribute(\"aria-modal\", \"true\");\n state.iframe.setAttribute(\"allow\", \"clipboard-write; microphone\");\n state.iframe.src = opts.iframeSrc;\n Object.assign(state.iframe.style, {\n position: \"fixed\",\n bottom: \"96px\",\n right: \"24px\",\n width: \"420px\",\n height: \"600px\",\n maxWidth: \"calc(100dvw - 48px)\",\n maxHeight: \"calc(100dvh - 120px)\",\n border: \"none\",\n borderRadius: \"16px\",\n boxShadow: \"0 8px 32px rgba(0,0,0,0.15)\",\n zIndex: \"2147483647\",\n opacity: \"0\",\n transform: \"translateY(16px) scale(0.96)\",\n transition: \"opacity 0.2s, transform 0.25s\",\n pointerEvents: \"none\",\n background: \"#fff\",\n });\n document.body.appendChild(state.iframe);\n\n state.iframe.addEventListener(\"load\", function () {\n var savedTheme = \"auto\";\n try {\n var stored = localStorage.getItem(\"chat-theme\");\n if (stored === \"light\" || stored === \"dark\" || stored === \"auto\") savedTheme = stored;\n } catch { /* unavailable */ }\n state.iframe.contentWindow.postMessage(\n { type: \"chat-config\", title: opts.title, placeholder: opts.placeholder, theme: { mode: savedTheme } },\n \"*\",\n );\n });\n }\n\n function toggle() {\n state.isOpen = !state.isOpen;\n var open = state.isOpen;\n\n state.button.setAttribute(\"aria-expanded\", String(open));\n state.iframe.style.opacity = open ? \"1\" : \"0\";\n state.iframe.style.transform = open ? \"translateY(0) scale(1)\" : \"translateY(16px) scale(0.96)\";\n state.iframe.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.overlay.style.opacity = open ? \"1\" : \"0\";\n state.overlay.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.button.style.transform = open ? \"scale(0)\" : \"\";\n state.button.style.opacity = open ? \"0\" : \"1\";\n state.button.style.pointerEvents = open ? \"none\" : \"auto\";\n\n document.body.style.overflow = open ? \"hidden\" : \"\";\n\n if (open) state.iframe.focus();\n }\n\n function handleMessage(event) {\n if (!state.iframe || event.source !== state.iframe.contentWindow) return;\n var data = event.data || {};\n if (data.type === \"chat-message\") {\n console.log(\"[Embed Chat] Message:\", data.text);\n }\n if (data.type === \"chat-close\") {\n toggle();\n }\n if (data.type === \"chat-viewport-config\") {\n var meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) return;\n var current = meta.getAttribute(\"content\") || \"\";\n if (data.content) {\n if (state.originalViewport === undefined) state.originalViewport = current;\n if (!current.includes(data.content)) {\n meta.setAttribute(\"content\", current + (current ? \", \" : \"\") + data.content);\n }\n } else {\n meta.setAttribute(\"content\", state.originalViewport ?? current);\n state.originalViewport = undefined;\n }\n }\n }\n\n function destroy() {\n if (!state.initialized) return;\n if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);\n if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);\n if (state.overlay && state.overlay.parentNode) state.overlay.parentNode.removeChild(state.overlay);\n if (state.styleEl && state.styleEl.parentNode) state.styleEl.parentNode.removeChild(state.styleEl);\n window.removeEventListener(\"message\", handleMessage);\n state.initialized = false;\n }\n\n function _initialize(opts) {\n if (document.querySelector(\"[data-embed-chat-btn]\")) return;\n\n state.opts = {};\n for (var key in DEFAULTS) {\n state.opts[key] = DEFAULTS[key];\n }\n if (opts) {\n for (var k in opts) {\n if (k === \"buttonStyle\" || k === \"overlayStyle\") {\n state.opts[k] = mergeStyles(state.opts[k] || {}, opts[k]);\n } else if (opts[k] !== undefined) {\n state.opts[k] = opts[k];\n }\n }\n }\n\n var style = document.createElement(\"style\");\n style.textContent =\n '@media (max-width: 799px) { [data-embed-chat-iframe] { width: 100dvw !important; height: 100dvh !important; bottom: 0 !important; right: 0 !important; max-width: none !important; max-height: none !important; border-radius: 0 !important; } [data-embed-chat-overlay] { display: none !important; } }';\n document.head.appendChild(style);\n state.styleEl = style;\n\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n state.initialized = true;\n }\n\n function initialize(opts) {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", function () { _initialize(opts); });\n } else {\n _initialize(opts);\n }\n }\n\n window.ChatSDK = { initialize: initialize, destroy: destroy };\n})();\n"],"mappings":";CAAC,WAAY;AACX;AAEA,MAAI,WAAW;AAAA,IACb,WAAW;AAAA,IACX,OAAO;AAAA,IACP,aAAa;AAAA,IACb,iBACE;AAAA,IACF,aAAa;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,IACA,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,QAAQ;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,aAAa;AAAA,EACf;AAEA,WAAS,YAAY,MAAM,WAAW;AACpC,QAAI,SAAS,CAAC;AACd,aAAS,OAAO,KAAM,QAAO,GAAG,IAAI,KAAK,GAAG;AAC5C,QAAI,WAAW;AACb,eAAS,KAAK,UAAW,QAAO,CAAC,IAAI,UAAU,CAAC;AAAA,IAClD;AACA,WAAO;AAAA,EACT;AAEA,WAAS,eAAe;AACtB,QAAI,OAAO,MAAM;AACjB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,UAAM,OAAO,aAAa,uBAAuB,EAAE;AACnD,UAAM,OAAO,aAAa,cAAc,WAAW;AACnD,UAAM,OAAO,aAAa,iBAAiB,OAAO;AAClD,UAAM,OAAO,YAAY,KAAK;AAC9B,WAAO,OAAO,MAAM,OAAO,OAAO,YAAY,SAAS,aAAa,KAAK,WAAW,CAAC;AACrF,UAAM,OAAO,iBAAiB,cAAc,WAAY;AACtD,YAAM,OAAO,MAAM,YAAY;AAAA,IACjC,CAAC;AACD,UAAM,OAAO,iBAAiB,cAAc,WAAY;AACtD,YAAM,OAAO,MAAM,YAAY;AAAA,IACjC,CAAC;AACD,UAAM,OAAO,iBAAiB,SAAS,MAAM;AAC7C,UAAM,OAAO,iBAAiB,WAAW,SAAU,GAAG;AACpD,UAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,UAAE,eAAe;AACjB,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AACD,aAAS,KAAK,YAAY,MAAM,MAAM;AAAA,EACxC;AAEA,WAAS,gBAAgB;AACvB,QAAI,OAAO,MAAM;AACjB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAM,QAAQ,aAAa,2BAA2B,EAAE;AACxD,WAAO,OAAO,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,KAAK,YAAY,CAAC;AACxF,UAAM,QAAQ,iBAAiB,SAAS,MAAM;AAC9C,aAAS,KAAK,YAAY,MAAM,OAAO;AAAA,EACzC;AAEA,WAAS,eAAe;AACtB,QAAI,OAAO,MAAM;AACjB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,UAAM,OAAO,aAAa,0BAA0B,EAAE;AACtD,UAAM,OAAO,aAAa,SAAS,aAAa;AAChD,UAAM,OAAO,aAAa,QAAQ,QAAQ;AAC1C,UAAM,OAAO,aAAa,cAAc,MAAM;AAC9C,UAAM,OAAO,aAAa,SAAS,6BAA6B;AAChE,UAAM,OAAO,MAAM,KAAK;AACxB,WAAO,OAAO,MAAM,OAAO,OAAO;AAAA,MAChC,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,YAAY;AAAA,IACd,CAAC;AACD,aAAS,KAAK,YAAY,MAAM,MAAM;AAEtC,UAAM,OAAO,iBAAiB,QAAQ,WAAY;AAChD,UAAI,aAAa;AACjB,UAAI;AACF,YAAI,SAAS,aAAa,QAAQ,YAAY;AAC9C,YAAI,WAAW,WAAW,WAAW,UAAU,WAAW,OAAQ,cAAa;AAAA,MACjF,QAAQ;AAAA,MAAoB;AAC5B,YAAM,OAAO,cAAc;AAAA,QACzB,EAAE,MAAM,eAAe,OAAO,KAAK,OAAO,aAAa,KAAK,aAAa,OAAO,EAAE,MAAM,WAAW,EAAE;AAAA,QACrG;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,SAAS;AAChB,UAAM,SAAS,CAAC,MAAM;AACtB,QAAI,OAAO,MAAM;AAEjB,UAAM,OAAO,aAAa,iBAAiB,OAAO,IAAI,CAAC;AACvD,UAAM,OAAO,MAAM,UAAU,OAAO,MAAM;AAC1C,UAAM,OAAO,MAAM,YAAY,OAAO,2BAA2B;AACjE,UAAM,OAAO,MAAM,gBAAgB,OAAO,SAAS;AAEnD,UAAM,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3C,UAAM,QAAQ,MAAM,gBAAgB,OAAO,SAAS;AAEpD,UAAM,OAAO,MAAM,YAAY,OAAO,aAAa;AACnD,UAAM,OAAO,MAAM,UAAU,OAAO,MAAM;AAC1C,UAAM,OAAO,MAAM,gBAAgB,OAAO,SAAS;AAEnD,aAAS,KAAK,MAAM,WAAW,OAAO,WAAW;AAEjD,QAAI,KAAM,OAAM,OAAO,MAAM;AAAA,EAC/B;AAEA,WAAS,cAAc,OAAO;AAC5B,QAAI,CAAC,MAAM,UAAU,MAAM,WAAW,MAAM,OAAO,cAAe;AAClE,QAAI,OAAO,MAAM,QAAQ,CAAC;AAC1B,QAAI,KAAK,SAAS,gBAAgB;AAChC,cAAQ,IAAI,yBAAyB,KAAK,IAAI;AAAA,IAChD;AACA,QAAI,KAAK,SAAS,cAAc;AAC9B,aAAO;AAAA,IACT;AACA,QAAI,KAAK,SAAS,wBAAwB;AACxC,UAAI,OAAO,SAAS,cAAc,uBAAuB;AACzD,UAAI,CAAC,KAAM;AACX,UAAI,UAAU,KAAK,aAAa,SAAS,KAAK;AAC9C,UAAI,KAAK,SAAS;AAChB,YAAI,MAAM,qBAAqB,OAAW,OAAM,mBAAmB;AACnE,YAAI,CAAC,QAAQ,SAAS,KAAK,OAAO,GAAG;AACnC,eAAK,aAAa,WAAW,WAAW,UAAU,OAAO,MAAM,KAAK,OAAO;AAAA,QAC7E;AAAA,MACF,OAAO;AACL,aAAK,aAAa,WAAW,MAAM,oBAAoB,OAAO;AAC9D,cAAM,mBAAmB;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,WAAS,UAAU;AACjB,QAAI,CAAC,MAAM,YAAa;AACxB,QAAI,MAAM,UAAU,MAAM,OAAO,WAAY,OAAM,OAAO,WAAW,YAAY,MAAM,MAAM;AAC7F,QAAI,MAAM,UAAU,MAAM,OAAO,WAAY,OAAM,OAAO,WAAW,YAAY,MAAM,MAAM;AAC7F,QAAI,MAAM,WAAW,MAAM,QAAQ,WAAY,OAAM,QAAQ,WAAW,YAAY,MAAM,OAAO;AACjG,QAAI,MAAM,WAAW,MAAM,QAAQ,WAAY,OAAM,QAAQ,WAAW,YAAY,MAAM,OAAO;AACjG,WAAO,oBAAoB,WAAW,aAAa;AACnD,UAAM,cAAc;AAAA,EACtB;AAEA,WAAS,YAAY,MAAM;AACzB,QAAI,SAAS,cAAc,uBAAuB,EAAG;AAErD,UAAM,OAAO,CAAC;AACd,aAAS,OAAO,UAAU;AACxB,YAAM,KAAK,GAAG,IAAI,SAAS,GAAG;AAAA,IAChC;AACA,QAAI,MAAM;AACR,eAAS,KAAK,MAAM;AAClB,YAAI,MAAM,iBAAiB,MAAM,gBAAgB;AAC/C,gBAAM,KAAK,CAAC,IAAI,YAAY,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,QAC1D,WAAW,KAAK,CAAC,MAAM,QAAW;AAChC,gBAAM,KAAK,CAAC,IAAI,KAAK,CAAC;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,cAAc,OAAO;AAC1C,UAAM,cACJ;AACF,aAAS,KAAK,YAAY,KAAK;AAC/B,UAAM,UAAU;AAEhB,kBAAc;AACd,iBAAa;AACb,iBAAa;AACb,WAAO,iBAAiB,WAAW,aAAa;AAChD,UAAM,cAAc;AAAA,EACtB;AAEA,WAAS,WAAW,MAAM;AACxB,QAAI,SAAS,eAAe,WAAW;AACrC,eAAS,iBAAiB,oBAAoB,WAAY;AAAE,oBAAY,IAAI;AAAA,MAAG,CAAC;AAAA,IAClF,OAAO;AACL,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,UAAU,EAAE,YAAwB,QAAiB;AAC9D,GAAG;","names":[]}
1
+ {"version":3,"sources":["../src/embed-chat.js"],"sourcesContent":["(function () {\n \"use strict\";\n\n var DEFAULTS = {\n iframeSrc: \"/chat-iframe\",\n title: \"Chat\",\n placeholder: \"Type a message...\",\n buttonInnerHtml:\n '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>',\n buttonStyle: {\n position: \"fixed\",\n bottom: \"24px\",\n right: \"24px\",\n width: \"56px\",\n height: \"56px\",\n borderRadius: \"50%\",\n border: \"none\",\n background: \"var(--chat-primary, #6366f1)\",\n color: \"#fff\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 4px 16px rgba(0,0,0,0.2)\",\n zIndex: \"2147483646\",\n transition: \"transform 0.2s, opacity 0.2s\",\n },\n overlayStyle: {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,0.3)\",\n zIndex: \"2147483646\",\n opacity: \"0\",\n transition: \"opacity 0.2s\",\n pointerEvents: \"none\",\n },\n };\n\n var state = {\n opts: null,\n button: null,\n iframe: null,\n overlay: null,\n styleEl: null,\n isOpen: false,\n originalViewport: undefined,\n initialized: false,\n };\n\n function mergeStyles(base, overrides) {\n var result = {};\n for (var key in base) result[key] = base[key];\n if (overrides) {\n for (var k in overrides) result[k] = overrides[k];\n }\n return result;\n }\n\n function createButton() {\n var opts = state.opts;\n state.button = document.createElement(\"button\");\n state.button.setAttribute(\"data-embed-chat-btn\", \"\");\n state.button.setAttribute(\"aria-label\", \"Open chat\");\n state.button.setAttribute(\"aria-expanded\", \"false\");\n state.button.innerHTML = opts.buttonInnerHtml;\n Object.assign(state.button.style, mergeStyles(DEFAULTS.buttonStyle, opts.buttonStyle));\n state.button.addEventListener(\"mouseenter\", function () {\n state.button.style.transform = \"scale(1.05)\";\n });\n state.button.addEventListener(\"mouseleave\", function () {\n state.button.style.transform = \"\";\n });\n state.button.addEventListener(\"click\", toggle);\n state.button.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n document.body.appendChild(state.button);\n }\n\n function createOverlay() {\n var opts = state.opts;\n state.overlay = document.createElement(\"div\");\n state.overlay.setAttribute(\"data-embed-chat-overlay\", \"\");\n Object.assign(state.overlay.style, mergeStyles(DEFAULTS.overlayStyle, opts.overlayStyle));\n state.overlay.addEventListener(\"click\", toggle);\n document.body.appendChild(state.overlay);\n }\n\n function createIframe() {\n var opts = state.opts;\n state.iframe = document.createElement(\"iframe\");\n state.iframe.setAttribute(\"data-embed-chat-iframe\", \"\");\n state.iframe.setAttribute(\"title\", \"Chat Widget\");\n state.iframe.setAttribute(\"role\", \"dialog\");\n state.iframe.setAttribute(\"aria-modal\", \"true\");\n state.iframe.setAttribute(\"allow\", \"clipboard-write; microphone\");\n state.iframe.src = opts.iframeSrc;\n Object.assign(state.iframe.style, {\n position: \"fixed\",\n bottom: \"96px\",\n right: \"24px\",\n width: \"420px\",\n height: \"600px\",\n maxWidth: \"calc(100dvw - 48px)\",\n maxHeight: \"calc(100dvh - 120px)\",\n border: \"none\",\n borderRadius: \"16px\",\n boxShadow: \"0 8px 32px rgba(0,0,0,0.15)\",\n zIndex: \"2147483647\",\n opacity: \"0\",\n transform: \"translateY(16px) scale(0.96)\",\n transition: \"opacity 0.2s, transform 0.25s\",\n pointerEvents: \"none\",\n background: \"#fff\",\n });\n document.body.appendChild(state.iframe);\n\n state.iframe.addEventListener(\"load\", function () {\n var savedTheme = \"auto\";\n try {\n var stored = localStorage.getItem(\"chat-theme\");\n if (stored === \"light\" || stored === \"dark\" || stored === \"auto\") savedTheme = stored;\n } catch {\n /* unavailable */\n }\n state.iframe.contentWindow.postMessage(\n {\n type: \"chat-config\",\n title: opts.title,\n placeholder: opts.placeholder,\n theme: { mode: savedTheme },\n },\n \"*\",\n );\n });\n }\n\n function toggle() {\n state.isOpen = !state.isOpen;\n var open = state.isOpen;\n\n state.button.setAttribute(\"aria-expanded\", String(open));\n state.iframe.style.opacity = open ? \"1\" : \"0\";\n state.iframe.style.transform = open ? \"translateY(0) scale(1)\" : \"translateY(16px) scale(0.96)\";\n state.iframe.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.overlay.style.opacity = open ? \"1\" : \"0\";\n state.overlay.style.pointerEvents = open ? \"auto\" : \"none\";\n\n state.button.style.transform = open ? \"scale(0)\" : \"\";\n state.button.style.opacity = open ? \"0\" : \"1\";\n state.button.style.pointerEvents = open ? \"none\" : \"auto\";\n\n document.body.style.overflow = open ? \"hidden\" : \"\";\n\n if (open) state.iframe.focus();\n }\n\n function handleMessage(event) {\n if (!state.iframe || event.source !== state.iframe.contentWindow) return;\n var data = event.data || {};\n if (data.type === \"chat-message\") {\n console.log(\"[Embed Chat] Message:\", data.text);\n }\n if (data.type === \"chat-close\") {\n toggle();\n }\n if (data.type === \"chat-viewport-config\") {\n var meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) return;\n var current = meta.getAttribute(\"content\") || \"\";\n if (data.content) {\n if (state.originalViewport === undefined) state.originalViewport = current;\n if (!current.includes(data.content)) {\n meta.setAttribute(\"content\", current + (current ? \", \" : \"\") + data.content);\n }\n } else {\n meta.setAttribute(\"content\", state.originalViewport ?? current);\n state.originalViewport = undefined;\n }\n }\n }\n\n function destroy() {\n if (!state.initialized) return;\n if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);\n if (state.iframe && state.iframe.parentNode) state.iframe.parentNode.removeChild(state.iframe);\n if (state.overlay && state.overlay.parentNode)\n state.overlay.parentNode.removeChild(state.overlay);\n if (state.styleEl && state.styleEl.parentNode)\n state.styleEl.parentNode.removeChild(state.styleEl);\n window.removeEventListener(\"message\", handleMessage);\n state.initialized = false;\n }\n\n function _initialize(opts) {\n if (document.querySelector(\"[data-embed-chat-btn]\")) return;\n\n state.opts = {};\n for (var key in DEFAULTS) {\n state.opts[key] = DEFAULTS[key];\n }\n if (opts) {\n for (var k in opts) {\n if (k === \"buttonStyle\" || k === \"overlayStyle\") {\n state.opts[k] = mergeStyles(state.opts[k] || {}, opts[k]);\n } else if (opts[k] !== undefined) {\n state.opts[k] = opts[k];\n }\n }\n }\n\n var style = document.createElement(\"style\");\n style.textContent =\n \"@media (max-width: 799px) { [data-embed-chat-iframe] { width: 100dvw !important; height: 100dvh !important; bottom: 0 !important; right: 0 !important; max-width: none !important; max-height: none !important; border-radius: 0 !important; } [data-embed-chat-overlay] { display: none !important; } }\";\n document.head.appendChild(style);\n state.styleEl = style;\n\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n state.initialized = true;\n }\n\n function initialize(opts) {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", function () {\n _initialize(opts);\n });\n } else {\n _initialize(opts);\n }\n }\n\n window.ChatSDK = { initialize: initialize, destroy: destroy };\n})();\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ WEBVIEW_SHIM: () => WEBVIEW_SHIM,
24
+ buildShimUrl: () => buildShimUrl,
23
25
  useIframeBridge: () => useIframeBridge
24
26
  });
25
27
  module.exports = __toCommonJS(index_exports);
@@ -28,8 +30,15 @@ module.exports = __toCommonJS(index_exports);
28
30
  var import_react = require("react");
29
31
  function useIframeBridge() {
30
32
  const [config, setConfig] = (0, import_react.useState)(null);
33
+ const [pushState, setPushState] = (0, import_react.useState)(null);
31
34
  const notificationCbRef = (0, import_react.useRef)(null);
35
+ const readyRef = (0, import_react.useRef)(false);
32
36
  const isInIframe = typeof window !== "undefined" && window !== window.parent;
37
+ (0, import_react.useEffect)(() => {
38
+ if (typeof window !== "undefined" && window.__chatBridge?._pushState) {
39
+ setPushState(window.__chatBridge._pushState);
40
+ }
41
+ }, []);
33
42
  const notifyMessage = (0, import_react.useCallback)(
34
43
  (text) => {
35
44
  if (!isInIframe) return;
@@ -49,6 +58,25 @@ function useIframeBridge() {
49
58
  const onNotificationClicked = (0, import_react.useCallback)((cb) => {
50
59
  notificationCbRef.current = cb;
51
60
  }, []);
61
+ const requestPushSubscribe = (0, import_react.useCallback)(() => {
62
+ if (!isInIframe) return;
63
+ const msg = { type: "chat-push-subscribe" };
64
+ window.parent.postMessage(msg, "*");
65
+ }, [isInIframe]);
66
+ const requestPushUnsubscribe = (0, import_react.useCallback)(() => {
67
+ if (!isInIframe) return;
68
+ const msg = { type: "chat-push-unsubscribe" };
69
+ window.parent.postMessage(msg, "*");
70
+ }, [isInIframe]);
71
+ (0, import_react.useEffect)(() => {
72
+ if (!isInIframe) return;
73
+ if (readyRef.current) return;
74
+ readyRef.current = true;
75
+ const msg = { type: "chat-ready" };
76
+ if (typeof window.parent.postMessage === "function") {
77
+ window.parent.postMessage(msg, "*");
78
+ }
79
+ }, [isInIframe]);
52
80
  (0, import_react.useEffect)(() => {
53
81
  if (!isInIframe) return;
54
82
  function handleMessage(event) {
@@ -64,15 +92,113 @@ function useIframeBridge() {
64
92
  case "chat-notification-clicked":
65
93
  notificationCbRef.current?.();
66
94
  break;
95
+ case "chat-push-state":
96
+ if (typeof data.status === "string") {
97
+ setPushState(data.status);
98
+ }
99
+ break;
100
+ }
101
+ }
102
+ function handleCustomEvent(event) {
103
+ const detail = event.detail;
104
+ if (!detail || typeof detail !== "object") return;
105
+ if (detail.type === "chat-push-state" && typeof detail.status === "string") {
106
+ setPushState(detail.status);
67
107
  }
68
108
  }
69
109
  window.addEventListener("message", handleMessage);
70
- return () => window.removeEventListener("message", handleMessage);
110
+ window.addEventListener("chat-bridge", handleCustomEvent);
111
+ return () => {
112
+ window.removeEventListener("message", handleMessage);
113
+ window.removeEventListener("chat-bridge", handleCustomEvent);
114
+ };
71
115
  }, [isInIframe]);
72
- return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };
116
+ return {
117
+ config,
118
+ isInIframe,
119
+ notifyMessage,
120
+ notifyViewportConfig,
121
+ onNotificationClicked,
122
+ pushState,
123
+ requestPushSubscribe,
124
+ requestPushUnsubscribe
125
+ };
126
+ }
127
+
128
+ // src/shim.ts
129
+ var WEBVIEW_SHIM = `
130
+ (function () {
131
+ 'use strict';
132
+ var _cached = [];
133
+ var _originalPostMessage = window.parent && window.parent.postMessage;
134
+
135
+ function _send(msg) {
136
+ try {
137
+ var json = JSON.stringify(msg);
138
+ } catch (e) {
139
+ var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });
140
+ try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}
141
+ console.error('[ChatBridge] JSON.stringify failed:', e);
142
+ return;
143
+ }
144
+ try {
145
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
146
+ window.ReactNativeWebView.postMessage(json);
147
+ } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {
148
+ window.AndroidBridge.postMessage(json);
149
+ } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {
150
+ window.webkit.messageHandlers.chatBridge.postMessage(msg);
151
+ } else if (_originalPostMessage) {
152
+ _originalPostMessage.call(window.parent, msg, '*');
153
+ } else {
154
+ console.warn('[ChatBridge] No bridge API detected');
155
+ }
156
+ } catch (e) {
157
+ var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });
158
+ try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}
159
+ console.error('[ChatBridge] postMessage failed:', e);
160
+ }
161
+ }
162
+
163
+ window.__chatBridge = {
164
+ _pushState: null,
165
+ send: function (msg) { _send(msg); },
166
+ setPushState: function (status) { window.__chatBridge._pushState = status; },
167
+ };
168
+
169
+ var _batches = 0;
170
+ window.addEventListener('chat-bridge', function (e) {
171
+ if (_batches++ > 0) return;
172
+ requestAnimationFrame(function () {
173
+ _batches = 0;
174
+ });
175
+ var payload = e.detail;
176
+ if (!payload || typeof payload !== 'object') return;
177
+ var type = payload.type;
178
+ if (type === 'chat-config') {
179
+ window.__chatBridge._config = payload;
180
+ } else if (type === 'chat-push-state') {
181
+ window.__chatBridge._pushState = payload.status || null;
182
+ }
183
+ _cached.push(payload);
184
+ });
185
+
186
+ window.addEventListener('message', function (e) {
187
+ var data = e.data;
188
+ if (!data || typeof data !== 'object' || !data.type) return;
189
+ if (data.type === 'chat-push-state') {
190
+ window.__chatBridge._pushState = data.status || null;
191
+ }
192
+ });
193
+ })();
194
+ `;
195
+ function buildShimUrl() {
196
+ return "data:text/javascript;base64," + btoa(WEBVIEW_SHIM);
73
197
  }
74
198
  // Annotate the CommonJS export names for ESM import in node:
75
199
  0 && (module.exports = {
200
+ WEBVIEW_SHIM,
201
+ buildShimUrl,
76
202
  useIframeBridge
77
203
  });
78
204
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/useIframeBridge.ts"],"sourcesContent":["export { useIframeBridge } from \"./useIframeBridge\";\nexport type { BridgeConfig, IframeBridgeHook, BridgeMessage } from \"./types\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { BridgeConfig, BridgeMessage, IframeBridgeHook } from \"./types\";\n\nexport function useIframeBridge(): IframeBridgeHook {\n const [config, setConfig] = useState<BridgeConfig | null>(null);\n const notificationCbRef = useRef<(() => void) | null>(null);\n\n const isInIframe = typeof window !== \"undefined\" && window !== window.parent;\n\n const notifyMessage = useCallback(\n (text: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-message\", text };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const notifyViewportConfig = useCallback(\n (content: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-viewport-config\", content };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const onNotificationClicked = useCallback((cb: () => void) => {\n notificationCbRef.current = cb;\n }, []);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n function handleMessage(event: MessageEvent) {\n const data = event.data as Record<string, unknown>;\n if (!data || typeof data !== \"object\" || !data.type) return;\n\n switch (data.type) {\n case \"chat-config\": {\n const configData = { ...data };\n delete configData.type;\n setConfig(configData as BridgeConfig);\n break;\n }\n case \"chat-notification-clicked\":\n notificationCbRef.current?.();\n break;\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [isInIframe]);\n\n return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAyD;AAGlD,SAAS,kBAAoC;AAClD,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAA8B,IAAI;AAC9D,QAAM,wBAAoB,qBAA4B,IAAI;AAE1D,QAAM,aAAa,OAAO,WAAW,eAAe,WAAW,OAAO;AAEtE,QAAM,oBAAgB;AAAA,IACpB,CAAC,SAAiB;AAChB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,gBAAgB,KAAK;AACxD,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,2BAAuB;AAAA,IAC3B,CAAC,YAAoB;AACnB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,wBAAwB,QAAQ;AACnE,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,4BAAwB,0BAAY,CAAC,OAAmB;AAC5D,sBAAkB,UAAU;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACd,QAAI,CAAC,WAAY;AAEjB,aAAS,cAAc,OAAqB;AAC1C,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,KAAM;AAErD,cAAQ,KAAK,MAAM;AAAA,QACjB,KAAK,eAAe;AAClB,gBAAM,aAAa,EAAE,GAAG,KAAK;AAC7B,iBAAO,WAAW;AAClB,oBAAU,UAA0B;AACpC;AAAA,QACF;AAAA,QACA,KAAK;AACH,4BAAkB,UAAU;AAC5B;AAAA,MACJ;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,EAClE,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO,EAAE,QAAQ,YAAY,eAAe,sBAAsB,sBAAsB;AAC1F;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/useIframeBridge.ts","../src/shim.ts"],"sourcesContent":["export { useIframeBridge } from \"./useIframeBridge\";\nexport { WEBVIEW_SHIM, buildShimUrl } from \"./shim\";\nexport type {\n BridgeConfig,\n IframeBridgeHook,\n BridgeMessage,\n BridgePushStatus,\n BridgeMessageType,\n ThemeMode,\n} from \"./types\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { BridgeConfig, BridgeMessage, BridgePushStatus, IframeBridgeHook } from \"./types\";\n\nexport function useIframeBridge(): IframeBridgeHook {\n const [config, setConfig] = useState<BridgeConfig | null>(null);\n const [pushState, setPushState] = useState<BridgePushStatus | null>(null);\n const notificationCbRef = useRef<(() => void) | null>(null);\n const readyRef = useRef(false);\n\n const isInIframe = typeof window !== \"undefined\" && window !== window.parent;\n\n useEffect(() => {\n if (typeof window !== \"undefined\" && (window as any).__chatBridge?._pushState) {\n setPushState((window as any).__chatBridge._pushState);\n }\n }, []);\n\n const notifyMessage = useCallback(\n (text: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-message\", text };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const notifyViewportConfig = useCallback(\n (content: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-viewport-config\", content };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const onNotificationClicked = useCallback((cb: () => void) => {\n notificationCbRef.current = cb;\n }, []);\n\n const requestPushSubscribe = useCallback(() => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-push-subscribe\" };\n window.parent.postMessage(msg, \"*\");\n }, [isInIframe]);\n\n const requestPushUnsubscribe = useCallback(() => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-push-unsubscribe\" };\n window.parent.postMessage(msg, \"*\");\n }, [isInIframe]);\n\n useEffect(() => {\n if (!isInIframe) return;\n if (readyRef.current) return;\n readyRef.current = true;\n\n const msg: BridgeMessage = { type: \"chat-ready\" };\n if (typeof window.parent.postMessage === \"function\") {\n window.parent.postMessage(msg, \"*\");\n }\n }, [isInIframe]);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n function handleMessage(event: MessageEvent) {\n const data = event.data as Record<string, unknown>;\n if (!data || typeof data !== \"object\" || !data.type) return;\n\n switch (data.type) {\n case \"chat-config\": {\n const configData = { ...data };\n delete configData.type;\n setConfig(configData as BridgeConfig);\n break;\n }\n case \"chat-notification-clicked\":\n notificationCbRef.current?.();\n break;\n case \"chat-push-state\":\n if (typeof data.status === \"string\") {\n setPushState(data.status as BridgePushStatus);\n }\n break;\n }\n }\n\n function handleCustomEvent(event: Event) {\n const detail = (event as CustomEvent).detail;\n if (!detail || typeof detail !== \"object\") return;\n if (detail.type === \"chat-push-state\" && typeof detail.status === \"string\") {\n setPushState(detail.status as BridgePushStatus);\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"chat-bridge\", handleCustomEvent);\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"chat-bridge\", handleCustomEvent);\n };\n }, [isInIframe]);\n\n return {\n config,\n isInIframe,\n notifyMessage,\n notifyViewportConfig,\n onNotificationClicked,\n pushState,\n requestPushSubscribe,\n requestPushUnsubscribe,\n };\n}\n","export const WEBVIEW_SHIM: string = `\n(function () {\n 'use strict';\n var _cached = [];\n var _originalPostMessage = window.parent && window.parent.postMessage;\n\n function _send(msg) {\n try {\n var json = JSON.stringify(msg);\n } catch (e) {\n var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });\n try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}\n console.error('[ChatBridge] JSON.stringify failed:', e);\n return;\n }\n try {\n if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {\n window.ReactNativeWebView.postMessage(json);\n } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {\n window.AndroidBridge.postMessage(json);\n } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {\n window.webkit.messageHandlers.chatBridge.postMessage(msg);\n } else if (_originalPostMessage) {\n _originalPostMessage.call(window.parent, msg, '*');\n } else {\n console.warn('[ChatBridge] No bridge API detected');\n }\n } catch (e) {\n var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });\n try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}\n console.error('[ChatBridge] postMessage failed:', e);\n }\n }\n\n window.__chatBridge = {\n _pushState: null,\n send: function (msg) { _send(msg); },\n setPushState: function (status) { window.__chatBridge._pushState = status; },\n };\n\n var _batches = 0;\n window.addEventListener('chat-bridge', function (e) {\n if (_batches++ > 0) return;\n requestAnimationFrame(function () {\n _batches = 0;\n });\n var payload = e.detail;\n if (!payload || typeof payload !== 'object') return;\n var type = payload.type;\n if (type === 'chat-config') {\n window.__chatBridge._config = payload;\n } else if (type === 'chat-push-state') {\n window.__chatBridge._pushState = payload.status || null;\n }\n _cached.push(payload);\n });\n\n window.addEventListener('message', function (e) {\n var data = e.data;\n if (!data || typeof data !== 'object' || !data.type) return;\n if (data.type === 'chat-push-state') {\n window.__chatBridge._pushState = data.status || null;\n }\n });\n})();\n`;\n\nexport function buildShimUrl(): string {\n return \"data:text/javascript;base64,\" + btoa(WEBVIEW_SHIM);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAyD;AAGlD,SAAS,kBAAoC;AAClD,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAA8B,IAAI;AAC9D,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAkC,IAAI;AACxE,QAAM,wBAAoB,qBAA4B,IAAI;AAC1D,QAAM,eAAW,qBAAO,KAAK;AAE7B,QAAM,aAAa,OAAO,WAAW,eAAe,WAAW,OAAO;AAEtE,8BAAU,MAAM;AACd,QAAI,OAAO,WAAW,eAAgB,OAAe,cAAc,YAAY;AAC7E,mBAAc,OAAe,aAAa,UAAU;AAAA,IACtD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB;AAAA,IACpB,CAAC,SAAiB;AAChB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,gBAAgB,KAAK;AACxD,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,2BAAuB;AAAA,IAC3B,CAAC,YAAoB;AACnB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,wBAAwB,QAAQ;AACnE,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,4BAAwB,0BAAY,CAAC,OAAmB;AAC5D,sBAAkB,UAAU;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,2BAAuB,0BAAY,MAAM;AAC7C,QAAI,CAAC,WAAY;AACjB,UAAM,MAAqB,EAAE,MAAM,sBAAsB;AACzD,WAAO,OAAO,YAAY,KAAK,GAAG;AAAA,EACpC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,6BAAyB,0BAAY,MAAM;AAC/C,QAAI,CAAC,WAAY;AACjB,UAAM,MAAqB,EAAE,MAAM,wBAAwB;AAC3D,WAAO,OAAO,YAAY,KAAK,GAAG;AAAA,EACpC,GAAG,CAAC,UAAU,CAAC;AAEf,8BAAU,MAAM;AACd,QAAI,CAAC,WAAY;AACjB,QAAI,SAAS,QAAS;AACtB,aAAS,UAAU;AAEnB,UAAM,MAAqB,EAAE,MAAM,aAAa;AAChD,QAAI,OAAO,OAAO,OAAO,gBAAgB,YAAY;AACnD,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,8BAAU,MAAM;AACd,QAAI,CAAC,WAAY;AAEjB,aAAS,cAAc,OAAqB;AAC1C,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,KAAM;AAErD,cAAQ,KAAK,MAAM;AAAA,QACjB,KAAK,eAAe;AAClB,gBAAM,aAAa,EAAE,GAAG,KAAK;AAC7B,iBAAO,WAAW;AAClB,oBAAU,UAA0B;AACpC;AAAA,QACF;AAAA,QACA,KAAK;AACH,4BAAkB,UAAU;AAC5B;AAAA,QACF,KAAK;AACH,cAAI,OAAO,KAAK,WAAW,UAAU;AACnC,yBAAa,KAAK,MAA0B;AAAA,UAC9C;AACA;AAAA,MACJ;AAAA,IACF;AAEA,aAAS,kBAAkB,OAAc;AACvC,YAAM,SAAU,MAAsB;AACtC,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,UAAI,OAAO,SAAS,qBAAqB,OAAO,OAAO,WAAW,UAAU;AAC1E,qBAAa,OAAO,MAA0B;AAAA,MAChD;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,iBAAiB,eAAe,iBAAiB;AACxD,WAAO,MAAM;AACX,aAAO,oBAAoB,WAAW,aAAa;AACnD,aAAO,oBAAoB,eAAe,iBAAiB;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjHO,IAAM,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmE7B,SAAS,eAAuB;AACrC,SAAO,iCAAiC,KAAK,YAAY;AAC3D;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,9 +1,13 @@
1
+ type BridgePushStatus = "unsupported" | "default" | "subscribed" | "denied" | "subscribing" | "error";
2
+ type BridgeMessageType = "chat-ready" | "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config" | "chat-viewport-insets" | "chat-push-state" | "chat-push-subscribe" | "chat-push-unsubscribe" | "chat-error";
3
+ type ThemeMode = "auto" | "light" | "dark";
1
4
  interface BridgeConfig {
2
5
  locale?: string;
3
6
  title?: string;
4
7
  placeholder?: string;
5
8
  theme?: {
6
- mode?: "auto" | "light" | "dark";
9
+ mode?: ThemeMode;
10
+ cssVariables?: Record<string, string>;
7
11
  };
8
12
  }
9
13
  interface IframeBridgeHook {
@@ -12,12 +16,19 @@ interface IframeBridgeHook {
12
16
  notifyMessage: (text: string) => void;
13
17
  notifyViewportConfig: (content: string) => void;
14
18
  onNotificationClicked: (cb: () => void) => void;
19
+ pushState: BridgePushStatus | null;
20
+ requestPushSubscribe: () => void;
21
+ requestPushUnsubscribe: () => void;
15
22
  }
16
23
  interface BridgeMessage {
17
- type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config";
24
+ type: BridgeMessageType;
25
+ id?: string;
18
26
  [key: string]: unknown;
19
27
  }
20
28
 
21
29
  declare function useIframeBridge(): IframeBridgeHook;
22
30
 
23
- export { type BridgeConfig, type BridgeMessage, type IframeBridgeHook, useIframeBridge };
31
+ declare const WEBVIEW_SHIM: string;
32
+ declare function buildShimUrl(): string;
33
+
34
+ export { type BridgeConfig, type BridgeMessage, type BridgeMessageType, type BridgePushStatus, type IframeBridgeHook, type ThemeMode, WEBVIEW_SHIM, buildShimUrl, useIframeBridge };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
+ type BridgePushStatus = "unsupported" | "default" | "subscribed" | "denied" | "subscribing" | "error";
2
+ type BridgeMessageType = "chat-ready" | "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config" | "chat-viewport-insets" | "chat-push-state" | "chat-push-subscribe" | "chat-push-unsubscribe" | "chat-error";
3
+ type ThemeMode = "auto" | "light" | "dark";
1
4
  interface BridgeConfig {
2
5
  locale?: string;
3
6
  title?: string;
4
7
  placeholder?: string;
5
8
  theme?: {
6
- mode?: "auto" | "light" | "dark";
9
+ mode?: ThemeMode;
10
+ cssVariables?: Record<string, string>;
7
11
  };
8
12
  }
9
13
  interface IframeBridgeHook {
@@ -12,12 +16,19 @@ interface IframeBridgeHook {
12
16
  notifyMessage: (text: string) => void;
13
17
  notifyViewportConfig: (content: string) => void;
14
18
  onNotificationClicked: (cb: () => void) => void;
19
+ pushState: BridgePushStatus | null;
20
+ requestPushSubscribe: () => void;
21
+ requestPushUnsubscribe: () => void;
15
22
  }
16
23
  interface BridgeMessage {
17
- type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config";
24
+ type: BridgeMessageType;
25
+ id?: string;
18
26
  [key: string]: unknown;
19
27
  }
20
28
 
21
29
  declare function useIframeBridge(): IframeBridgeHook;
22
30
 
23
- export { type BridgeConfig, type BridgeMessage, type IframeBridgeHook, useIframeBridge };
31
+ declare const WEBVIEW_SHIM: string;
32
+ declare function buildShimUrl(): string;
33
+
34
+ export { type BridgeConfig, type BridgeMessage, type BridgeMessageType, type BridgePushStatus, type IframeBridgeHook, type ThemeMode, WEBVIEW_SHIM, buildShimUrl, useIframeBridge };
package/dist/index.js CHANGED
@@ -2,8 +2,15 @@
2
2
  import { useCallback, useEffect, useRef, useState } from "react";
3
3
  function useIframeBridge() {
4
4
  const [config, setConfig] = useState(null);
5
+ const [pushState, setPushState] = useState(null);
5
6
  const notificationCbRef = useRef(null);
7
+ const readyRef = useRef(false);
6
8
  const isInIframe = typeof window !== "undefined" && window !== window.parent;
9
+ useEffect(() => {
10
+ if (typeof window !== "undefined" && window.__chatBridge?._pushState) {
11
+ setPushState(window.__chatBridge._pushState);
12
+ }
13
+ }, []);
7
14
  const notifyMessage = useCallback(
8
15
  (text) => {
9
16
  if (!isInIframe) return;
@@ -23,6 +30,25 @@ function useIframeBridge() {
23
30
  const onNotificationClicked = useCallback((cb) => {
24
31
  notificationCbRef.current = cb;
25
32
  }, []);
33
+ const requestPushSubscribe = useCallback(() => {
34
+ if (!isInIframe) return;
35
+ const msg = { type: "chat-push-subscribe" };
36
+ window.parent.postMessage(msg, "*");
37
+ }, [isInIframe]);
38
+ const requestPushUnsubscribe = useCallback(() => {
39
+ if (!isInIframe) return;
40
+ const msg = { type: "chat-push-unsubscribe" };
41
+ window.parent.postMessage(msg, "*");
42
+ }, [isInIframe]);
43
+ useEffect(() => {
44
+ if (!isInIframe) return;
45
+ if (readyRef.current) return;
46
+ readyRef.current = true;
47
+ const msg = { type: "chat-ready" };
48
+ if (typeof window.parent.postMessage === "function") {
49
+ window.parent.postMessage(msg, "*");
50
+ }
51
+ }, [isInIframe]);
26
52
  useEffect(() => {
27
53
  if (!isInIframe) return;
28
54
  function handleMessage(event) {
@@ -38,14 +64,112 @@ function useIframeBridge() {
38
64
  case "chat-notification-clicked":
39
65
  notificationCbRef.current?.();
40
66
  break;
67
+ case "chat-push-state":
68
+ if (typeof data.status === "string") {
69
+ setPushState(data.status);
70
+ }
71
+ break;
72
+ }
73
+ }
74
+ function handleCustomEvent(event) {
75
+ const detail = event.detail;
76
+ if (!detail || typeof detail !== "object") return;
77
+ if (detail.type === "chat-push-state" && typeof detail.status === "string") {
78
+ setPushState(detail.status);
41
79
  }
42
80
  }
43
81
  window.addEventListener("message", handleMessage);
44
- return () => window.removeEventListener("message", handleMessage);
82
+ window.addEventListener("chat-bridge", handleCustomEvent);
83
+ return () => {
84
+ window.removeEventListener("message", handleMessage);
85
+ window.removeEventListener("chat-bridge", handleCustomEvent);
86
+ };
45
87
  }, [isInIframe]);
46
- return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };
88
+ return {
89
+ config,
90
+ isInIframe,
91
+ notifyMessage,
92
+ notifyViewportConfig,
93
+ onNotificationClicked,
94
+ pushState,
95
+ requestPushSubscribe,
96
+ requestPushUnsubscribe
97
+ };
98
+ }
99
+
100
+ // src/shim.ts
101
+ var WEBVIEW_SHIM = `
102
+ (function () {
103
+ 'use strict';
104
+ var _cached = [];
105
+ var _originalPostMessage = window.parent && window.parent.postMessage;
106
+
107
+ function _send(msg) {
108
+ try {
109
+ var json = JSON.stringify(msg);
110
+ } catch (e) {
111
+ var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });
112
+ try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}
113
+ console.error('[ChatBridge] JSON.stringify failed:', e);
114
+ return;
115
+ }
116
+ try {
117
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
118
+ window.ReactNativeWebView.postMessage(json);
119
+ } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {
120
+ window.AndroidBridge.postMessage(json);
121
+ } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {
122
+ window.webkit.messageHandlers.chatBridge.postMessage(msg);
123
+ } else if (_originalPostMessage) {
124
+ _originalPostMessage.call(window.parent, msg, '*');
125
+ } else {
126
+ console.warn('[ChatBridge] No bridge API detected');
127
+ }
128
+ } catch (e) {
129
+ var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });
130
+ try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}
131
+ console.error('[ChatBridge] postMessage failed:', e);
132
+ }
133
+ }
134
+
135
+ window.__chatBridge = {
136
+ _pushState: null,
137
+ send: function (msg) { _send(msg); },
138
+ setPushState: function (status) { window.__chatBridge._pushState = status; },
139
+ };
140
+
141
+ var _batches = 0;
142
+ window.addEventListener('chat-bridge', function (e) {
143
+ if (_batches++ > 0) return;
144
+ requestAnimationFrame(function () {
145
+ _batches = 0;
146
+ });
147
+ var payload = e.detail;
148
+ if (!payload || typeof payload !== 'object') return;
149
+ var type = payload.type;
150
+ if (type === 'chat-config') {
151
+ window.__chatBridge._config = payload;
152
+ } else if (type === 'chat-push-state') {
153
+ window.__chatBridge._pushState = payload.status || null;
154
+ }
155
+ _cached.push(payload);
156
+ });
157
+
158
+ window.addEventListener('message', function (e) {
159
+ var data = e.data;
160
+ if (!data || typeof data !== 'object' || !data.type) return;
161
+ if (data.type === 'chat-push-state') {
162
+ window.__chatBridge._pushState = data.status || null;
163
+ }
164
+ });
165
+ })();
166
+ `;
167
+ function buildShimUrl() {
168
+ return "data:text/javascript;base64," + btoa(WEBVIEW_SHIM);
47
169
  }
48
170
  export {
171
+ WEBVIEW_SHIM,
172
+ buildShimUrl,
49
173
  useIframeBridge
50
174
  };
51
175
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useIframeBridge.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { BridgeConfig, BridgeMessage, IframeBridgeHook } from \"./types\";\n\nexport function useIframeBridge(): IframeBridgeHook {\n const [config, setConfig] = useState<BridgeConfig | null>(null);\n const notificationCbRef = useRef<(() => void) | null>(null);\n\n const isInIframe = typeof window !== \"undefined\" && window !== window.parent;\n\n const notifyMessage = useCallback(\n (text: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-message\", text };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const notifyViewportConfig = useCallback(\n (content: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-viewport-config\", content };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const onNotificationClicked = useCallback((cb: () => void) => {\n notificationCbRef.current = cb;\n }, []);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n function handleMessage(event: MessageEvent) {\n const data = event.data as Record<string, unknown>;\n if (!data || typeof data !== \"object\" || !data.type) return;\n\n switch (data.type) {\n case \"chat-config\": {\n const configData = { ...data };\n delete configData.type;\n setConfig(configData as BridgeConfig);\n break;\n }\n case \"chat-notification-clicked\":\n notificationCbRef.current?.();\n break;\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [isInIframe]);\n\n return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };\n}\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AAGlD,SAAS,kBAAoC;AAClD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA8B,IAAI;AAC9D,QAAM,oBAAoB,OAA4B,IAAI;AAE1D,QAAM,aAAa,OAAO,WAAW,eAAe,WAAW,OAAO;AAEtE,QAAM,gBAAgB;AAAA,IACpB,CAAC,SAAiB;AAChB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,gBAAgB,KAAK;AACxD,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,uBAAuB;AAAA,IAC3B,CAAC,YAAoB;AACnB,UAAI,CAAC,WAAY;AACjB,YAAM,MAAqB,EAAE,MAAM,wBAAwB,QAAQ;AACnE,aAAO,OAAO,YAAY,KAAK,GAAG;AAAA,IACpC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,wBAAwB,YAAY,CAAC,OAAmB;AAC5D,sBAAkB,UAAU;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,CAAC,WAAY;AAEjB,aAAS,cAAc,OAAqB;AAC1C,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,KAAM;AAErD,cAAQ,KAAK,MAAM;AAAA,QACjB,KAAK,eAAe;AAClB,gBAAM,aAAa,EAAE,GAAG,KAAK;AAC7B,iBAAO,WAAW;AAClB,oBAAU,UAA0B;AACpC;AAAA,QACF;AAAA,QACA,KAAK;AACH,4BAAkB,UAAU;AAC5B;AAAA,MACJ;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,aAAa;AAChD,WAAO,MAAM,OAAO,oBAAoB,WAAW,aAAa;AAAA,EAClE,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO,EAAE,QAAQ,YAAY,eAAe,sBAAsB,sBAAsB;AAC1F;","names":[]}
1
+ {"version":3,"sources":["../src/useIframeBridge.ts","../src/shim.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { BridgeConfig, BridgeMessage, BridgePushStatus, IframeBridgeHook } from \"./types\";\n\nexport function useIframeBridge(): IframeBridgeHook {\n const [config, setConfig] = useState<BridgeConfig | null>(null);\n const [pushState, setPushState] = useState<BridgePushStatus | null>(null);\n const notificationCbRef = useRef<(() => void) | null>(null);\n const readyRef = useRef(false);\n\n const isInIframe = typeof window !== \"undefined\" && window !== window.parent;\n\n useEffect(() => {\n if (typeof window !== \"undefined\" && (window as any).__chatBridge?._pushState) {\n setPushState((window as any).__chatBridge._pushState);\n }\n }, []);\n\n const notifyMessage = useCallback(\n (text: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-message\", text };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const notifyViewportConfig = useCallback(\n (content: string) => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-viewport-config\", content };\n window.parent.postMessage(msg, \"*\");\n },\n [isInIframe],\n );\n\n const onNotificationClicked = useCallback((cb: () => void) => {\n notificationCbRef.current = cb;\n }, []);\n\n const requestPushSubscribe = useCallback(() => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-push-subscribe\" };\n window.parent.postMessage(msg, \"*\");\n }, [isInIframe]);\n\n const requestPushUnsubscribe = useCallback(() => {\n if (!isInIframe) return;\n const msg: BridgeMessage = { type: \"chat-push-unsubscribe\" };\n window.parent.postMessage(msg, \"*\");\n }, [isInIframe]);\n\n useEffect(() => {\n if (!isInIframe) return;\n if (readyRef.current) return;\n readyRef.current = true;\n\n const msg: BridgeMessage = { type: \"chat-ready\" };\n if (typeof window.parent.postMessage === \"function\") {\n window.parent.postMessage(msg, \"*\");\n }\n }, [isInIframe]);\n\n useEffect(() => {\n if (!isInIframe) return;\n\n function handleMessage(event: MessageEvent) {\n const data = event.data as Record<string, unknown>;\n if (!data || typeof data !== \"object\" || !data.type) return;\n\n switch (data.type) {\n case \"chat-config\": {\n const configData = { ...data };\n delete configData.type;\n setConfig(configData as BridgeConfig);\n break;\n }\n case \"chat-notification-clicked\":\n notificationCbRef.current?.();\n break;\n case \"chat-push-state\":\n if (typeof data.status === \"string\") {\n setPushState(data.status as BridgePushStatus);\n }\n break;\n }\n }\n\n function handleCustomEvent(event: Event) {\n const detail = (event as CustomEvent).detail;\n if (!detail || typeof detail !== \"object\") return;\n if (detail.type === \"chat-push-state\" && typeof detail.status === \"string\") {\n setPushState(detail.status as BridgePushStatus);\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"chat-bridge\", handleCustomEvent);\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"chat-bridge\", handleCustomEvent);\n };\n }, [isInIframe]);\n\n return {\n config,\n isInIframe,\n notifyMessage,\n notifyViewportConfig,\n onNotificationClicked,\n pushState,\n requestPushSubscribe,\n requestPushUnsubscribe,\n };\n}\n","export const WEBVIEW_SHIM: string = `\n(function () {\n 'use strict';\n var _cached = [];\n var _originalPostMessage = window.parent && window.parent.postMessage;\n\n function _send(msg) {\n try {\n var json = JSON.stringify(msg);\n } catch (e) {\n var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });\n try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}\n console.error('[ChatBridge] JSON.stringify failed:', e);\n return;\n }\n try {\n if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {\n window.ReactNativeWebView.postMessage(json);\n } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {\n window.AndroidBridge.postMessage(json);\n } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {\n window.webkit.messageHandlers.chatBridge.postMessage(msg);\n } else if (_originalPostMessage) {\n _originalPostMessage.call(window.parent, msg, '*');\n } else {\n console.warn('[ChatBridge] No bridge API detected');\n }\n } catch (e) {\n var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });\n try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}\n console.error('[ChatBridge] postMessage failed:', e);\n }\n }\n\n window.__chatBridge = {\n _pushState: null,\n send: function (msg) { _send(msg); },\n setPushState: function (status) { window.__chatBridge._pushState = status; },\n };\n\n var _batches = 0;\n window.addEventListener('chat-bridge', function (e) {\n if (_batches++ > 0) return;\n requestAnimationFrame(function () {\n _batches = 0;\n });\n var payload = e.detail;\n if (!payload || typeof payload !== 'object') return;\n var type = payload.type;\n if (type === 'chat-config') {\n window.__chatBridge._config = payload;\n } else if (type === 'chat-push-state') {\n window.__chatBridge._pushState = payload.status || null;\n }\n _cached.push(payload);\n });\n\n window.addEventListener('message', function (e) {\n var data = e.data;\n if (!data || typeof data !== 'object' || !data.type) return;\n if (data.type === 'chat-push-state') {\n window.__chatBridge._pushState = data.status || null;\n }\n });\n})();\n`;\n\nexport function buildShimUrl(): string {\n return \"data:text/javascript;base64,\" + btoa(WEBVIEW_SHIM);\n}\n"],"mappings":"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","names":[]}
package/dist/shim.cjs ADDED
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/shim.ts
21
+ var shim_exports = {};
22
+ __export(shim_exports, {
23
+ WEBVIEW_SHIM: () => WEBVIEW_SHIM,
24
+ buildShimUrl: () => buildShimUrl
25
+ });
26
+ module.exports = __toCommonJS(shim_exports);
27
+ var WEBVIEW_SHIM = `
28
+ (function () {
29
+ 'use strict';
30
+ var _cached = [];
31
+ var _originalPostMessage = window.parent && window.parent.postMessage;
32
+
33
+ function _send(msg) {
34
+ try {
35
+ var json = JSON.stringify(msg);
36
+ } catch (e) {
37
+ var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });
38
+ try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}
39
+ console.error('[ChatBridge] JSON.stringify failed:', e);
40
+ return;
41
+ }
42
+ try {
43
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
44
+ window.ReactNativeWebView.postMessage(json);
45
+ } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {
46
+ window.AndroidBridge.postMessage(json);
47
+ } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {
48
+ window.webkit.messageHandlers.chatBridge.postMessage(msg);
49
+ } else if (_originalPostMessage) {
50
+ _originalPostMessage.call(window.parent, msg, '*');
51
+ } else {
52
+ console.warn('[ChatBridge] No bridge API detected');
53
+ }
54
+ } catch (e) {
55
+ var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });
56
+ try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}
57
+ console.error('[ChatBridge] postMessage failed:', e);
58
+ }
59
+ }
60
+
61
+ window.__chatBridge = {
62
+ _pushState: null,
63
+ send: function (msg) { _send(msg); },
64
+ setPushState: function (status) { window.__chatBridge._pushState = status; },
65
+ };
66
+
67
+ var _batches = 0;
68
+ window.addEventListener('chat-bridge', function (e) {
69
+ if (_batches++ > 0) return;
70
+ requestAnimationFrame(function () {
71
+ _batches = 0;
72
+ });
73
+ var payload = e.detail;
74
+ if (!payload || typeof payload !== 'object') return;
75
+ var type = payload.type;
76
+ if (type === 'chat-config') {
77
+ window.__chatBridge._config = payload;
78
+ } else if (type === 'chat-push-state') {
79
+ window.__chatBridge._pushState = payload.status || null;
80
+ }
81
+ _cached.push(payload);
82
+ });
83
+
84
+ window.addEventListener('message', function (e) {
85
+ var data = e.data;
86
+ if (!data || typeof data !== 'object' || !data.type) return;
87
+ if (data.type === 'chat-push-state') {
88
+ window.__chatBridge._pushState = data.status || null;
89
+ }
90
+ });
91
+ })();
92
+ `;
93
+ function buildShimUrl() {
94
+ return "data:text/javascript;base64," + btoa(WEBVIEW_SHIM);
95
+ }
96
+ // Annotate the CommonJS export names for ESM import in node:
97
+ 0 && (module.exports = {
98
+ WEBVIEW_SHIM,
99
+ buildShimUrl
100
+ });
101
+ //# sourceMappingURL=shim.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["export const WEBVIEW_SHIM: string = `\n(function () {\n 'use strict';\n var _cached = [];\n var _originalPostMessage = window.parent && window.parent.postMessage;\n\n function _send(msg) {\n try {\n var json = JSON.stringify(msg);\n } catch (e) {\n var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });\n try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}\n console.error('[ChatBridge] JSON.stringify failed:', e);\n return;\n }\n try {\n if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {\n window.ReactNativeWebView.postMessage(json);\n } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {\n window.AndroidBridge.postMessage(json);\n } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {\n window.webkit.messageHandlers.chatBridge.postMessage(msg);\n } else if (_originalPostMessage) {\n _originalPostMessage.call(window.parent, msg, '*');\n } else {\n console.warn('[ChatBridge] No bridge API detected');\n }\n } catch (e) {\n var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });\n try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}\n console.error('[ChatBridge] postMessage failed:', e);\n }\n }\n\n window.__chatBridge = {\n _pushState: null,\n send: function (msg) { _send(msg); },\n setPushState: function (status) { window.__chatBridge._pushState = status; },\n };\n\n var _batches = 0;\n window.addEventListener('chat-bridge', function (e) {\n if (_batches++ > 0) return;\n requestAnimationFrame(function () {\n _batches = 0;\n });\n var payload = e.detail;\n if (!payload || typeof payload !== 'object') return;\n var type = payload.type;\n if (type === 'chat-config') {\n window.__chatBridge._config = payload;\n } else if (type === 'chat-push-state') {\n window.__chatBridge._pushState = payload.status || null;\n }\n _cached.push(payload);\n });\n\n window.addEventListener('message', function (e) {\n var data = e.data;\n if (!data || typeof data !== 'object' || !data.type) return;\n if (data.type === 'chat-push-state') {\n window.__chatBridge._pushState = data.status || null;\n }\n });\n})();\n`;\n\nexport function buildShimUrl(): string {\n return \"data:text/javascript;base64,\" + btoa(WEBVIEW_SHIM);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmE7B,SAAS,eAAuB;AACrC,SAAO,iCAAiC,KAAK,YAAY;AAC3D;","names":[]}
package/dist/shim.js ADDED
@@ -0,0 +1,75 @@
1
+ // src/shim.ts
2
+ var WEBVIEW_SHIM = `
3
+ (function () {
4
+ 'use strict';
5
+ var _cached = [];
6
+ var _originalPostMessage = window.parent && window.parent.postMessage;
7
+
8
+ function _send(msg) {
9
+ try {
10
+ var json = JSON.stringify(msg);
11
+ } catch (e) {
12
+ var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });
13
+ try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}
14
+ console.error('[ChatBridge] JSON.stringify failed:', e);
15
+ return;
16
+ }
17
+ try {
18
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
19
+ window.ReactNativeWebView.postMessage(json);
20
+ } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {
21
+ window.AndroidBridge.postMessage(json);
22
+ } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {
23
+ window.webkit.messageHandlers.chatBridge.postMessage(msg);
24
+ } else if (_originalPostMessage) {
25
+ _originalPostMessage.call(window.parent, msg, '*');
26
+ } else {
27
+ console.warn('[ChatBridge] No bridge API detected');
28
+ }
29
+ } catch (e) {
30
+ var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });
31
+ try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}
32
+ console.error('[ChatBridge] postMessage failed:', e);
33
+ }
34
+ }
35
+
36
+ window.__chatBridge = {
37
+ _pushState: null,
38
+ send: function (msg) { _send(msg); },
39
+ setPushState: function (status) { window.__chatBridge._pushState = status; },
40
+ };
41
+
42
+ var _batches = 0;
43
+ window.addEventListener('chat-bridge', function (e) {
44
+ if (_batches++ > 0) return;
45
+ requestAnimationFrame(function () {
46
+ _batches = 0;
47
+ });
48
+ var payload = e.detail;
49
+ if (!payload || typeof payload !== 'object') return;
50
+ var type = payload.type;
51
+ if (type === 'chat-config') {
52
+ window.__chatBridge._config = payload;
53
+ } else if (type === 'chat-push-state') {
54
+ window.__chatBridge._pushState = payload.status || null;
55
+ }
56
+ _cached.push(payload);
57
+ });
58
+
59
+ window.addEventListener('message', function (e) {
60
+ var data = e.data;
61
+ if (!data || typeof data !== 'object' || !data.type) return;
62
+ if (data.type === 'chat-push-state') {
63
+ window.__chatBridge._pushState = data.status || null;
64
+ }
65
+ });
66
+ })();
67
+ `;
68
+ function buildShimUrl() {
69
+ return "data:text/javascript;base64," + btoa(WEBVIEW_SHIM);
70
+ }
71
+ export {
72
+ WEBVIEW_SHIM,
73
+ buildShimUrl
74
+ };
75
+ //# sourceMappingURL=shim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shim.ts"],"sourcesContent":["export const WEBVIEW_SHIM: string = `\n(function () {\n 'use strict';\n var _cached = [];\n var _originalPostMessage = window.parent && window.parent.postMessage;\n\n function _send(msg) {\n try {\n var json = JSON.stringify(msg);\n } catch (e) {\n var errJson = JSON.stringify({ type: 'chat-error', code: 'SERIALIZE_ERROR', message: 'Failed to serialize message' + e.message });\n try { if (window.parent) window.parent.postMessage(errJson, '*'); } catch (_) {}\n console.error('[ChatBridge] JSON.stringify failed:', e);\n return;\n }\n try {\n if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {\n window.ReactNativeWebView.postMessage(json);\n } else if (window.AndroidBridge && window.AndroidBridge.postMessage) {\n window.AndroidBridge.postMessage(json);\n } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.chatBridge) {\n window.webkit.messageHandlers.chatBridge.postMessage(msg);\n } else if (_originalPostMessage) {\n _originalPostMessage.call(window.parent, msg, '*');\n } else {\n console.warn('[ChatBridge] No bridge API detected');\n }\n } catch (e) {\n var fallback = JSON.stringify({ type: 'chat-error', code: 'BRIDGE_ERROR', message: 'Bridge postMessage failed: ' + e.message });\n try { if (window.parent) window.parent.postMessage(fallback, '*'); } catch (_) {}\n console.error('[ChatBridge] postMessage failed:', e);\n }\n }\n\n window.__chatBridge = {\n _pushState: null,\n send: function (msg) { _send(msg); },\n setPushState: function (status) { window.__chatBridge._pushState = status; },\n };\n\n var _batches = 0;\n window.addEventListener('chat-bridge', function (e) {\n if (_batches++ > 0) return;\n requestAnimationFrame(function () {\n _batches = 0;\n });\n var payload = e.detail;\n if (!payload || typeof payload !== 'object') return;\n var type = payload.type;\n if (type === 'chat-config') {\n window.__chatBridge._config = payload;\n } else if (type === 'chat-push-state') {\n window.__chatBridge._pushState = payload.status || null;\n }\n _cached.push(payload);\n });\n\n window.addEventListener('message', function (e) {\n var data = e.data;\n if (!data || typeof data !== 'object' || !data.type) return;\n if (data.type === 'chat-push-state') {\n window.__chatBridge._pushState = data.status || null;\n }\n });\n})();\n`;\n\nexport function buildShimUrl(): string {\n return \"data:text/javascript;base64,\" + btoa(WEBVIEW_SHIM);\n}\n"],"mappings":";AAAO,IAAM,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmE7B,SAAS,eAAuB;AACrC,SAAO,iCAAiC,KAAK,YAAY;AAC3D;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bootdesk/chat-widget-bridge",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Iframe bridge for BootDesk Chat SDK - enables embedding the chat widget in an iframe with cross-frame communication via postMessage",
5
5
  "repository": "https://github.com/bootdesk/chat-sdk",
6
6
  "type": "module",
@@ -16,6 +16,10 @@
16
16
  "./embed-chat": {
17
17
  "import": "./dist/embed-chat.js",
18
18
  "require": "./dist/embed-chat.cjs"
19
+ },
20
+ "./shim": {
21
+ "import": "./dist/shim.js",
22
+ "require": "./dist/shim.cjs"
19
23
  }
20
24
  },
21
25
  "files": [