@cocreate/elements 1.48.0 → 2.0.0

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/CONTRIBUTING.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # Contributing to CoCreate-elements
2
2
 
3
- This project is work of [many contributors](https://github.com/CoCreate-app/CoCreate-elements/graphs/contributors).
4
- You're encouraged to submit [pull requests](https://github.com/CoCreate-app/CoCreate-elements/pulls),
5
- [propose features and discuss issues](https://github.com/CoCreate-app/CoCreate-elements/issues).
3
+ This project is work of [many contributors](https://github.com/CoCreateJS/elements/graphs/contributors).
4
+ You're encouraged to submit [pull requests](https://github.com/CoCreateJS/elements/pulls),
5
+ [propose features and discuss issues](https://github.com/CoCreateJS/elements/issues).
6
6
 
7
7
  In the examples below, substitute your Github username for `contributor` in URLs.
8
8
 
9
9
  ## Fork the Project
10
10
 
11
- Fork the [project on Github](https://github.com/CoCreate-app/CoCreate-elements) and check out your copy.
11
+ Fork the [project on Github](https://github.com/CoCreateJS/elements) and check out your copy.
12
12
 
13
13
  ```
14
14
  git elements https://github.com/contributor/CoCreate-elements.git
15
15
  cd CoCreate-elements
16
- git remote add upstream https://gitlab.com/cocreatejs/CoCreate-elements.git
16
+ git remote add upstream https://github.com/CoCreateJS/elements.git
17
17
  ```
18
18
 
19
19
  ## Create a Topic Branch
@@ -75,7 +75,7 @@ git push origin my-feature-branch
75
75
 
76
76
  ## Make a Pull Request
77
77
 
78
- Go to [https://github.com/CoCreate-app/CoCreate-elements](https://github.com/CoCreate-app/CoCreate-elements) and select your feature branch.
78
+ Go to [https://github.com/CoCreateJS/elements](https://github.com/CoCreateJS/elements) and select your feature branch.
79
79
  Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
80
80
 
81
81
  ## Rebase
package/README.md CHANGED
@@ -6,7 +6,7 @@ Bind any HTML element directly to your data using HTML5 attributes. An element d
6
6
 
7
7
  ## Documentation
8
8
 
9
- For a complete guide and working demo refer to the [documentation](https://cocreate.app/docs/elements).
9
+ For a complete guide and working demo refer to the [documentation](https://CoCreateJS.com/docs/elements).
10
10
 
11
11
  ## Table of Contents
12
12
 
@@ -61,7 +61,7 @@ yarn add @cocreate/elements
61
61
  ### CDN
62
62
 
63
63
  ```html
64
- <script src="https://cdn.cocreate.app/elements/latest/CoCreate-elements.min.js"></script>
64
+ <script src="https://cdn.CoCreateJS.com/elements/latest/CoCreate-elements.min.js"></script>
65
65
  ```
66
66
 
67
67
  ---
@@ -437,7 +437,7 @@ elements.init(document.querySelector("#profile"));
437
437
 
438
438
  ## Announcements
439
439
 
440
- All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreate-app/CoCreate-elements/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreate-app/CoCreate-elements/releases). You may also subscribe to email for releases and breaking changes.
440
+ All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreateJS/elements/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreateJS/elements/releases). You may also subscribe to email for releases and breaking changes.
441
441
 
442
442
  ---
443
443
 
@@ -451,15 +451,15 @@ Upcoming enhancements include:
451
451
  * Development mode diagnostics for unbound and misconfigured scopes
452
452
  * Devtools inspection of an element's scope and subscriptions
453
453
 
454
- If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreate-app/CoCreate-elements/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-elements/pulls). We would love to hear your feedback.
454
+ If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreateJS/elements/issues) and [pull requests](https://github.com/CoCreateJS/elements/pulls). We would love to hear your feedback.
455
455
 
456
456
  ---
457
457
 
458
458
  ## How to Contribute
459
459
 
460
- We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreate-app/CoCreate-elements/blob/master/CONTRIBUTING.md) guide for details.
460
+ We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreateJS/elements/blob/master/CONTRIBUTING.md) guide for details.
461
461
 
462
- We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreate-app/CoCreate-elements/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-elements/pulls) or merely upvote or comment on existing issues or pull requests.
462
+ We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreateJS/elements/issues) and [pull requests](https://github.com/CoCreateJS/elements/pulls) or merely upvote or comment on existing issues or pull requests.
463
463
 
464
464
  We appreciate your continued support, thank you!
465
465
 
@@ -469,7 +469,7 @@ We appreciate your continued support, thank you!
469
469
 
470
470
  CoCreate-elements is guided and supported by the CoCreate Developer Experience Team.
471
471
 
472
- Please Email the Developer Experience Team [here](mailto:develop@cocreate.app) in case of any queries.
472
+ Please Email the Developer Experience Team [here](mailto:develop@CoCreateJS.com) in case of any queries.
473
473
 
474
474
  CoCreate-elements is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
475
475
 
@@ -479,9 +479,9 @@ CoCreate-elements is maintained and funded by CoCreate. The names and logos for
479
479
 
480
480
  This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
481
481
 
482
- * **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreate-app/CoCreate-elements/blob/master/LICENSE).
482
+ * **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreateJS/elements/blob/master/LICENSE).
483
483
 
484
- * **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://cocreate.app). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
484
+ * **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://CoCreateJS.com). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
485
485
 
486
486
  If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.
487
487
 
package/demo/index.html CHANGED
@@ -195,6 +195,6 @@
195
195
 
196
196
  <!-- <script src="../dist/CoCreate-elements.js"></script> -->
197
197
  <!-- <script src="../../../CoCreateJS/dist/CoCreate.js"></script> -->
198
- <script src="https://CoCreate.app/dist/CoCreate.js"></script>
198
+ <script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
199
199
  </body>
200
200
  </html>
package/docs/index.html CHANGED
@@ -13,7 +13,7 @@
13
13
  <meta name="robots" content="index,follow" />
14
14
  <meta
15
15
  property="og:image"
16
- content="https://cdn.cocreate.app/docs/elements.png" />
16
+ content="https://cdn.CoCreateJS.com/docs/elements.png" />
17
17
 
18
18
  <title>CoCreate-elements Documentation | CoCreateJS</title>
19
19
 
@@ -22,7 +22,7 @@
22
22
  rel="icon"
23
23
  type="image/png"
24
24
  sizes="32x32"
25
- href="https://cocreate.app/images/favicon.ico" />
25
+ href="https://CoCreateJS.com/images/favicon.ico" />
26
26
  <link
27
27
  rel="stylesheet"
28
28
  href="../index.css"
@@ -75,7 +75,7 @@
75
75
  share-title="CoCreate elements"
76
76
  share-height="600"
77
77
  share-width="700"
78
- share-media="https://cdn.cocreate.app/docs/elements.png"
78
+ share-media="https://cdn.CoCreateJS.com/docs/elements.png"
79
79
  hover="display:block!important"
80
80
  hover-query=".social-networks">
81
81
  <div class="display:none social-networks">
@@ -106,7 +106,7 @@
106
106
  ></a>
107
107
  </div>
108
108
  <a
109
- href="https://github.com/CoCreate-app/CoCreate-elements"
109
+ href="https://github.com/CoCreateJS/CoCreate-elements"
110
110
  target="_blank"
111
111
  class="margin-right:15px"
112
112
  ><i src="/assets/svg/github.svg"></i
@@ -145,7 +145,7 @@
145
145
  <p class="padding:10px_0px line-height:1.5">
146
146
  Or you can use cdn link:
147
147
  </p>
148
- <pre><code class="language-html">&lt;script&gt;https://cdn.cocreate.app/elements/latest/CoCreate-elements.min.js&lt;/script&gt;</code></pre>
148
+ <pre><code class="language-html">&lt;script&gt;https://cdn.CoCreateJS.com/elements/latest/CoCreate-elements.min.js&lt;/script&gt;</code></pre>
149
149
 
150
150
  <div
151
151
  id="elements-usage"
@@ -330,13 +330,13 @@
330
330
  </div>
331
331
  </div>
332
332
  <button
333
- href="https://github.com/CoCreate-app/CoCreate-elements/tree/master/docs/index.html?message=docs%3A%20describe%20your%20change..."
333
+ href="https://github.com/CoCreateJS/CoCreate-elements/tree/master/docs/index.html?message=docs%3A%20describe%20your%20change..."
334
334
  target="_blank"
335
335
  class="display:flex justify-content:center align-items:center position:fixed bottom:15px right:15px height:50px width:50px border-radius:50% box-shadow:0px_2px_10px_0px_rgba(0,_0,_0,_0.4)">
336
336
  <i src="../assets/svg/pencil-alt.svg"></i>
337
337
  </button>
338
338
  </main>
339
339
 
340
- <script src="https://CoCreate.app/dist/CoCreate.js"></script>
340
+ <script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
341
341
  </body>
342
342
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/elements",
3
- "version": "1.48.0",
3
+ "version": "2.0.0",
4
4
  "description": "Fetch content into any html element by using html5 attributes to query data stored in CoCreate headless CMS. If data is changed it will instantly reflect in html tags as changes are broadcasted in realtime",
5
5
  "keywords": [
6
6
  "elements",
@@ -22,17 +22,17 @@
22
22
  },
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "git+https://gitlab.com/cocreatejs/CoCreate-elements.git"
25
+ "url": "git+https://github.com/CoCreateJS/elements.git"
26
26
  },
27
27
  "author": "CoCreate LLC",
28
28
  "license": "AGPL-3.0",
29
29
  "bugs": {
30
- "url": "https://github.com/CoCreate-app/CoCreate-elements/issues"
30
+ "url": "https://github.com/CoCreateJS/elements/issues"
31
31
  },
32
- "homepage": "https://cocreate.app/docs/elements",
32
+ "homepage": "https://CoCreateJS.com/docs/elements",
33
33
  "funding": {
34
34
  "type": "GitHub Sponsors ❤",
35
- "url": "https://github.com/sponsors/CoCreate-app"
35
+ "url": "https://github.com/sponsors/CoCreateJS"
36
36
  },
37
37
  "main": "./src/index.js",
38
38
  "dependencies": {
@@ -205,7 +205,9 @@ export async function save(element, action) {
205
205
  array: data[i].array,
206
206
  key: data[i].key,
207
207
  object: data[i].object._id,
208
- value
208
+ value,
209
+ realtime: true,
210
+ commit: true
209
211
  });
210
212
  }
