@cocreate/render 1.45.1 → 1.45.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/render",
3
- "version": "1.45.1",
3
+ "version": "1.45.3",
4
4
  "description": "A simple render component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "render",
@@ -45,23 +45,19 @@
45
45
  },
46
46
  "main": "./src/index.js",
47
47
  "devDependencies": {
48
- "@babel/core": "^7.9.6",
49
- "@babel/preset-env": "^7.9.6",
50
- "babel-loader": "^8.1.0",
51
- "clean-webpack-plugin": "^3.0.0",
52
- "file-loader": "^6.2.0",
48
+ "css-loader": "^5.1.3",
49
+ "esbuild": "^0.25.2",
50
+ "esbuild-loader": "^4.3.0",
53
51
  "mini-css-extract-plugin": "^1.5.0",
54
- "style-loader": "^3.3.1",
55
- "terser-webpack-plugin": "^5.1.1",
56
52
  "webpack": "^5.24.4",
57
53
  "webpack-cli": "^4.5.0",
58
54
  "webpack-log": "^3.0.1"
59
55
  },
60
56
  "dependencies": {
61
- "@cocreate/actions": "^1.18.4",
62
- "@cocreate/api": "^1.4.2",
63
- "@cocreate/element-prototype": "^1.23.0",
64
- "@cocreate/observer": "^1.16.3",
65
- "@cocreate/utils": "^1.34.1"
57
+ "@cocreate/actions": "^1.21.1",
58
+ "@cocreate/api": "^1.22.3",
59
+ "@cocreate/element-prototype": "^1.29.1",
60
+ "@cocreate/observer": "^1.18.1",
61
+ "@cocreate/utils": "^1.39.0"
66
62
  }
67
63
  }
package/src/index.js CHANGED
@@ -35,19 +35,14 @@ import "./index.css";
35
35
 
36
36
  const sources = new Map();
37
37
  const renderedNodes = new Map();
38
- const elementSelector =
39
- "[render-selector], [render-closest], [render-parent], [render-next], [render-previous]";
38
+ const elementSelector = "[render-query]";
40
39
 
