@cocreate/elements 1.41.1 → 1.42.1

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/src/index.js CHANGED
@@ -40,6 +40,7 @@ import { render, renderValue, renderedNodes } from "@cocreate/render";
40
40
  import "@cocreate/element-prototype";
41
41
  import "./fetchSrc";
42
42
  import { reset } from "./form";
43
+ import "./value.js";
43
44
 
44
45
  const selector = "[storage], [database], [array], [render-json]";
45
46
  const elements = new Map();
@@ -67,9 +68,9 @@ async function init(element) {
67
68
  !(element instanceof HTMLCollection) &&
68
69
  !(element instanceof NodeList) &&
69
70
  !Array.isArray(element)
70
- )
71
+ ) {
71
72
  element = [element];
72
- else if (!element) {
73
+ } else if (!element) {
73
74
  element = document.querySelectorAll(selector);
74
75
  initSocket();
75
76
  }
@@ -462,7 +463,12 @@ async function filterData(element, data, type, key) {
462
463
  }
463
464
 
464
465
  let property = key;
465
- if (operator) property = property.replace(operator + ".", "");
466
+ if (operator) {
467
+ property = property.replace(operator + ".", "");
468
+ if (operator === "$sum") {
469
+ value = 0;
470
+ }
471
+ }
466
472
  if (Array.isArray(data[type])) {
467
473
  let Data = [],
468
474
  isObject;
@@ -482,7 +488,7 @@ async function filterData(element, data, type, key) {
482
488
  if (docValue) {
483
489
  if (operator === "$sum" && typeof docValue === "number") {
484
490
  if (typeof value !== "number") value = 0;
485
- value += docValue;
491
+ value += docValue || 0;
486
492
  } else if (Array.isArray(docValue)) {
487
493
  Data.push(...docValue);
488
494
  } else {
@@ -844,11 +850,7 @@ async function getData(form) {
844
850
  if (attribute.includes("save", "delete")) continue;
845
851
  }
846
852
 
847
- if (
848
- element.matches(
849
- "[render-selector], [render-closest], [render-parent], [render-next], [render-previous]"
850
- )
851
- ) {
853
+ if (element.matches("[render-query]")) {
852
854
  let type = element.getAttribute("type");
853
855
  if (type !== "file") continue;
854
856
  }
@@ -991,7 +993,7 @@ async function getData(form) {
991
993
  }
992
994
 
993
995
  //dataKey should be used to group
994
- let key = dataKey + Data.method;
996
+ let key = dataKey; //+ Data.method;
995
997
  if (dataKeys.has(key)) {
996
998
  let storedData = dataKeys.get(key)[Data.type];
997
999
  dataKeys.get(key)[Data.type] = {
@@ -1010,7 +1012,7 @@ async function getData(form) {
1010
1012
  return dataArray;
1011
1013
  }
1012
1014
 
1013
- async function save(element) {
1015
+ async function save(element, action) {
1014
1016
  if (!element) return;
1015
1017
  let data, value;
1016
1018
  let upsert = element.getAttribute("upsert");
@@ -1116,19 +1118,28 @@ async function save(element) {
1116
1118
  (data[i].type !== "object" &&
1117
1119
  data[i].method.endsWith(".update")))
1118
1120
  ) {
1119
- setTypeValue(element, data[i]);
1120
- } else if (data[i])
1121
- document.dispatchEvent(
1122
- new CustomEvent("saved", {
1123
- detail: data[i]
1124
- })
1125
- );
1121
+ setTypeValue(element, data[i], action);
1122
+ } else if (data[i]) {
1123
+ if (action) {
1124
+ action.element.dispatchEvent(
1125
+ new CustomEvent("saved", {
1126
+ detail: data
1127
+ })
1128
+ );
1129
+ } else {
1130
+ document.dispatchEvent(
1131
+ new CustomEvent("saved", {
1132
+ detail: data
1133
+ })
1134
+ );
1135
+ }
1136
+ }
1126
1137
  }
1127
1138
 
1128
1139
  return Data;
1129
1140
  }
1130
1141
 
1131
- function setTypeValue(element, data) {
1142
+ function setTypeValue(element, data, action) {
1132
1143
  // TODO: if an array name is updated, the attibute array="" needs to be updated.
1133
1144
 
1134
1145
  if (!data) return;
@@ -1164,7 +1175,7 @@ function setTypeValue(element, data) {
1164
1175
  }
1165
1176
  setData(Array.from(elements.keys()), data);
1166
1177
 
1167
- // const state_ids = new Map();
1178
+ // const state_ids = new Map()
1168
1179
 
1169
1180
  // let state_id = form.getAttribute('state_id');
1170
1181
  // if (state_id) {
@@ -1217,11 +1228,19 @@ function setTypeValue(element, data) {
1217
1228
  // }
1218
1229
  }
1219
1230
 
1220
- document.dispatchEvent(
1221
- new CustomEvent("saved", {
1222
- detail: data
1223
- })
1224
- );
1231
+ if (action) {
1232
+ action.element.dispatchEvent(
1233
+ new CustomEvent("saved", {
1234
+ detail: data
1235
+ })
1236
+ );
1237
+ } else {
1238
+ document.dispatchEvent(
1239
+ new CustomEvent("saved", {
1240
+ detail: data
1241
+ })
1242
+ );
1243
+ }
1225
1244
  }
1226
1245
 
1227
1246
  async function remove(element) {
@@ -1291,6 +1310,9 @@ function initSocket() {
1291
1310
  if (data.rendered) return;
1292
1311
 
1293
1312
  data.rendered = true;
1313
+ if (data && data.key === "answers") {
1314
+ console.log("test");
1315
+ }
1294
1316
 
1295
1317
  setData(null, data);
1296
1318
  });
@@ -1300,7 +1322,7 @@ function initSocket() {
1300
1322
 
1301
1323
  Observer.init({
1302
1324
  name: "render",
1303
- observe: ["addedNodes"],
1325
+ types: ["addedNodes"],
1304
1326
  selector: "[render-clone]",
1305
1327
  callback: function (mutation) {
1306
1328
  if (!mutation.parentElement.hasAttribute("dnd")) return;
@@ -1449,16 +1471,16 @@ function dndCrudSend(data, crudType) {
1449
1471
 
1450
1472
  Observer.init({
1451
1473
  name: "CoCreateElementsChildList",
1452
- observe: ["childList"],
1474
+ types: ["addedNodes"],
1453
1475
  selector: selector,
1454
1476
  callback: function (mutation) {
1455
- init(mutation.addedNodes);
1477
+ init([mutation.target]);
1456
1478
  }
1457
1479
  });
1458
1480
 
1459
1481
  Observer.init({
1460
1482
  name: "CoCreateElementsRemovedNodes",
1461
- observe: ["removedNodes"],
1483
+ types: ["removedNodes"],
1462
1484
  selector: selector,
1463
1485
  callback: function (mutation) {
1464
1486
  // if (mutation.target.parentElement) return
@@ -1476,8 +1498,8 @@ Observer.init({
1476
1498
 
1477
1499
  Observer.init({
1478
1500
  name: "CoCreateElementsAttributes",
1479
- observe: ["attributes"],
1480
- attributeName: [
1501
+ types: ["attributes"],
1502
+ attributeFilter: [
1481
1503
  "organization_id",
1482
1504
  "host",
1483
1505
  "storage",
@@ -1491,8 +1513,8 @@ Observer.init({
1491
1513
  callback: function (mutation) {
1492
1514
  let currentValue = mutation.target.getAttribute(mutation.attributeName);
1493
1515
  if (currentValue !== mutation.oldValue) {
1494
- remove(mutation.target);
1495
1516
  if (mutation.target.tagName === "FORM") return;
1517
+ remove(mutation.target);
1496
1518
  init([mutation.target]);
1497
1519
  }
1498
1520
  }
@@ -1503,7 +1525,7 @@ Actions.init([
1503
1525
  name: "save",
1504
1526
  endEvent: "saved",
1505
1527
  callback: (action) => {
1506
- if (action.form) save(action.form);
1528
+ if ((action.form, action)) save(action.form, action);
1507
1529
  }
1508
1530
  },
1509
1531
  {
@@ -1512,11 +1534,15 @@ Actions.init([
1512
1534
  callback: async (action) => {
1513
1535
  // TODO: use selector to target elements for deletion if element is apart of render get render get rendering element for more crud detils
1514
1536
  // this way any selector can be used to target crud deletions not just .selected
1515
- let elements = queryElements({
1516
- element: action.element,
1517
- prefix: "delete"
1518
- });
1519
- if (elements === false) elements = [action.element];
1537
+ let elements = [];
1538
+ if (action.element.hasAttribute("delete-query")) {
1539
+ elements = queryElements({
1540
+ element: action.element,
1541
+ prefix: "delete"
1542
+ });
1543
+ } else {
1544
+ elements = [action.element];
1545
+ }
1520
1546
 
1521
1547
  for (let i = 0; i < elements.length; i++) {
1522
1548
  const data = getObject(elements[i]);
@@ -1546,7 +1572,7 @@ Actions.init([
1546
1572
  data[data.type] = { _id: data[data.type] };
1547
1573
 
1548
1574
  let response = await CRUD.send(data);
1549
- document.dispatchEvent(
1575
+ action.element.dispatchEvent(
1550
1576
  new CustomEvent("deleted", {
1551
1577
  detail: response
1552
1578
  })
package/src/value.js ADDED
@@ -0,0 +1,106 @@
1
+ import Observer from "@cocreate/observer";
2
+ import "@cocreate/element-prototype";
3
+ import { queryElements } from "@cocreate/utils";
4
+
5
+ const selector = "[value-query]";
6
+
7
+ /**
8
+ * Initializes elements with value-* attributes to enable dynamic value retrieval and setting.
9
+ *
10
+ * @param {HTMLElement|HTMLCollection|NodeList|Array<HTMLElement>} [element] - Optional element(s) to initialize. If not provided, initializes all matching elements in the document.
11
+ */
12
+ async function init(element) {
13
+ if (
14
+ element &&
15
+ !(element instanceof HTMLCollection) &&
16
+ !(element instanceof NodeList) &&
17
+ !Array.isArray(element)
18
+ ) {
19
+ element = [element];
20
+ } else if (!element) {
21
+ element = document.querySelectorAll(selector);
22
+ }
23
+
24
+ for (let i = 0; i < element.length; i++) {
25
+ initElement(element[i]);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Initializes a single element with value-* attributes.
31
+ *
32
+ * @param {HTMLElement} element - The element to initialize.
33
+ */
34
+ function initElement(element) {
35
+ let targets = queryElements({ element, prefix: "value" });
36
+
37
+ valueHandler(element, targets, true);
38
+ }
39
+
40
+ /**
41
+ * Handles the retrieval and setting of values based on value-* attributes.
42
+ *
43
+ * @param {HTMLElement} element - The element to set the value on.
44
+ * @param {object} targets - An object containing elements retrieved by queryElements().
45
+ */
46
+ function valueHandler(element, targets, initialize) {
47
+ let values = [];
48
+ // TODO: consdier the potential of targets being an array of elements, should value be an array of the values?
49
+ for (let i = 0; i < targets.length; i++) {
50
+ if (!targets[i] || !targets[i].isConnected) {
51
+ targets.splice(i, 1); // Remove the element
52
+ i -= 1; // Adjust the index
53
+ continue; // Skip to the next iteration
54
+ }
55
+
56
+ if (initialize) {
57
+ // Remove existing listener (if any)
58
+ targets[i].removeEventListener("input", elementValueHandler);
59
+
60
+ // Add new listener
61
+ targets[i].addEventListener("input", elementValueHandler);
62
+ }
63
+
64
+ values.push(targets[i].getValue());
65
+ }
66
+
67
+ if (!values.length) {
68
+ return;
69
+ } else if (values.length === 1) {
70
+ values = values[0];
71
+ }
72
+
73
+ let attribute = element.getAttribute("value-attribute");
74
+ if (attribute) {
75
+ element.setAttribute(attribute, values);
76
+ } else {
77
+ element.setValue(values);
78
+ }
79
+
80
+ function elementValueHandler(e) {
81
+ valueHandler(element, targets);
82
+ }
83
+ }
84
+
85
+ init();
86
+
87
+ Observer.init({
88
+ name: "CoCreateElementsValueAdded",
89
+ types: ["addedNodes"],
90
+ selector: selector,
91
+ callback: function (mutation) {
92
+ init(mutation.target);
93
+ }
94
+ });
95
+
96
+ Observer.init({
97
+ name: "CoCreateElementsAttributes",
98
+ types: ["attributes"],
99
+ attributeFilter: ["value-query"],
100
+ callback: function (mutation) {
101
+ let currentValue = mutation.target.getAttribute(mutation.attributeName);
102
+ if (currentValue !== mutation.oldValue) {
103
+ initElement(mutation.target);
104
+ }
105
+ }
106
+ });
package/webpack.config.js CHANGED
@@ -1,90 +1,65 @@
1
- const path = require("path")
2
- const TerserPlugin = require("terser-webpack-plugin")
3
- const MiniCssExtractPlugin = require("mini-css-extract-plugin")
4
- const { CleanWebpackPlugin } = require("clean-webpack-plugin")
5
-
6
- module.exports = (env, argv) => {
7
- let isProduction = false
8
- if (argv.mode === 'production')
9
- isProduction = true
10
-
11
- const config = {
12
- entry: {
13
- "CoCreate-elements": "./src/index.js",
14
- },
15
- output: {
16
- path: path.resolve(__dirname, "dist"),
17
- filename: isProduction ? "[name].min.js" : "[name].js",
18
- libraryTarget: "umd",
19
- libraryExport: "default",
20
- library: ["CoCreate", "elements"],
21
- globalObject: "this",
22
- },
23
-
24
- plugins: [
25
- new CleanWebpackPlugin(),
26
- new MiniCssExtractPlugin({
27
- filename: "[name].css",
28
- }),
29
- ],
30
- // Default mode for Webpack is production.
31
- // Depending on mode Webpack will apply different things
32
- // on final bundle. For now we don't need production's JavaScript
33
- // minifying and other thing so let's set mode to development
34
- mode: isProduction ? "production" : "development",
35
- module: {
36
- rules: [
37
- {
38
- test: /.js$/,
39
- exclude: /(node_modules)/,
40
- use: {
41
- loader: "babel-loader",
42
- options: {
43
- plugins: ["@babel/plugin-transform-modules-commonjs"],
44
- },
45
- },
46
- },
47
- {
48
- test: /.css$/i,
49
- use: [
50
- { loader: "style-loader", options: { injectType: "linkTag" } },
51
- "file-loader",
52
- ],
53
- },
54
- ],
55
- },
56
-
57
- // add source map
58
- ...(isProduction ? {} : { devtool: "eval-source-map" }),
59
-
60
- optimization: {
61
- minimize: true,
62
- minimizer: [
63
- new TerserPlugin({
64
- extractComments: true,
65
- // cache: true,
66
- parallel: true,
67
- // sourceMap: true, // Must be set to true if using source-maps in production
68
- terserOptions: {
69
- // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
70
- // extractComments: 'all',
71
- compress: {
72
- drop_console: true,
73
- },
74
- },
75
- }),
76
- ],
77
- splitChunks: {
78
- chunks: "all",
79
- minSize: 200,
80
- // maxSize: 99999,
81
- //minChunks: 1,
82
-
83
- cacheGroups: {
84
- defaultVendors: false,
85
- },
86
- },
87
- },
88
- }
89
- return config
90
- }
1
+ const path = require("path");
2
+ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
3
+ const { EsbuildPlugin } = require("esbuild-loader");
4
+ const { FileUploader } = require("@cocreate/webpack");
5
+
6
+ module.exports = async (env, argv) => {
7
+ const isProduction = argv && argv.mode === "production";
8
+ const config = {
9
+ entry: {
10
+ "CoCreate-elements": "./src/index.js"
11
+ },
12
+ output: {
13
+ path: path.resolve(__dirname, "dist"),
14
+ filename: isProduction ? "[name].min.js" : "[name].js",
15
+ libraryExport: "default",
16
+ library: ["CoCreate", "elements"],
17
+ clean: true
18
+ },
19
+ plugins: [
20
+ new MiniCssExtractPlugin({
21
+ filename: isProduction ? "[name].min.css" : "[name].css"
22
+ }),
23
+ new FileUploader(env, argv)
24
+ ],
25
+ mode: isProduction ? "production" : "development",
26
+ devtool: isProduction ? "source-map" : "eval-source-map",
27
+ module: {
28
+ rules: [
29
+ {
30
+ test: /.js$/,
31
+ exclude: /node_modules/,
32
+ use: {
33
+ loader: "esbuild-loader",
34
+ options: {
35
+ loader: "js",
36
+ target: "es2017"
37
+ }
38
+ }
39
+ },
40
+ {
41
+ test: /.css$/i,
42
+ use: [MiniCssExtractPlugin.loader, "css-loader"]
43
+ }
44
+ ]
45
+ },
46
+ optimization: {
47
+ minimize: isProduction,
48
+ minimizer: [
49
+ new EsbuildPlugin({
50
+ target: "es2017",
51
+ css: true
52
+ })
53
+ ],
54
+ splitChunks: {
55
+ cacheGroups: {
56
+ defaultVendors: false
57
+ }
58
+ }
59
+ },
60
+ performance: {
61
+ hints: isProduction ? "warning" : false
62
+ }
63
+ };
64
+ return config;
65
+ };