@bootdesk/chat-widget-bridge 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,6 +129,8 @@ Via a `<script>` tag:
129
129
  ### Behavior
130
130
 
131
131
  - Exposes `window.ChatSDK.initialize()` to create a floating chat button, overlay, and iframe
132
+ - Exposes `window.ChatSDK.destroy()` to remove all DOM elements and event listeners
133
+ - Waits for `DOMContentLoaded` before creating elements if script runs in `<head>`
132
134
  - On click, opens a panel with the iframe (slide + fade animation)
133
135
  - On small screens (<800px) the iframe goes fullscreen and the overlay is hidden
134
136
  - Reads `localStorage` key `chat-theme` and passes it to the iframe via `chat-config`
@@ -147,6 +149,18 @@ Via a `<script>` tag:
147
149
  | `buttonStyle` | `object` | Default button styles | CSS overrides for the button |
148
150
  | `overlayStyle` | `object` | Default overlay styles | CSS overrides for the overlay |
149
151
 
152
+ ### Cleanup
153
+
154
+ Call `ChatSDK.destroy()` to remove all DOM elements (button, iframe, overlay, style) and event listeners:
155
+
156
+ ```js
157
+ // Module import
158
+ import "@bootdesk/chat-widget-bridge/embed-chat";
159
+ ChatSDK.initialize({ iframeSrc: "/chat" });
160
+ // later...
161
+ ChatSDK.destroy();
162
+ ```
163
+
150
164
  ## License
151
165
 
152
166
  MIT
@@ -41,8 +41,10 @@
41
41
  button: null,
42
42
  iframe: null,
43
43
  overlay: null,
44
+ styleEl: null,
44
45
  isOpen: false,
45
- originalViewport: void 0
46
+ originalViewport: void 0,
47
+ initialized: false
46
48
  };
47
49
  function mergeStyles(base, overrides) {
48
50
  var result = {};
@@ -124,10 +126,6 @@
124
126
  );
125
127
  });
126
128
  }
127
- function close() {
128
- if (!state.isOpen) return;
129
- toggle();
130
- }
131
129
  function toggle() {
132
130
  state.isOpen = !state.isOpen;
133
131
  var open = state.isOpen;
@@ -150,7 +148,7 @@
150
148
  console.log("[Embed Chat] Message:", data.text);
151
149
  }
152
150
  if (data.type === "chat-close") {
153
- close();
151
+ toggle();
154
152
  }
155
153
  if (data.type === "chat-viewport-config") {
156
154
  var meta = document.querySelector('meta[name="viewport"]');
@@ -167,7 +165,16 @@
167
165
  }
168
166
  }
169
167
  }
170
- function initialize(opts) {
168
+ function destroy() {
169
+ if (!state.initialized) return;
170
+ if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);
171
+ 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);
174
+ window.removeEventListener("message", handleMessage);
175
+ state.initialized = false;
176
+ }
177
+ function _initialize(opts) {
171
178
  if (document.querySelector("[data-embed-chat-btn]")) return;
172
179
  state.opts = {};
173
180
  for (var key in DEFAULTS) {
@@ -185,11 +192,22 @@
185
192
  var style = document.createElement("style");
186
193
  style.textContent = "@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; } }";
187
194
  document.head.appendChild(style);
195
+ state.styleEl = style;
188
196
  createOverlay();
189
197
  createIframe();
190
198
  createButton();
191
199
  window.addEventListener("message", handleMessage);
200
+ state.initialized = true;
201
+ }
202
+ function initialize(opts) {
203
+ if (document.readyState === "loading") {
204
+ document.addEventListener("DOMContentLoaded", function() {
205
+ _initialize(opts);
206
+ });
207
+ } else {
208
+ _initialize(opts);
209
+ }
192
210
  }
193
- window.ChatSDK = { initialize };
211
+ window.ChatSDK = { initialize, destroy };
194
212
  })();
195
213
  //# sourceMappingURL=embed-chat.cjs.map
