@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.
- package/dist/browser/css/dialog.css +1 -1
- package/dist/browser/css/drawer.css +1 -1
- package/dist/browser/css/popover.css +1 -1
- package/dist/browser/embed.js +2 -2
- package/dist/package/css/dialog.css +1 -1
- package/dist/package/css/drawer.css +1 -1
- package/dist/package/css/popover.css +1 -1
- package/dist/package/package.cjs +225 -101
- package/dist/package/package.mjs +225 -101
- package/dist/package/types/core/button-options.d.ts +13 -0
- package/dist/package/types/core/button-options.d.ts.map +1 -1
- package/dist/package/types/core/create-iframe.d.ts +2 -0
- package/dist/package/types/core/create-iframe.d.ts.map +1 -1
- package/dist/package/types/core/embed-types.d.ts +12 -0
- package/dist/package/types/core/embed-types.d.ts.map +1 -1
- package/dist/package/types/core/iframe-messages.d.ts +6 -0
- package/dist/package/types/core/iframe-messages.d.ts.map +1 -0
- package/dist/package/types/factories/create-dialog/create-dialog.d.ts +2 -1
- package/dist/package/types/factories/create-dialog/create-dialog.d.ts.map +1 -1
- package/dist/package/types/factories/create-drawer/create-drawer.d.ts +2 -2
- package/dist/package/types/factories/create-drawer/create-drawer.d.ts.map +1 -1
- package/dist/package/types/factories/create-popover/create-popover.d.ts +2 -1
- package/dist/package/types/factories/create-popover/create-popover.d.ts.map +1 -1
- package/dist/package/types/factories/create-widget/create-widget.d.ts +2 -1
- package/dist/package/types/factories/create-widget/create-widget.d.ts.map +1 -1
- package/dist/package/types/package.d.ts +1 -0
- package/dist/package/types/package.d.ts.map +1 -1
- package/dist/package/types/utils/brand-types.d.ts +7 -0
- package/dist/package/types/utils/brand-types.d.ts.map +1 -1
- package/dist/package/types/utils/built-button/built-button.d.ts.map +1 -1
- package/dist/package/types/utils/create-closing-guard.d.ts +6 -0
- package/dist/package/types/utils/create-closing-guard.d.ts.map +1 -0
- package/dist/package/types/utils/icons.d.ts +3 -0
- package/dist/package/types/utils/icons.d.ts.map +1 -0
- package/dist/package/types/utils/open-state-store/index.d.ts +2 -0
- package/dist/package/types/utils/open-state-store/index.d.ts.map +1 -0
- package/dist/package/types/utils/open-state-store/open-state-store.d.ts +18 -0
- package/dist/package/types/utils/open-state-store/open-state-store.d.ts.map +1 -0
- package/dist/package/types/utils/open-state-store/open-state-store.spec.d.ts +2 -0
- package/dist/package/types/utils/open-state-store/open-state-store.spec.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/package/package.mjs
CHANGED
|
@@ -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(
|
|
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))
|
|
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))
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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))
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
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;
|
|
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 @@
|
|
|
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
|
|
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;
|
|
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
|
|
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;
|
|
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;
|
|
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
|
|
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;
|
|
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"}
|
|
@@ -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"}
|