@revvue/embed 0.0.0-beta.2 → 0.0.0-beta.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.
Files changed (41) hide show
  1. package/dist/browser/css/dialog.css +1 -1
  2. package/dist/browser/css/drawer.css +1 -1
  3. package/dist/browser/css/popover.css +1 -1
  4. package/dist/browser/embed.js +2 -2
  5. package/dist/package/css/dialog.css +1 -1
  6. package/dist/package/css/drawer.css +1 -1
  7. package/dist/package/css/popover.css +1 -1
  8. package/dist/package/package.cjs +225 -101
  9. package/dist/package/package.mjs +225 -101
  10. package/dist/package/types/core/button-options.d.ts +13 -0
  11. package/dist/package/types/core/button-options.d.ts.map +1 -1
  12. package/dist/package/types/core/create-iframe.d.ts +2 -0
  13. package/dist/package/types/core/create-iframe.d.ts.map +1 -1
  14. package/dist/package/types/core/embed-types.d.ts +12 -0
  15. package/dist/package/types/core/embed-types.d.ts.map +1 -1
  16. package/dist/package/types/core/iframe-messages.d.ts +6 -0
  17. package/dist/package/types/core/iframe-messages.d.ts.map +1 -0
  18. package/dist/package/types/factories/create-dialog/create-dialog.d.ts +2 -1
  19. package/dist/package/types/factories/create-dialog/create-dialog.d.ts.map +1 -1
  20. package/dist/package/types/factories/create-drawer/create-drawer.d.ts +2 -2
  21. package/dist/package/types/factories/create-drawer/create-drawer.d.ts.map +1 -1
  22. package/dist/package/types/factories/create-popover/create-popover.d.ts +2 -1
  23. package/dist/package/types/factories/create-popover/create-popover.d.ts.map +1 -1
  24. package/dist/package/types/factories/create-widget/create-widget.d.ts +2 -1
  25. package/dist/package/types/factories/create-widget/create-widget.d.ts.map +1 -1
  26. package/dist/package/types/package.d.ts +1 -0
  27. package/dist/package/types/package.d.ts.map +1 -1
  28. package/dist/package/types/utils/brand-types.d.ts +7 -0
  29. package/dist/package/types/utils/brand-types.d.ts.map +1 -1
  30. package/dist/package/types/utils/built-button/built-button.d.ts.map +1 -1
  31. package/dist/package/types/utils/create-closing-guard.d.ts +6 -0
  32. package/dist/package/types/utils/create-closing-guard.d.ts.map +1 -0
  33. package/dist/package/types/utils/icons.d.ts +3 -0
  34. package/dist/package/types/utils/icons.d.ts.map +1 -0
  35. package/dist/package/types/utils/open-state-store/index.d.ts +2 -0
  36. package/dist/package/types/utils/open-state-store/index.d.ts.map +1 -0
  37. package/dist/package/types/utils/open-state-store/open-state-store.d.ts +18 -0
  38. package/dist/package/types/utils/open-state-store/open-state-store.d.ts.map +1 -0
  39. package/dist/package/types/utils/open-state-store/open-state-store.spec.d.ts +2 -0
  40. package/dist/package/types/utils/open-state-store/open-state-store.spec.d.ts.map +1 -0
  41. package/package.json +1 -1
@@ -16,6 +16,12 @@ function refreshIframe(iframe) {
16
16
  }
17
17
  }
18
18
  //#endregion
19
+ //#region src/core/iframe-messages.ts
20
+ var IFRAME_MESSAGES = {
21
+ close: "rvv-embed-close",
22
+ focus: "rvv-embed-focus"
23
+ };
24
+ //#endregion
19
25
  //#region src/core/create-iframe.ts