@@ -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 isOpen: false,\n originalViewport: undefined,\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 close() {\n if (!state.isOpen) return;\n toggle();\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 close();\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 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\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n }\n\n window.ChatSDK = { initialize: initialize };\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,QAAQ;AAAA,IACR,kBAAkB;AAAA,EACpB;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,QAAQ;AACf,QAAI,CAAC,MAAM,OAAQ;AACnB,WAAO;AAAA,EACT;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,YAAM;AAAA,IACR;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,WAAW,MAAM;AACxB,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;AAE/B,kBAAc;AACd,iBAAa;AACb,iBAAa;AACb,WAAO,iBAAiB,WAAW,aAAa;AAAA,EAClD;AAEA,SAAO,UAAU,EAAE,WAAuB;AAC5C,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 { /* 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":[]}
@@ -39,8 +39,10 @@
39
39
  button: null,
40
40
  iframe: null,
41
41
  overlay: null,
42
+ styleEl: null,
42
43
  isOpen: false,
43
- originalViewport: void 0
44
+ originalViewport: void 0,
45
+ initialized: false
44
46
  };
45
47
  function mergeStyles(base, overrides) {
46
48
  var result = {};
@@ -122,10 +124,6 @@
122
124
  );
123
125
  });
124
126
  }
125
- function close() {
126
- if (!state.isOpen) return;
127
- toggle();
128
- }
129
127
  function toggle() {
130
128
  state.isOpen = !state.isOpen;
131
129
  var open = state.isOpen;
@@ -148,7 +146,7 @@
148
146
  console.log("[Embed Chat] Message:", data.text);
149
147
  }
150
148
  if (data.type === "chat-close") {
151
- close();
149
+ toggle();
152
150
  }
153
151
  if (data.type === "chat-viewport-config") {
154
152
  var meta = document.querySelector('meta[name="viewport"]');
@@ -165,7 +163,16 @@
165
163
  }
166
164
  }
167
165
  }
168
- function initialize(opts) {
166
+ function destroy() {
167
+ if (!state.initialized) return;
168
+ if (state.button && state.button.parentNode) state.button.parentNode.removeChild(state.button);
169
+ 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);
172
+ window.removeEventListener("message", handleMessage);
173
+ state.initialized = false;
174
+ }
175
+ function _initialize(opts) {
169
176
  if (document.querySelector("[data-embed-chat-btn]")) return;
170
177
  state.opts = {};
171
178
  for (var key in DEFAULTS) {
@@ -183,11 +190,22 @@
183
190
  var style = document.createElement("style");
184
191
  style.textContent = "@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; } }";
185
192
  document.head.appendChild(style);
193
+ state.styleEl = style;
186
194
  createOverlay();
187
195
  createIframe();
188
196
  createButton();
189
197
  window.addEventListener("message", handleMessage);
198
+ state.initialized = true;
199
+ }
200
+ function initialize(opts) {
201
+ if (document.readyState === "loading") {
202
+ document.addEventListener("DOMContentLoaded", function() {
203
+ _initialize(opts);
204
+ });
205
+ } else {
206
+ _initialize(opts);
207
+ }
190
208
  }
191
- window.ChatSDK = { initialize };
209
+ window.ChatSDK = { initialize, destroy };
192
210
  })();
193
211
  //# sourceMappingURL=embed-chat.js.map
@@ -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 isOpen: false,\n originalViewport: undefined,\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 close() {\n if (!state.isOpen) return;\n toggle();\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 close();\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 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\n createOverlay();\n createIframe();\n createButton();\n window.addEventListener(\"message\", handleMessage);\n }\n\n window.ChatSDK = { initialize: initialize };\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 { /* 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":[]}
package/dist/index.cjs CHANGED
@@ -38,6 +38,14 @@ function useIframeBridge() {
38
38
  },
39
39
  [isInIframe]
40
40
  );
41
+ const notifyViewportConfig = (0, import_react.useCallback)(
42
+ (content) => {
43
+ if (!isInIframe) return;
44
+ const msg = { type: "chat-viewport-config", content };
45
+ window.parent.postMessage(msg, "*");
46
+ },
47
+ [isInIframe]
48
+ );
41
49
  const onNotificationClicked = (0, import_react.useCallback)((cb) => {
42
50
  notificationCbRef.current = cb;
43
51
  }, []);
@@ -61,7 +69,7 @@ function useIframeBridge() {
61
69
  window.addEventListener("message", handleMessage);
62
70
  return () => window.removeEventListener("message", handleMessage);
63
71
  }, [isInIframe]);
64
- return { config, isInIframe, notifyMessage, onNotificationClicked };
72
+ return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };
65
73
  }
66
74
  // Annotate the CommonJS export names for ESM import in node:
67
75
  0 && (module.exports = {
@@ -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 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, 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,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;AACpE;","names":[]}
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":[]}
package/dist/index.d.cts CHANGED
@@ -10,10 +10,11 @@ interface IframeBridgeHook {
10
10
  config: BridgeConfig | null;
11
11
  isInIframe: boolean;
12
12
  notifyMessage: (text: string) => void;
13
+ notifyViewportConfig: (content: string) => void;
13
14
  onNotificationClicked: (cb: () => void) => void;
14
15
  }
15
16
  interface BridgeMessage {
16
- type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close";
17
+ type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config";
17
18
  [key: string]: unknown;
18
19
  }
19
20
 
package/dist/index.d.ts CHANGED
@@ -10,10 +10,11 @@ interface IframeBridgeHook {
10
10
  config: BridgeConfig | null;
11
11
  isInIframe: boolean;
12
12
  notifyMessage: (text: string) => void;
13
+ notifyViewportConfig: (content: string) => void;
13
14
  onNotificationClicked: (cb: () => void) => void;
14
15
  }
15
16
  interface BridgeMessage {
16
- type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close";
17
+ type: "chat-config" | "chat-message" | "chat-notification-clicked" | "chat-close" | "chat-viewport-config";
17
18
  [key: string]: unknown;
18
19
  }
19
20
 
package/dist/index.js CHANGED
@@ -12,6 +12,14 @@ function useIframeBridge() {
12
12
  },
13
13
  [isInIframe]
14
14
  );
15
+ const notifyViewportConfig = useCallback(
16
+ (content) => {
17
+ if (!isInIframe) return;
18
+ const msg = { type: "chat-viewport-config", content };
19
+ window.parent.postMessage(msg, "*");
20
+ },
21
+ [isInIframe]
22
+ );
15
23
  const onNotificationClicked = useCallback((cb) => {
16
24
  notificationCbRef.current = cb;
17
25
  }, []);
@@ -35,7 +43,7 @@ function useIframeBridge() {
35
43
  window.addEventListener("message", handleMessage);
36
44
  return () => window.removeEventListener("message", handleMessage);
37
45
  }, [isInIframe]);
38
- return { config, isInIframe, notifyMessage, onNotificationClicked };
46
+ return { config, isInIframe, notifyMessage, notifyViewportConfig, onNotificationClicked };
39
47
  }
40
48
  export {
41
49
  useIframeBridge
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 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, 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,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;AACpE;","names":[]}
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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bootdesk/chat-widget-bridge",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
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",