41
40
  /**
42
41
  * Initializes elements based on specified rendering attributes. If a specific element is provided, it initializes that element.
43
42
  * If no element is provided, it queries and initializes all elements matching the defined selector criteria for rendering attributes.
44
43
  *
45
44
  * Supported rendering attributes:
46
- * - render-selector: [Describe what this attribute does]
47
- * - render-closest: [Describe what this attribute does]
48
- * - render-parent: [Describe what this attribute does]
49
- * - render-next: [Describe what this attribute does]
50
- * - render-previous: [Describe what this attribute does]
45
+ * - render-query: [Describe what this attribute does]
51
46
  *
52
47
  * @param {(Element|Element[]|HTMLCollection|null)} [element] - Optional. A single element, an array of elements, an HTMLCollection, or null.
53
48
  * - If an HTMLCollection or an array of elements is provided, each element in the collection/array is initialized.
@@ -100,52 +95,64 @@ async function render({
100
95
  update,
101
96
  remove
102
97
  }) {
103
- let Data = { ...data };
104
- if (!element) {
105
- if (source) {
106
- element = queryElements({ element: source, prefix: "render" });
107
- if (!element && source.children.length > 0) {
108
- for (const child of source.children) {
109
- if (
110
- child.matches(
111
- "template, [template], .template, [render]"
112
- )
113
- ) {
114
- element = child;
115
- break; // Found the desired element, no need to continue the loop
116
- }
117
- }
118
- }
98
+ if (!data || (!source && !data)) {
99
+ return;
100
+ }
119
101
 
120
- if (!element) {
121
- element = source.querySelector(
122
- "template, [template], .template, [render]"
102
+ if (!element) {
103
+ if (source instanceof HTMLElement) {
104
+ if (selector || (selector = source.getAttribute("render-query"))) {
105
+ element = queryElements({
106
+ element: source,
107
+ selector
108
+ });
109
+ } else if (source.children.length > 0) {
110
+ element = Array.from(source.children).find((child) =>
111
+ child.matches("template, [template], .template, [render]")
123
112
  );
113
+ if (!element) {
114
+ element = source.querySelector(
115
+ "template, [template], .template, [render]"
116
+ );
117
+ }
124
118
  }
125
- } else if (selector) element = queryElements({ selector });
119
+ } else if (selector) {
120
+ element = queryElements({
121
+ selector
122
+ });
123
+ }
126
124
 
127
- if (!element) return;
125
+ if (!element || (Array.isArray(element) && !element.length)) {
126
+ return;
127
+ }
128
128
  }
129
129
 
130
- if (source) {
131
- if (!key) {
132
- key = source.getAttribute("render") || source.getAttribute("key");
133
- if (!key) {
134
- key = data.type;
135
- if (key == "key") key = "object";
136
- else if (!key && data.method) key = data.method.split(".")[0];
137
- else if (!key) return;
138
- } else if (key == "{}") key = "object";
130
+ if (!key) {
131
+ key =
132
+ source.getAttribute("render") ||
133
+ source.getAttribute("key") ||
134
+ data.type;
135
+ if (!key || key === "key") {
136
+ key = "object";
137
+ } else if (key === "{}" || (!key && data.method)) {
138
+ key = data.method ? data.method.split(".")[0] : undefined;
139
139
  }
140
- let sourceData = sources.get(source);
141
- if (!sourceData) {
142
- sourceData = { element: source, Data };
143
- sources.set(source, sourceData);
140
+ if (!key) {
141
+ return;
144
142
  }
143
+ }
145
144
 
146
- source = sourceData;
147
- if (!source.data) source.data = Data;
148
- } else if (data) source = { Data };
145
+ let sourceData = sources.get(source);
146
+ if (!sourceData) {
147
+ sourceData = { element: source, data: { ...data } };
148
+ sources.set(source, sourceData);
149
+ } else if (sourceData.data) {
150
+ sourceData.data = { ...data };
151
+ } else {
152
+ // TODO: Most effiecientway to comapre too objects or array of objects
153
+ if (data === sourceData.data) return;
154
+ sourceData.data = { ...data };
155
+ }
149
156
 
150
157
  if (data.$filter) {
151
158
  index = index || data.$filter.startingIndex || data.$filter.index;
@@ -157,36 +164,42 @@ async function render({
157
164
  !Array.isArray(element) &&
158
165
  !(element instanceof HTMLCollection) &&
159
166
  !(element instanceof NodeList)
160
- )
167
+ ) {
161
168
  element = [element];
169
+ }
162
170
 
163
171
  for (let i = 0; i < element.length; i++) {
164
- key = element[i].getAttribute("render") || key;
165
-
166
172
  let renderedNode = renderedNodes.get(element[i]);
167
- if (
168
- renderedNode &&
169
- renderedNode.clones &&
170
- renderedNode.source &&
171
- renderedNode.source.element
172
- ) {
173
- let limit =
174
- renderedNode.source.element.getAttribute("render-limit");
175
- if (limit && renderedNode.clones.size >= parseInt(limit)) continue;
173
+ if (renderedNode) {
174
+ if (
175
+ renderedNode.clones &&
176
+ renderedNode.source &&
177
+ renderedNode.source.element
178
+ ) {
179
+ let limit =
180
+ renderedNode.source.element.getAttribute("render-limit");
181
+ if (limit && renderedNode.clones.size >= parseInt(limit))
182
+ continue;
183
+ }
184
+ } else {
185
+ renderedNode = {
186
+ element: element[i],
187
+ source: sourceData,
188
+ clones: new Map()
189
+ };
190
+ renderedNodes.set(element[i], renderedNode);
176
191
  }
177
192
 
178
- if (source) {
179
- if (!renderedNode) {
180
- renderedNode = {
181
- element: element[i],
182
- source,
183
- clones: new Map(),
184
- renderAs: new Map()
185
- };
186
- renderedNodes.set(element[i], renderedNode);
187
- }
193
+ let clones = renderedNode.clones; // || renderedNode.template.clones..
194
+ if (!clones) {
195
+ clones = renderedNode.template.clones;
196
+ console.log("renderedNode.template.clones", clones);
188
197
  }
189
198
 
199
+ key = element[i].getAttribute("render") || key;
200
+ let renderType =
201
+ renderedNode.source.element.getAttribute("render-type");
202
+ let clone;
190
203
  if (remove) {
191
204
  for (let j = 0; j < data[key].length; j++) {
192
205
  let cloneKey;
@@ -196,21 +209,23 @@ async function render({
196
209
  cloneKey = data[key][j].name;
197
210
  }
198
211
 
199
- let clone = renderedNode.clones.get(cloneKey);
212
+ clone = clones.get(cloneKey);
200
213
  if (!clone) return;
201
214
 
202
- renderedNode.clones.delete(cloneKey);
215
+ clones.delete(cloneKey);
203
216
  renderedNodes.delete(clone);
204
217
  clone.remove();
205
218
  }
206
- } else if ((key && Array.isArray(data[key])) || Array.isArray(data)) {
219
+ } else if (
220
+ (key && (Array.isArray(data[key]) || renderType)) ||
221
+ Array.isArray(data)
222
+ ) {
207
223
  if (update) {
208
224
  for (let j = 0; j < data[key].length; j++) {
209
- let clone;
210
225
  if (key === "object") {
211
- clone = renderedNode.clones.get(data[key][j]._id);
226
+ clone = clones.get(data[key][j]._id);
212
227
  } else {
213
- clone = renderedNode.clones.get(data[key][j].name);
228
+ clone = clones.get(data[key][j].name);
214
229
  }
215
230
 
216
231
  if (!currentIndex) currentIndex = data.$filter.currentIndex;
@@ -248,48 +263,36 @@ async function renderTemplate(template, data, key, index, keyPath) {
248
263
  }
249
264
 
250
265
  templateData.parent = template.parentElement.closest("[render]");
251
- if (templateData.parent)
266
+ if (templateData.parent) {
252
267
  templateData.parent = renderedNodes.get(templateData.parent);
268
+ }
253
269
 
254
270
  if (!templateData.keyPath) {
255
- if (keyPath) templateData.keyPath = keyPath;
256
- else if (templateData.parent && templateData.parent.keyPath)
271
+ if (keyPath) {
272
+ templateData.keyPath = keyPath;
273
+ } else if (templateData.parent && templateData.parent.keyPath) {
257
274
  templateData.keyPath = templateData.parent.keyPath;
258
- else if (key) templateData.keyPath = key;
275
+ } else if (key) {
276
+ templateData.keyPath = key;
277
+ }
259
278
  }
260
279
 
261
280
  template = templateData;
262
281
 
263
282
  let renderData;
264
- if (key) renderData = getRenderValue(template.element, data, key);
265
- else if (Array.isArray(data)) renderData = data;
266
-
267
- if (!renderData && data)
268
- if (Array.isArray(data)) renderData = data;
269
- else renderData = [data];
270
- else if (!renderData) return;
283
+ if (key) {
284
+ renderData = getRenderValue(template.element, data, key);
285
+ } else if (Array.isArray(data)) {
286
+ renderData = data;
287
+ }
271
288
 
272
- let isInsert = data.$filter && (data.$filter.create || data.$filter.update);
273
- if ((!isInsert && !index) || data.$filter.overwrite) {
274
- if (!template.clones) template = template.template;
275
- for (const [key, element] of template.clones) {
276
- renderedNodes.delete(element);
277
- element.remove();
278
- template.clones.delete(key);
289
+ if (!renderData && data) {
290
+ if (Array.isArray(data)) {
291
+ renderData = data;
292
+ } else {
293
+ renderData = [data];
279
294
  }
280
- // if (renderedNodes.size) {
281
- // for (let [element] of renderedNodes) {
282
- // element.remove()
283
- // }
284
- // renderedNodes.clear();
285
- // }
286
-
287
- // template.data = renderData
288
- }
289
- // else if (index) {
290
- // updates data that has already been rendered
291
- // template.data = dotNotationToObject(renderData, template.data)
292
- // }
295
+ } else if (!renderData) return;
293
296
 
294
297
  let renderAs = template.element.getAttribute("render-as") || key;
295
298
  template.renderAs = renderAs;
@@ -312,18 +315,43 @@ async function renderTemplate(template, data, key, index, keyPath) {
312
315
  }
313
316
  let reference = template.element.getAttribute("render-reference");
314
317
 
318
+ let isInsert = data.$filter && (data.$filter.create || data.$filter.update);
319
+ if (renderType !== "object") {
320
+ if ((!isInsert && !index) || data.$filter.overwrite) {
321
+ if (!template.clones) template = template.template;
322
+ for (const [key, element] of template.clones) {
323
+ renderedNodes.delete(element);
324
+ element.remove();
325
+ template.clones.delete(key);
326
+ }
327
+ } //
328
+ // else if (index) {
329
+ // updates data that has already been rendered
330
+ // template.data = dotNotationToObject(renderData, template.data)
331
+ // }
332
+ }
333
+
315
334
  if ((key && !Array.isArray(renderData)) || renderType === "object") {
316
335
  if (renderType && Array.isArray(renderData) && renderData.length === 1)
317
336
  renderData = renderData[0];
318
337
 
319
338
  const keys = Object.keys(renderData);
320
339
  for (let i = 0; i < keys.length; i++) {
321
- if (exclude.includes(keys[i])) continue;
340
+ let clone = template.clones.get(keys[i]);
341
+ clone = renderedNodes.get(clone);
342
+
322
343
  if (
323
- reference === "false" &&
324
- ["$storage", "$database", "$array"].includes(key)
325
- )
344
+ exclude.includes(keys[i]) ||
345
+ (reference === "false" &&
346
+ ["$storage", "$database", "$array"].includes(key))
347
+ ) {
348
+ if (clone) {
349
+ renderedNodes.delete(clone.element);
350
+ clone.element.remove();
351
+ template.clones.delete(keys[i]);
352
+ }
326
353
  continue;
354
+ }
327
355
 
328
356
  let value = renderData[keys[i]];
329
357
  let type = "string";
@@ -333,7 +361,16 @@ async function renderTemplate(template, data, key, index, keyPath) {
333
361
 
334
362
  let Data = { [renderAs]: { key: keys[i], value, type } };
335
363
 
336
- let clone = cloneTemplate(template);
364
+ if (!clone) {
365
+ clone = cloneTemplate(template);
366
+ } else {
367
+ if (clone.renderedValue === value) {
368
+ continue;
369
+ }
370
+ }
371
+ clone.renderedValue = value;
372
+ // let clone = cloneTemplate(template);
373
+
337
374
  let renderedKey = key.split(".");
338
375
  renderedKey = renderedKey[renderedKey.length - 1];
339
376
  //renderedKey needs to remove the parent.renderAs/key
@@ -441,6 +478,7 @@ function cloneTemplate(template) {
441
478
  clone = container.firstChild;
442
479
  container.remove();
443
480
  }
481
+
444
482
  let renderedNode = { template, element: clone };
445
483
  renderedNodes.set(clone, renderedNode);
446
484
  return renderedNode;
@@ -905,9 +943,9 @@ function getRenderValue(node, data, key, renderAs) {
905
943
  eid,
906
944
  parent = parentNode.parent || parentNode.template;
907
945
  do {
908
- if (key.includes("keyPath"))
946
+ if (key.includes("keyPath")) {
909
947
  value = parentNode.keyPath || parent.keyPath;
910
- else if (key.includes("parentKey")) {
948
+ } else if (key.includes("parentKey")) {
911
949
  value =
912
950
  parentNode.parentKey ||
913
951
  parent.parentKey ||
@@ -916,17 +954,24 @@ function getRenderValue(node, data, key, renderAs) {
916
954
  value = renderAs;
917
955
  } else if (key === "object" || key === "_id")
918
956
  value = ObjectId().toString();
919
- else if (key === "uuid") value = uuid.generate(6);
920
- else if (parent.source) Data = parent.source.data;
921
- else if (parent.parent) parent = parent.parent;
922
- else if (parent.template) parent = parent.template;
923
- else parent = undefined;
957
+ else if (key === "uuid") {
958
+ value = uuid.generate(6);
959
+ } else if (parent.source) {
960
+ Data = parent.source.data;
961
+ } else if (parent.parent) {
962
+ parent = parent.parent;
963
+ } else if (parent.template) {
964
+ parent = parent.template;
965
+ } else {
966
+ parent = undefined;
967
+ }
924
968
 
925
969
  if (!Data && parent && parent.eid) eid = parent.eid;
926
970
  } while (!value && parent && !Data);
927
971
 
928
- if (!value && Data) value = getValueFromObject(Data, key);
929
-
972
+ if (!value && Data) {
973
+ value = getValueFromObject(Data, key);
974
+ }
930
975
  if (!value && key.includes(".")) {
931
976
  let renderedData = getValueFromObject(
932
977
  Data,
@@ -934,29 +979,34 @@ function getRenderValue(node, data, key, renderAs) {
934
979
  );
935
980
  if (renderedData) {
936
981
  let index;
937
- if (!parent.clones.size || parent.clones.size === 1)
982
+ if (
983
+ !parent.clones.size ||
984
+ parent.clones.size === 1
985
+ ) {
938
986
  index = 0;
939
- else if (eid)
987
+ } else if (eid) {
940
988
  index = Array.from(
941
989
  parent.clones.keys()
942
990
  ).indexOf(eid);
943
- else console.log("eid not found");
991
+ } else console.log("eid not found");
944
992
 
945
- if (index >= 0)
993
+ if (index >= 0) {
946
994
  Data = {
947
995
  [key.split(".")[0]]: renderedData[index]
948
996
  };
949
-
997
+ }
950
998
  value = getValueFromObject(Data, key);
951
999
  }
952
1000
  }
953
1001
  }
954
1002
  }
955
1003
 
956
- if (!value && parentTemplate.parentElement)
1004
+ if (!value && parentTemplate.parentElement) {
957
1005
  parentTemplate =
958
1006
  parentTemplate.parentElement.closest("[render]");
959
- else parentTemplate = undefined;
1007
+ } else {
1008
+ parentTemplate = undefined;
1009
+ }
960
1010
  } while (!value && parentTemplate);
961
1011
  }
962
1012
 
@@ -977,7 +1027,9 @@ async function renderKey(action) {
977
1027
  let form = action.form || document;
978
1028
  let params = action.params;
979
1029
 
980
- if (!params) params = "render-key";
1030
+ if (!params) {
1031
+ params = "render-key";
1032
+ }
981
1033
 
982
1034
  let data = {};
983
1035
  let selector = `[${params}]`;
@@ -989,7 +1041,7 @@ async function renderKey(action) {
989
1041
  data = dotNotationToObject(data);
990
1042
  let renderData = { data: { [params]: data } };
991
1043
 
992
- let renderSelector = element.getAttribute("render-selector");
1044
+ let renderSelector = element.getAttribute("render-query");
993
1045
  if (!renderSelector) return;
994
1046
 
995
1047
  renderData.selector = renderSelector;
@@ -1054,13 +1106,7 @@ Observer.init({
1054
1106
  Observer.init({
1055
1107
  name: "fileRender",
1056
1108
  types: ["attributes"],
1057
- attributeFilter: [
1058
- "render-selector",
1059
- "render-closest",
1060
- "render-parent",
1061
- "render-next",
1062
- "render-previous"
1063
- ],
1109
+ attributeFilter: ["render-query"],
1064
1110
  callback: async function (mutation) {
1065
1111
  render({
1066
1112
  element: mutation.target,
@@ -1080,8 +1126,12 @@ Observer.init({
1080
1126
  return;
1081
1127
  let renderedNode = renderedNodes.get(parentElement);
1082
1128
  let data;
1083
- if (renderedNode.source) data = renderedNode.source.data;
1084
- if (renderedNode.template) data = renderedNode.template.source.data;
1129
+ if (renderedNode.source) {
1130
+ data = renderedNode.source.data;
1131
+ }
1132
+ if (renderedNode.template) {
1133
+ data = renderedNode.template.source.data;
1134
+ }
1085
1135
 
1086
1136
  render({ element: mutation.target, data });
1087
1137
  }