20
26
  function getIframeSrc() {
21
27
  return "http://localhost:5173/";
@@ -31,13 +37,52 @@ function createIframe(_options) {
31
37
  iframe.id = embedId;
32
38
  const refresh = () => refreshIframe(iframe);
33
39
  const focus = () => {
34
- iframe.contentWindow?.postMessage("rvv-embed-focus", "*");
40
+ iframe.contentWindow?.postMessage(IFRAME_MESSAGES.focus, "*");
41
+ };
42
+ const onMessage = (handler) => {
43
+ const listener = (event) => {
44
+ if (event.source !== iframe.contentWindow) return;
45
+ handler(event.data);
46
+ };
47
+ window.addEventListener("message", listener);
48
+ return () => window.removeEventListener("message", listener);
35
49
  };
36
50
  return {
37
51
  iframe,
38
52
  focus,
39
53
  refresh,
40
- embedId
54
+ embedId,
55
+ onMessage
56
+ };
57
+ }
58
+ //#endregion
59
+ //#region src/utils/create-closing-guard.ts
60
+ function createClosingGuard() {
61
+ let cancelClose = null;
62
+ function isClosing() {
63
+ return cancelClose !== null;
64
+ }
65
+ function scheduleClose(element, onDone) {
66
+ const abortController = new AbortController();
67
+ element.addEventListener("transitionend", () => {
68
+ cancelClose = null;
69
+ onDone();
70
+ }, {
71
+ signal: abortController.signal,
72
+ once: true
73
+ });
74
+ cancelClose = () => {
75
+ abortController.abort();
76
+ cancelClose = null;
77
+ };
78
+ }
79
+ function cancelPendingClose() {
80
+ cancelClose?.();
81
+ }
82
+ return {
83
+ isClosing,
84
+ scheduleClose,
85
+ cancelPendingClose
41
86
  };
42
87
  }
43
88
  //#endregion
@@ -72,6 +117,26 @@ function onEscape(callback) {
72
117
  });
73
118
  }
74
119
  //#endregion
120
+ //#region src/utils/open-state-store/open-state-store.ts
121
+ function createOpenStateStore(initial = false) {
122
+ let state = initial;
123
+ const listeners = /* @__PURE__ */ new Set();
124
+ return {
125
+ getState: () => state,
126
+ setState(next) {
127
+ if (state === next) return;
128
+ state = next;
129
+ for (const listener of listeners) listener();
130
+ },
131
+ subscribe(listener) {
132
+ listeners.add(listener);
133
+ return () => {
134
+ listeners.delete(listener);
135
+ };
136
+ }
137
+ };
138
+ }
139
+ //#endregion
75
140
  //#region src/utils/set-element-size.ts