211
213
 
@@ -0,0 +1,7 @@
1
+ // CRUD runtime. Loaded by data selectors, CRUD actions, or an Elements API call.
2
+ import "@cocreate/element-prototype";
3
+
4
+ export { init } from "./initHandler.js";
5
+ export { read, save } from "./crudHandler.js";
6
+ export { getData } from "./getDataHandler.js";
7
+ export { setDataType } from "./setDataHandler.js";
@@ -0,0 +1,54 @@
1
+ import { getAttributes, checkValue } from "@cocreate/utils";
2
+
3
+ export const environment = localStorage.getItem("environment");
4
+
5
+ /**
6
+ * Parses and normalizes HTML attributes from an element into a canonical CRUD data object.
7
+ * Infers execution type (object, index, array, database, storage, data) dynamically.
8
+ *
9
+ * @param {Element} element
10
+ * @returns {Object|undefined} Normalized data payload object
11
+ */
12
+ export function getDataObject(element) {
13
+ const data = getAttributes(element);
14
+ const crudType = ["storage", "database", "array", "index", "object"];
15
+
16
+ for (let i = 0; i < crudType.length; i++) {
17
+ if (!checkValue(data[crudType[i]])) return;
18
+
19
+ if (data[crudType[i]] && data[crudType[i]].includes(",")) {
20
+ const array = data[crudType[i]].split(",");
21
+ data[crudType[i]] = [];
22
+
23
+ for (let j = 0; j < array.length; j++) {
24
+ const item = array[j].trim();
25
+ if (crudType[i] === "object") {
26
+ data[crudType[i]].push({ _id: item });
27
+ } else {
28
+ data[crudType[i]].push(item);
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ if (data.object || data.object === "" || data.key || data.key === "") {
35
+ if (!data.array || (data.array && !data.array.length)) return;
36
+ data.type = "object";
37
+ } else if (data.index || data.index === "") {
38
+ if (!data.array || (data.array && !data.array.length)) return;
39
+ data.type = "index";
40
+ } else if (data.array || data.array === "") data.type = "array";
41
+ else if (data.database || data.database === "") data.type = "database";
42
+ else if (data.storage || data.storage === "") data.type = "storage";
43
+ else if (data.data) data.type = "data";
44
+
45
+ if (
46
+ environment &&
47
+ !data.database &&
48
+ ["array", "index", "object"].includes(data.type)
49
+ )
50
+ data.database = environment;
51
+
52
+ delete data.isRealtime;
53
+ return data;
54
+ }
@@ -2,6 +2,7 @@ import Observer from "@cocreate/observer";
2
2
  import { getAttributeNames, ObjectId, queryElements } from "@cocreate/utils";
3
3
  import Action from "@cocreate/actions";
4
4
  import elementPrototype from "@cocreate/element-prototype";
5
+ import { formSelector } from "./formSelectors.js";
5
6
 
6
7
  /**
7
8
  * Initializes form elements. If no parameter is provided, or null is passed, it queries and initializes all form elements.
@@ -13,7 +14,7 @@ import elementPrototype from "@cocreate/element-prototype";
13
14
  * - If an array of form elements is provided, each element in the array is initialized.
14
15
  */
15
16
  function init(elements) {
16
- if (!elements) elements = document.querySelectorAll("form, fieldset");
17
+ if (!elements) elements = document.querySelectorAll(formSelector);
17
18
  else if (!Array.isArray(elements)) elements = [elements];
18
19
 
19
20
  for (let element of elements) {
@@ -242,7 +243,7 @@ function setValue(form) {
242
243
  Observer.init({
243
244
  name: "CoCreateForm",
244
245
  types: ["addedNodes"],
245
- selector: "form, fieldset",
246
+ selector: formSelector,
246
247
  callback: (mutation) => init(mutation.target)
247
248
  });
248
249
 
@@ -258,7 +259,7 @@ Observer.init({
258
259
  "object",
259
260
  "index"
260
261
  ]),
261
- selector: "form, fieldset",
262
+ selector: formSelector,
262
263
  callback: (mutation) => setAttribute(mutation.target, null, [mutation.attributeName])
263
264
  });
264
265
 
@@ -0,0 +1 @@
1
+ export const formSelector = "form, fieldset";
@@ -1,8 +1,3 @@
1
- import {
2
- getAttributes,
3
- checkValue
4
- } from "@cocreate/utils";
5
-
6
1
  import {
7
2
  elements,
8
3
  forms,
@@ -13,7 +8,8 @@ import {
13
8
  import { getSubscription } from "./subscribeHandler.js";
14
9
  import { read, save } from "./crudHandler.js";
15
10
 
16
- const environment = localStorage.getItem("environment");
11
+ import { environment, getDataObject } from "./dataObject.js";
12
+ export { getDataObject } from "./dataObject.js";
17
13
 
18
14
  function registerFormElement(form, element, data) {
19
15
  if (!form || !data?.type) return;
@@ -37,57 +33,6 @@ function registerFormElement(form, element, data) {
37
33
  formObject.types.get(data.type).set(element, data);
38
34
  }
39
35
 
40
- /**
41
- * Parses and normalizes HTML attributes from an element into a canonical CRUD data object.
42
- * Infers execution type (object, index, array, database, storage, data) dynamically.
43
- *
44
- * @param {Element} element
45
- * @returns {Object|undefined} Normalized data payload object
46
- */
47
- export function getDataObject(element) {
48
- const data = getAttributes(element);
49
- const crudType = ["storage", "database", "array", "index", "object"];
50
-
51
- for (let i = 0; i < crudType.length; i++) {
52
- if (!checkValue(data[crudType[i]])) return;
53
-
54
- if (data[crudType[i]] && data[crudType[i]].includes(",")) {
55
- const array = data[crudType[i]].split(",");
56
- data[crudType[i]] = [];
57
-
58
- for (let j = 0; j < array.length; j++) {
59
- const item = array[j].trim();
60
- if (crudType[i] === "object") {
61
- data[crudType[i]].push({ _id: item });
62
- } else {
63
- data[crudType[i]].push(item);
64
- }
65
- }
66
- }
67
- }
68
-
69
- if (data.object || data.object === "" || data.key || data.key === "") {
70
- if (!data.array || (data.array && !data.array.length)) return;
71
- data.type = "object";
72
- } else if (data.index || data.index === "") {
73
- if (!data.array || (data.array && !data.array.length)) return;
74
- data.type = "index";
75
- } else if (data.array || data.array === "") data.type = "array";
76
- else if (data.database || data.database === "") data.type = "database";
77
- else if (data.storage || data.storage === "") data.type = "storage";
78
- else if (data.data) data.type = "data";
79
-
80
- if (
81
- environment &&
82
- !data.database &&
83
- ["array", "index", "object"].includes(data.type)
84
- )
85
- data.database = environment;
86
-
87
- delete data.isRealtime;
88
- return data;
89
- }
90
-
91
36
  /**
92
37
  * Registers an element and its generated dataKey into local client maps.
93
38
  * Binds element save/read helper methods and associates form context.
@@ -0,0 +1,104 @@
1
+ import Actions from "@cocreate/actions";
2
+ import { queryElements } from "@cocreate/utils";
3
+
4
+ const selector = "[href], [target]";
5
+
6
+ function init() {
7
+ document.link ||= { islink: "true" };
8
+ document.addEventListener("click", linkEvent, true);
9
+ }
10
+
11
+ // Delegation also handles links inserted after this feature loads.
12
+ function linkEvent(event) {
13
+ const target = event.target.closest?.(selector);
14
+ if (!target || target.hasAttribute("download") || target.closest("[actions]")) return;
15
+ open(target, event);
16
+ }
17
+
18
+ function open(target, event) {
19
+ if (!target) return;
20
+ const doc = target.ownerDocument || document;
21
+ if (doc.link?.islink === "false" || doc.link?.islink === false) return;
22
+ if (!target.getAttribute("href")) return;
23
+ event?.preventDefault();
24
+ openLink(target);
25
+ }
26
+
27
+ function openLink(link) {
28
+ const href = link.getAttribute("href");
29
+ const target = link.getAttribute("target");
30
+
31
+ if (!target || target === "_self") {
32
+ const currentUrl = new URL(location.href);
33
+ const targetUrl = new URL(href, location.href);
34
+ const currentPath = currentUrl.pathname.replace("/index.html", "/");
35
+ const targetPath = targetUrl.pathname.replace("/index.html", "/");
36
+ if (currentPath !== targetPath || currentUrl.hash !== targetUrl.hash) {
37
+ location.href = href;
38
+ }
39
+ } else if (target === "_window") {
40
+ window.open(href, "_blank", "location=yes,height=570,width=520,scrollbars=yes,status=yes");
41
+ } else {
42
+ window.open(href, target);
43
+ }
44
+ }
45
+
46
+ // Actions passes its chain element; resolve its associated link before opening it.
47
+ function href(element, context) {
48
+ const link = element.closest("[href], [target], [state_to]") ||
49
+ element.querySelector("[href], [target], [state_to]");
50
+ if (!link || link.hasAttribute("download")) return;
51
+ return open(link, context?.event);
52
+ }
53
+
54
+ function linkDocuments(element) {
55
+ const targets = element.hasAttribute("link-query")
56
+ ? queryElements({ element, prefix: "link" }) : [document];
57
+ return new Set(targets.map(target => target.nodeType === 9 ? target :
58
+ target.contentDocument || target.document || target.ownerDocument).filter(Boolean));
59
+ }
60
+
61
+ function disableHref(element) {
62
+ for (const doc of linkDocuments(element)) {
63
+ doc.link = { islink: "false" };
64
+ doc.removeEventListener("click", linkEvent, true);
65
+ doc.addEventListener("click", preventDefault, true);
66
+ }
67
+ }
68
+
69
+ function enableHref(element) {
70
+ for (const doc of linkDocuments(element)) {
71
+ doc.link = { islink: "true" };
72
+ doc.removeEventListener("click", preventDefault, true);
73
+ doc.addEventListener("click", linkEvent, true);
74
+ }
75
+ }
76
+
77
+ function preventDefault(event) {
78
+ event.preventDefault();
79
+ }
80
+
81
+ Actions.init([
82
+ {
83
+ name: "disableHref",
84
+ endEvent: "disableHref",
85
+ callback: action => {
86
+ disableHref(action.element);
87
+ action.end();
88
+ }
89
+ },
90
+ {
91
+ name: "enableHref",
92
+ endEvent: "enableHref",
93
+ callback: action => {
94
+ enableHref(action.element);
95
+ action.end();
96
+ }
97
+ }
98
+ ]);
99
+
100
+ Actions.href = href;
101
+ init();
102
+
103
+ export { open, disableHref, enableHref };
104
+ export default { open, disableHref, enableHref };
@@ -0,0 +1,90 @@
1
+ import observer from "@cocreate/observer";
2
+ import { relayEvents } from "@cocreate/utils/iframe";
3
+
4
+ export function clickedElement(frames) {
5
+ for (const frame of frames) {
6
+ try {
7
+ const frameDocument = frame.contentDocument;
8
+ if (frameDocument.clickedElement === undefined) {
9
+ frameDocument.addEventListener("click", (e) => {
10
+ frame.clickedElement = e.target;
11
+ frameDocument.clickedElement = e.target;
12
+ const ClickedElementEvent = frame.ownerDocument.defaultView.CustomEvent;
13
+ frame.dispatchEvent(new ClickedElementEvent("clickedElement", {
14
+ bubbles: true,
15
+ detail: {
16
+ cursor: { x: e.clientX, y: e.clientY },
17
+ document: frameDocument
18
+ }
19
+ }));
20
+ });
21
+ frameDocument.clickedElement = null;
22
+ }
23
+ } catch (iframeError) {
24
+ console.log(
25
+ `Cross-origin frame handling failed for: ${frame}`,
26
+ iframeError
27
+ );
28
+ }
29
+ }
30
+ }
31
+
32
+ export function hoveredElement(frames) {
33
+ for (const frame of frames) {
34
+ try {
35
+ const frameDocument = frame.contentDocument;
36
+ if (frameDocument.hoveredElement === undefined) {
37
+ frameDocument.hoveredElement = null;
38
+ frame.hoveredElement = null;
39
+
40
+ const emitHoveredElement = (event) => {
41
+ const HoveredElementEvent = frame.ownerDocument.defaultView.CustomEvent;
42
+ frame.dispatchEvent(new HoveredElementEvent("hoveredElement", {
43
+ bubbles: true,
44
+ detail: {
45
+ cursor: { x: event.clientX, y: event.clientY },
46
+ document: frameDocument
47
+ }
48
+ }));
49
+ };
50
+
51
+ frameDocument.addEventListener("mouseover", (event) => {
52
+ frame.hoveredElement = event.target;
53
+ frameDocument.hoveredElement = event.target;
54
+ emitHoveredElement(event);
55
+ });
56
+ frameDocument.addEventListener("mouseout", (event) => {
57
+ const nextElement = event.relatedTarget;
58
+ frame.hoveredElement = nextElement;
59
+ frameDocument.hoveredElement = nextElement;
60
+ emitHoveredElement(event);
61
+ });
62
+ frameDocument.addEventListener("mousemove", (event) => {
63
+ frame.hoveredElement = event.target;
64
+ frameDocument.hoveredElement = event.target;
65
+ emitHoveredElement(event);
66
+ });
67
+ }
68
+ } catch (iframeError) {
69
+ console.log(
70
+ `Cross-origin frame handling failed for: ${frame}`,
71
+ iframeError
72
+ );
73
+ }
74
+ }
75
+ }
76
+
77
+ clickedElement(document.querySelectorAll("iframe"));
78
+ hoveredElement(document.querySelectorAll("iframe"));
79
+ relayEvents(document.querySelectorAll("iframe"));
80
+
81
+ observer.init({
82
+ name: "CoCreateIframes",
83
+ types: ["addedNodes"],
84
+ selector: "iframe",
85
+ callback: (mutation) => {
86
+ clickedElement([mutation.target]);
87
+ hoveredElement([mutation.target]);
88
+ relayEvents([mutation.target]);
89
+ }
90
+ });