For Preact based element, we register a Preact component as a web component. This resolve the issue of race-condition between Bubble element initialization and code loading.
For Functional elements, we would register a retry pattern until the plugin's code is fully loaded.
-
Create a new Bubble plugin element
-
Add this piece of code into the element header
<script src="https://www.unpkg.com/preact@^10.19.3/dist/preact.umd.js"></script>
<script src="https://www.unpkg.com/preact@^10.19.3/hooks/dist/hooks.umd.js"></script>
<script src="https://www.unpkg.com/preact@^10.19.3/compat/dist/compat.umd.js"></script>
<script src="https://www.unpkg.com/preact-custom-element@^4.3.0/dist/preact-custom-element.umd.js"></script>
<script src="https://www.unpkg.com/@preact/signals-core@^1.5.1/dist/signals-core.min.js"></script>
<script src="https://www.unpkg.com/@preact/signals@^1.2.2/dist/signals.min.js"></script>
<script src="http://localhost:5173/@vite/client" type="module"></script>
<script src="http://localhost:5173/src/index.ts" type="module"></script>
-
Set the initialize
function content. You would want to match this with the web component names.
The example file has this as counter
, as shown in PasswordInput.tsx
function(instance, context) {
const ELEMENT_NAME = "counter";
instance.data._elementReady = false;
instance.data._element = document.createElement(ELEMENT_NAME);
instance.canvas.append(instance.data._element);
instance.data._tryInject = function tryInject(retryLeft, properties) {
const element = instance.data._element;
if (!retryLeft || retryLeft <= 0 || !element) {
return;
}
if (!element._vdom) {
setTimeout(() => tryInject(retryLeft - 1, properties), 200);
return;
}
element.properties = properties;
if (!element.instance) {
element.instance = instance;
}
if (!element.bubbleContext) {
element.bubbleContext = context;
}
}
-
Set the update
function content.
function(instance, properties, context) {
instance.data._tryInject(50, properties);
}
-
Set the preview
function content. Because the preview environment is isolated from the Bubble Editor environment, we have to do a full in script loading of the resources
function(instance, properties) {
function loadJS(url, module = false) {
return new Promise((resolve, reject) => {
let scriptEle = document.createElement("script");
document.head.appendChild(scriptEle);
scriptEle.onload = function () {
resolve();
}
scriptEle.setAttribute("type", module ? "module" : "text/javascript" );
scriptEle.setAttribute("src", url);
});
}
const DEV = false;
const ELEMENT_NAME = "counter";
const PACKAGE_LINK = "https://www.unpkg.com/@citizendev/bubble-file-uploader@0.1.2";
let jsLink, cssLink;
if (DEV) {
cssLink = "http://localhost:5173/src/style.css"
jsLink = "http://localhost:5173/src/index.ts";
} else {
cssLink = `${PACKAGE_LINK}/dist/style.css`;
jsLink = `${PACKAGE_LINK}/dist/index.umd.js`;
}
jQuery("html").height("100%");
jQuery("body").height("100%");
jQuery("head").append(`<link rel="stylesheet" href="${cssLink}" />`);
(async () => {
if (DEV) {
await loadJS("http://localhost:5173/@vite/client", true);
}
await loadJS("https://www.unpkg.com/preact@^10.19.3/dist/preact.umd.js");
await loadJS("https://www.unpkg.com/preact@^10.19.3/hooks/dist/hooks.umd.js");
await loadJS("https://www.unpkg.com/preact@^10.19.3/compat/dist/compat.umd.js");
await loadJS("https://www.unpkg.com/preact-custom-element@^4.3.0/dist/preact-custom-element.umd.js");
await loadJS("https://www.unpkg.com/@preact/signals-core@^1.5.1/dist/signals-core.min.js");
await loadJS("https://www.unpkg.com/@preact/signals@^1.2.2/dist/signals.min.js");
await loadJS(jsLink, DEV);
const element = document.createElement(ELEMENT_NAME);
instance.canvas.append(element);
function tryInject(retryLeft, properties) {
if (!retryLeft || retryLeft <= 0 || !element) {
return;
}
if (!element._vdom) {
setTimeout(() => tryInject(retryLeft - 1, properties), 200);
return;
}
element.properties = properties;
if (!element.instance) {
element.instance = instance;
element.isPreview = true;
}
}
tryInject(25, properties);
})();
}
-
Open test app.