76
141
  var getValueWithUnits = (value) => {
77
142
  if (typeof value === "string" && !value.match(/^[0-9]+$/)) return value;
@@ -84,6 +149,7 @@ var setElementSize = (element, { width, height }) => {
84
149
  };
85
150
  //#endregion
86
151
  //#region src/factories/create-dialog/create-dialog.ts
152
+ var noop$3 = () => {};
87
153
  function createDialogElement() {
88
154
  const container = document.createElement("dialog");
89
155
  container.classList.add("rvv-dialog");
@@ -98,15 +164,18 @@ function unmountElement$2(element) {
98
164
  element.remove();
99
165
  }
100
166
  function createDialog(options, element) {
167
+ const store = createOpenStateStore();
101
168
  if (!is.browser()) return {
102
- toggle: () => {},
103
- open: () => {},
104
- close: () => {},
105
- unmount: () => {},
106
- refresh: () => {},
107
- focus: () => {}
169
+ toggle: noop$3,
170
+ open: noop$3,
171
+ close: noop$3,
172
+ unmount: noop$3,
173
+ refresh: noop$3,
174
+ focus: noop$3,
175
+ isOpen: store.getState,
176
+ subscribe: store.subscribe
108
177
  };
109
- const { iframe, refresh, focus } = createIframe(options);
178
+ const { iframe, refresh, focus, onMessage } = createIframe(options);
110
179
  const container = element ?? document.body;
111
180
  const dialog = createDialogElement();
112
181
  const wrapper = createDialogWrapper();
@@ -122,21 +191,35 @@ function createDialog(options, element) {
122
191
  onEscape(close);
123
192
  }
124
193
  };
194
+ const guard = createClosingGuard();
125
195
  function open() {
126
- if (is.open(wrapper)) return;
196
+ if (is.open(wrapper)) {
197
+ if (guard.isClosing()) {
198
+ guard.cancelPendingClose();
199
+ store.setState(true);
200
+ return;
201
+ }
202
+ return;
203
+ }
127
204
  dialog.append(wrapper);
128
205
  dialog.showModal();
206
+ store.setState(true);
129
207
  }
130
208
  function close() {
131
209
  if (!is.open(wrapper)) return;
132
210
  dialog.close();
133
- unmountElement$2(wrapper);
211
+ guard.scheduleClose(dialog, () => unmountElement$2(wrapper));
212
+ store.setState(false);
134
213
  }
135
214
  function toggle() {
136
215
  is.open(wrapper) ? close() : open();
137
216
  }
217
+ const removeOnMessageHandler = onMessage((msg) => {
218
+ if (msg === IFRAME_MESSAGES.close) close();
219
+ });
138
220
  function unmount() {
139
221
  unmountElement$2(dialog);
222
+ removeOnMessageHandler();
140
223
  }
141
224
  return {
142
225
  toggle,
@@ -144,59 +227,14 @@ function createDialog(options, element) {
144
227
  close,
145
228
  unmount,
146
229
  refresh,
147
- focus
148
- };
149
- }
150
- //#endregion
151
- //#region src/utils/built-button/built-button.ts
152
- var defaultIcon = `
153
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square-icon lucide-message-square"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg>`;
154
- var closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`;
155
- function buildDefaultIcons() {
156
- const openEl = document.createElement("span");
157
- openEl.classList.add("rvv-button-icon--open");
158
- openEl.innerHTML = defaultIcon;
159
- const closeEl = document.createElement("span");
160
- closeEl.classList.add("rvv-button-icon--close");
161
- closeEl.innerHTML = closeIcon;
162
- return {
163
- openEl,
164
- closeEl
165
- };
166
- }
167
- function buildButtonElement(options) {
168
- const button = document.createElement("button");
169
- button.classList.add("rvv-button", "rvv-button--trigger");
170
- button.setAttribute("type", "button");
171
- button.dataset.position = options.position ?? "right";
172
- button.dataset.open = "false";
173
- if (options.color) button.style.setProperty("--rvv-button-color", options.color);
174
- if (options.textColor) button.style.setProperty("--rvv-button-text-color", options.textColor);
175
- const iconWrapper = document.createElement("span");
176
- iconWrapper.classList.add("rvv-button-icon");
177
- iconWrapper.setAttribute("aria-hidden", "true");
178
- if (options.label) {
179
- const labelEl = document.createElement("span");
180
- labelEl.classList.add("rvv-button-label");
181
- labelEl.textContent = options.label;
182
- button.append(labelEl);
183
- }
184
- if (options.icon) iconWrapper.innerHTML = options.icon;
185
- else if (!options.label) {
186
- const { openEl, closeEl } = buildDefaultIcons();
187
- iconWrapper.append(openEl, closeEl);
188
- }
189
- if (iconWrapper.childNodes.length > 0) button.append(iconWrapper);
190
- function setOpen(isOpen) {
191
- button.dataset.open = String(isOpen);
192
- }
193
- return {
194
- el: button,
195
- setOpen
230
+ focus,
231
+ isOpen: store.getState,
232
+ subscribe: store.subscribe
196
233
  };
197
234
  }
198
235
  //#endregion
199
236
  //#region src/factories/create-drawer/create-drawer.ts
237
+ var noop$2 = () => {};
200
238
  function createDrawerElement() {
201
239
  const container = document.createElement("div");
202
240
  container.classList.add("rvv-drawer");
@@ -211,15 +249,18 @@ function unmountElement$1(element) {
211
249
  element.remove();
212
250
  }
213
251
  function createDrawer(options, element) {
252
+ const store = createOpenStateStore();
214
253
  if (!is.browser()) return {
215
- toggle: () => {},
216
- open: () => {},
217
- close: () => {},
218
- unmount: () => {},
219
- refresh: () => {},
220
- focus: () => {}
254
+ toggle: noop$2,
255
+ open: noop$2,
256
+ close: noop$2,
257
+ unmount: noop$2,
258
+ refresh: noop$2,
259
+ focus: noop$2,
260
+ isOpen: store.getState,
261
+ subscribe: store.subscribe
221
262
  };
222
- const { iframe, refresh, focus } = createIframe(options);
263
+ const { iframe, refresh, focus, onMessage } = createIframe(options);
223
264
  const container = element ?? document.body;
224
265
  const drawer = createDrawerElement();
225
266
  const wrapper = createDrawerWrapper();
@@ -229,49 +270,106 @@ function createDrawer(options, element) {
229
270
  });
230
271
  container.append(drawer);
231
272
  wrapper.append(iframe);
232
- const { autoOpen = false, autoOpenDelay = 0 } = options;
233
- let setButtonOpen = () => {};
234
- const { el: buttonEl, setOpen } = buildButtonElement(options);
235
- setButtonOpen = setOpen;
236
- buttonEl.addEventListener("click", () => toggle());
237
- document.body.append(buttonEl);
238
273
  iframe.onload = (event) => {
239
274
  if (event?.isTrusted) {
240
275
  drawer.classList.add("open");
241
276
  onEscape(close);
242
277
  }
243
278
  };
279
+ const guard = createClosingGuard();
244
280
  function open() {
245
- if (is.open(wrapper)) return;
281
+ if (is.open(wrapper)) {
282
+ if (guard.isClosing()) {
283
+ guard.cancelPendingClose();
284
+ drawer.classList.add("open");
285
+ store.setState(true);
286
+ return;
287
+ }
288
+ return;
289
+ }
246
290
  drawer.append(wrapper);
247
- setButtonOpen(true);
291
+ store.setState(true);
248
292
  }
249
293
  function close() {
250
294
  if (!is.open(wrapper)) return;
251
- unmountElement$1(wrapper);
252
295
  drawer.classList.remove("open");
253
- setButtonOpen(false);
296
+ store.setState(false);
297
+ guard.scheduleClose(drawer, () => unmountElement$1(wrapper));
254
298
  }
255
299
  function toggle() {
256
300
  is.open(wrapper) ? close() : open();
257
301
  }
302
+ const removeOnMessageHandler = onMessage((msg) => {
303
+ if (msg === IFRAME_MESSAGES.close) close();
304
+ });
258
305
  function unmount() {
259
- buttonEl?.remove();
260
306
  unmountElement$1(drawer);
307
+ removeOnMessageHandler();
261
308
  }
262
- if (autoOpen) if (autoOpenDelay > 0) setTimeout(() => open(), autoOpenDelay);
263
- else open();
264
309
  return {
265
310
  toggle,
266
311
  open,
267
312
  close,
268
313
  unmount,
269
314
  refresh,
270
- focus
315
+ focus,
316
+ isOpen: store.getState,
317
+ subscribe: store.subscribe
318
+ };
319
+ }
320
+ //#endregion
321
+ //#region src/utils/icons.ts
322
+ var chatIcon = `
323
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square-icon lucide-message-square"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg>`;
324
+ var closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`;
325
+ //#endregion
326
+ //#region src/utils/built-button/built-button.ts
327
+ function buildDefaultIcons() {
328
+ const openEl = document.createElement("span");
329
+ openEl.classList.add("rvv-button-icon--open");
330
+ openEl.innerHTML = chatIcon;
331
+ const closeEl = document.createElement("span");
332
+ closeEl.classList.add("rvv-button-icon--close");
333
+ closeEl.innerHTML = closeIcon;
334
+ return {
335
+ openEl,
336
+ closeEl
337
+ };
338
+ }
339
+ function buildButtonElement(options) {
340
+ const button = document.createElement("button");
341
+ button.classList.add("rvv-button", "rvv-button--trigger");
342
+ button.setAttribute("type", "button");
343
+ button.dataset.position = options.position ?? "right";
344
+ button.dataset.open = "false";
345
+ if (options.color) button.style.setProperty("--rvv-button-color", options.color);
346
+ if (options.textColor) button.style.setProperty("--rvv-button-text-color", options.textColor);
347
+ const iconWrapper = document.createElement("span");
348
+ iconWrapper.classList.add("rvv-button-icon");
349
+ iconWrapper.setAttribute("aria-hidden", "true");
350
+ if (options.label) {
351
+ const labelEl = document.createElement("span");
352
+ labelEl.classList.add("rvv-button-label");
353
+ labelEl.textContent = options.label;
354
+ button.append(labelEl);
355
+ }
356
+ if (options.icon) iconWrapper.innerHTML = options.icon;
357
+ else if (!options.label) {
358
+ const { openEl, closeEl } = buildDefaultIcons();
359
+ iconWrapper.append(openEl, closeEl);
360
+ }
361
+ if (iconWrapper.childNodes.length > 0) button.append(iconWrapper);
362
+ function setOpen(isOpen) {
363
+ button.dataset.open = String(isOpen);
364
+ }
365
+ return {
366
+ el: button,
367
+ setOpen
271
368
  };
272
369
  }
273
370
  //#endregion
274
371
  //#region src/factories/create-popover/create-popover.ts
372
+ var noop$1 = () => {};
275
373
  function createPopoverElement() {
276
374
  const container = document.createElement("div");
277
375
  container.classList.add("rvv-popover");
@@ -286,15 +384,18 @@ function unmountElement(element) {
286
384
  element.remove();
287
385
  }
288
386
  function createPopover(options, element) {
387
+ const store = createOpenStateStore();
289
388
  if (!is.browser()) return {
290
- toggle: () => {},
291
- close: () => {},
292
- open: () => {},
293
- unmount: () => {},
294
- refresh: () => {},
295
- focus: () => {}
389
+ toggle: noop$1,
390
+ close: noop$1,
391
+ open: noop$1,
392
+ unmount: noop$1,
393
+ refresh: noop$1,
394
+ focus: noop$1,
395
+ isOpen: store.getState,
396
+ subscribe: store.subscribe
296
397
  };
297
- const { iframe, refresh, focus } = createIframe(options);
398
+ const { iframe, refresh, focus, onMessage } = createIframe(options);
298
399
  const container = element ?? document.body;
299
400
  const popover = createPopoverElement();
300
401
  const wrapper = createPopoverWrapper();
@@ -304,12 +405,17 @@ function createPopover(options, element) {
304
405
  });
305
406
  container.append(popover);
306
407
  wrapper.append(iframe);
307
- const { autoOpen = false, autoOpenDelay = 0 } = options;
308
- let setButtonOpen = () => {};
309
- const { el: buttonEl, setOpen } = buildButtonElement(options);
310
- setButtonOpen = setOpen;
311
- buttonEl.addEventListener("click", () => toggle());
312
- document.body.append(buttonEl);
408
+ const { autoOpen = false, autoOpenDelay = 0, trigger = "default" } = options;
409
+ let setButtonOpen = noop$1;
410
+ let unmountButton = noop$1;
411
+ if (trigger === "default") {
412
+ const { el: buttonEl, setOpen } = buildButtonElement(options);
413
+ buttonEl.classList.add("rvv-button--trigger-popover");
414
+ setButtonOpen = setOpen;
415
+ buttonEl.addEventListener("click", () => toggle());
416
+ document.body.append(buttonEl);
417
+ unmountButton = () => buttonEl.remove();
418
+ }
313
419
  function toggle() {
314
420
  is.open(wrapper) ? close() : open();
315
421
  }
@@ -319,20 +425,35 @@ function createPopover(options, element) {
319
425
  onEscape(close);
320
426
  }
321
427
  };
428
+ const guard = createClosingGuard();
322
429
  function open() {
323
- if (is.open(wrapper)) return;
430
+ if (is.open(wrapper)) {
431
+ if (guard.isClosing()) {
432
+ guard.cancelPendingClose();
433
+ popover.classList.add("open");
434
+ store.setState(true);
435
+ return;
436
+ }
437
+ return;
438
+ }
324
439
  popover.append(wrapper);
325
440
  setButtonOpen(true);
441
+ store.setState(true);
326
442
  }
327
443
  function close() {
328
444
  if (!is.open(wrapper)) return;
329
445
  popover.classList.remove("open");
330
446
  setButtonOpen(false);
331
- popover.addEventListener("transitionend", () => unmountElement(wrapper), { once: true });
447
+ store.setState(false);
448
+ guard.scheduleClose(popover, () => unmountElement(wrapper));
332
449
  }
450
+ const removeOnMessageHandler = onMessage((msg) => {
451
+ if (msg === IFRAME_MESSAGES.close) close();
452
+ });
333
453
  function unmount() {
334
- buttonEl?.remove();
454
+ unmountButton();
335
455
  unmountElement(popover);
456
+ removeOnMessageHandler();
336
457
  }
337
458
  if (autoOpen) if (autoOpenDelay > 0) setTimeout(() => open(), autoOpenDelay);
338
459
  else open();
@@ -342,16 +463,19 @@ function createPopover(options, element) {
342
463
  open,
343
464
  unmount,
344
465
  refresh,
345
- focus
466
+ focus,
467
+ isOpen: store.getState,
468
+ subscribe: store.subscribe
346
469
  };
347
470
  }
348
471
  //#endregion
349
472
  //#region src/factories/create-widget/create-widget.ts
473
+ var noop = () => {};
350
474
  function createWidget(options, element) {
351
475
  if (!is.browser()) return {
352
- unmount: () => {},
353
- refresh: () => {},
354
- focus: () => {}
476
+ unmount: noop,
477
+ refresh: noop,
478
+ focus: noop
355
479
  };
356
480
  const { iframe, refresh, focus } = createIframe(options);
357
481
  const container = element ?? document.body;
@@ -1,4 +1,17 @@
1
1
  export interface ButtonOptions {
2
+ /**
3
+ * Controls whether the factory mounts its own default trigger button.
4
+ *
5
+ * - `"default"` (default): the factory builds and appends a styled `<button>`
6
+ * to `document.body`. This is the right choice for vanilla CDN consumers.
7
+ * - `"none"`: the factory skips button creation entirely. The consumer is
8
+ * responsible for rendering their own trigger and wiring it to
9
+ * `open()` / `close()` / `toggle()`. Use this in React or any framework
10
+ * that wants to own the trigger element.
11
+ *
12
+ * @default "default"
13
+ */
14
+ trigger?: "default" | "none";
2
15
  /**
3
16
  * Text label displayed inside the button.
4
17
  * @default "Open"
@@ -1 +1 @@
1
- {"version":3,"file":"button-options.d.ts","sourceRoot":"","sources":["../../../../src/core/button-options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"button-options.d.ts","sourceRoot":"","sources":["../../../../src/core/button-options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAE7B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
@@ -1,10 +1,12 @@
1
1
  import { EmbedOptions } from './app-options';
2
+ import { IframeMessage } from './iframe-messages';
2
3
  type CreateIframeOptions = {} & EmbedOptions;
3
4
  export declare function createIframe(_options: CreateIframeOptions): {
4
5
  iframe: HTMLIFrameElement;
5
6
  focus: () => void;
6
7
  refresh: () => void;
7
8
  embedId: `${string}-${string}-${string}-${string}-${string}`;
9
+ onMessage: (handler: (message: IframeMessage) => void) => (() => void);
8
10
  };
9
11
  export {};
10
12
  //# sourceMappingURL=create-iframe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-iframe.d.ts","sourceRoot":"","sources":["../../../../src/core/create-iframe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,KAAK,mBAAmB,GAAG,EAAE,GAAG,YAAY,CAAC;AAM7C,wBAAgB,YAAY,CAAC,QAAQ,EAAE,mBAAmB;;;;;EAoBzD"}
1
+ {"version":3,"file":"create-iframe.d.ts","sourceRoot":"","sources":["../../../../src/core/create-iframe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAExE,KAAK,mBAAmB,GAAG,EAAE,GAAG,YAAY,CAAC;AAM7C,wBAAgB,YAAY,CAAC,QAAQ,EAAE,mBAAmB;;;;;yBAmB5B,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;EAU5E"}
@@ -4,9 +4,21 @@ export type EmbedWidget = {
4
4
  refresh: () => void;
5
5
  focus: () => void;
6
6
  };
7
+ /**
8
+ * Subscriber callback signature compatible with React's `useSyncExternalStore`.
9
+ * The store calls every registered listener whenever open state flips.
10
+ */
11
+ export type EmbedStateListener = () => void;
7
12
  export type EmbedFloating = EmbedWidget & {
8
13
  open: () => void;
9
14
  close: () => void;
10
15
  toggle: () => void;
16
+ /** Returns the current open state synchronously. Stable reference. */
17
+ isOpen: () => boolean;
18
+ /**
19
+ * Register a listener that fires after every open/close transition.
20
+ * Returns an unsubscribe function. Compatible with `useSyncExternalStore`.
21
+ */
22
+ subscribe: (listener: EmbedStateListener) => () => void;
11
23
  };
12
24
  //# sourceMappingURL=embed-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"embed-types.d.ts","sourceRoot":"","sources":["../../../../src/core/embed-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnE,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"embed-types.d.ts","sourceRoot":"","sources":["../../../../src/core/embed-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnE,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,sEAAsE;IACtE,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;CACzD,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const IFRAME_MESSAGES: {
2
+ readonly close: "rvv-embed-close";
3
+ readonly focus: "rvv-embed-focus";
4
+ };
5
+ export type IframeMessage = (typeof IFRAME_MESSAGES)[keyof typeof IFRAME_MESSAGES];
6
+ //# sourceMappingURL=iframe-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iframe-messages.d.ts","sourceRoot":"","sources":["../../../../src/core/iframe-messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { EmbedOptions } from '../../core/app-options';
2
2
  import { EmbedFloating } from '../../core/embed-types';
3
+ import { Public } from '../../utils/brand-types';
3
4
  export type Dialog = EmbedFloating;
4
- export declare function createDialog(options: EmbedOptions, element?: HTMLElement): Dialog;
5
+ export declare function createDialog(options: Public<EmbedOptions>, element?: HTMLElement): Dialog;
5
6
  //# sourceMappingURL=create-dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-dialog.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-dialog/create-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAK5D,MAAM,MAAM,MAAM,GAAG,aAAa,CAAC;AAkBnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAwDjF"}
1
+ {"version":3,"file":"create-dialog.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-dialog/create-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAOtD,MAAM,MAAM,MAAM,GAAG,aAAa,CAAC;AAoBnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA8EzF"}
@@ -1,6 +1,6 @@
1
1
  import { EmbedOptions } from '../../core/app-options';
2
- import { ButtonOptions } from '../../core/button-options';
3
2
  import { EmbedFloating } from '../../core/embed-types';
3
+ import { Public } from '../../utils/brand-types';
4
4
  export type Drawer = EmbedFloating;
5
- export declare function createDrawer(options: EmbedOptions & ButtonOptions, element?: HTMLElement): Drawer;
5
+ export declare function createDrawer(options: Public<EmbedOptions>, element?: HTMLElement): Drawer;
6
6
  //# sourceMappingURL=create-drawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-drawer.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-drawer/create-drawer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAM5D,MAAM,MAAM,MAAM,GAAG,aAAa,CAAC;AAkBnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,aAAa,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA2EjG"}
1
+ {"version":3,"file":"create-drawer.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-drawer/create-drawer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAOtD,MAAM,MAAM,MAAM,GAAG,aAAa,CAAC;AAoBnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA8EzF"}
@@ -1,6 +1,7 @@
1
1
  import { EmbedOptions } from '../../core/app-options';
2
2
  import { ButtonOptions } from '../../core/button-options';
3
3
  import { EmbedFloating } from '../../core/embed-types';
4
+ import { Public } from '../../utils/brand-types';
4
5
  export type Popover = EmbedFloating;
5
- export declare function createPopover(options: EmbedOptions & ButtonOptions, element?: HTMLElement): Popover;
6
+ export declare function createPopover(options: Public<EmbedOptions> & ButtonOptions, element?: HTMLElement): Popover;
6
7
  //# sourceMappingURL=create-popover.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-popover.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-popover/create-popover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAM5D,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC;AAkBpC,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,aAAa,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CA6EnG"}
1
+ {"version":3,"file":"create-popover.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-popover/create-popover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAQtD,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC;AAoBpC,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,aAAa,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CA0G3G"}
@@ -1,5 +1,6 @@
1
1
  import { EmbedOptions } from '../../core/app-options';
2
2
  import { EmbedWidget } from '../../core/embed-types';
3
+ import { Public } from '../../utils/brand-types';
3
4
  export type Widget = EmbedWidget;
4
- export declare function createWidget(options: EmbedOptions, element?: HTMLElement): Widget;
5
+ export declare function createWidget(options: Public<EmbedOptions>, element?: HTMLElement): Widget;
5
6
  //# sourceMappingURL=create-widget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-widget.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-widget/create-widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1D,MAAM,MAAM,MAAM,GAAG,WAAW,CAAC;AAEjC,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA2BjF"}
1
+ {"version":3,"file":"create-widget.d.ts","sourceRoot":"","sources":["../../../../../src/factories/create-widget/create-widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAItD,MAAM,MAAM,MAAM,GAAG,WAAW,CAAC;AAIjC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA2BzF"}
@@ -5,4 +5,5 @@ export * from './core/common';
5
5
  export * from './core/embed-apps';
6
6
  export * from './core/embed-types';
7
7
  export * from './factories';
8
+ export type { Public } from './utils/brand-types';
8
9
  //# sourceMappingURL=package.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../src/package.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../src/package.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,4 +1,11 @@
1
1
  export type Brand<T, B extends string> = T & {
2
2
  __brand: B;
3
3
  };
4
+ type Unbranded<T> = {
5
+ [K in keyof T]: T[K] extends string & {
6
+ __brand: unknown;
7
+ } ? string : T[K];
8
+ };
9
+ export type Public<T> = T extends unknown ? Unbranded<T> : never;
10
+ export {};
4
11
  //# sourceMappingURL=brand-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brand-types.d.ts","sourceRoot":"","sources":["../../../../src/utils/brand-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"brand-types.d.ts","sourceRoot":"","sources":["../../../../src/utils/brand-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAM5D,KAAK,SAAS,CAAC,CAAC,IAAI;KACjB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3E,CAAC;AAKF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC"}