@cocreate/utils 1.40.0 → 1.41.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +1 -1
  3. package/src/index.js +113 -86
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.41.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.40.1...v1.41.0) (2025-11-16)
2
+
3
+
4
+ ### Features
5
+
6
+ * add uid function to generate UUIDs with customizable length ([7103971](https://github.com/CoCreate-app/CoCreate-utils/commit/71039712fe19d37bacdd5cd23db3366dd6b16ccb))
7
+
8
+ ## [1.40.1](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.40.0...v1.40.1) (2025-10-10)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * refine getRelativePath handling for localhost and improve getValueFromObject validation ([b7bd32f](https://github.com/CoCreate-app/CoCreate-utils/commit/b7bd32fa83d503108e9398e40c1c519caadb8ed5))
14
+
1
15
  # [1.40.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.39.2...v1.40.0) (2025-10-08)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/utils",
3
- "version": "1.40.0",
3
+ "version": "1.41.0",
4
4
  "description": "A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "utils",
package/src/index.js CHANGED
@@ -46,15 +46,17 @@
46
46
  path = window.location.pathname.replace(/\/[^\/]*$/, ""); // Remove file from path
47
47
  }
48
48
 
49
- // For localhost/127.0.0.1, trim everything after '/src'
49
+ // For localhost/127.0.0.1, remove everything up to and including the first '/src'
50
+ // so content AFTER '/src' is treated as the root
50
51
  if (
51
52
  isBrowser &&
52
53
  (location.hostname === "localhost" ||
53
54
  location.hostname === "127.0.0.1")
54
55
  ) {
56
+ // Find the '/src' directory in the path and keep everything after it (exclude '/src' itself)
55
57
  const srcIndex = path.indexOf("/src");
56
58
  if (srcIndex !== -1) {
57
- path = path.substring(0, srcIndex + 4); // keep '/src'
59
+ path = path.slice(srcIndex + 4); // remove '/src' and everything before it
58
60
  }
59
61
  }
60
62
 
@@ -112,6 +114,21 @@
112
114
  };
113
115
  }
114
116
 
117
+ function uid(length = 36) {
118
+ let pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
119
+ if (length > 36) {
120
+ length = 36; // If requested length is more than 36, set it to 36.
121
+ }
122
+
123
+ let uuid = pattern.replace(/[xy]/g, function (c) {
124
+ var r = (Math.random() * 16) | 0;
125
+ var v = c === 'x' ? r : (r & 0x3 | 0x8);
126
+ return v.toString(16);
127
+ }).substring(0, length); // Truncate to the requested length.
128
+
129
+ return uuid;
130
+ }
131
+
115
132
  function checkValue(value) {
116
133
  if (/{{\s*([\w\W]+)\s*}}/g.test(value)) return false;
117
134
  else return true;
@@ -314,13 +331,14 @@
314
331
 
315
332
  function getValueFromObject(object = {}, path = "", throwError = false) {
316
333
  try {
317
- if (!Object.keys(object).length || !path) {
334
+ if ((!Array.isArray(object) && !Object.keys(object).length) || !path) {
318
335
  if (throwError)
319
336
  throw new Error("Invalid input to getValueFromObject");
320
337
  return;
321
338
  }
322
339
 
323
- path = path.replace(/\[(\d+)\]/g, ".$1");
340
+ // remove leading dot if path is like `[0].src`
341
+ path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, '');
324
342
 
325
343
  let data = object,
326
344
  subpath = path.split(".");
@@ -706,106 +724,114 @@
706
724
  * @returns {Array} - An array of elements that match the query.
707
725
  */
708
726
  function queryElements({ element = document, prefix, selector }) {
709
- // Initialize a Set to store unique elements.
710
- let elements = new Set();
711
-
712
- // If no selector is provided and the element is an element node.
713
- if (!selector && element.nodeType === 1) {
714
- // If no prefix is provided, derive one from the element's attributes.
715
- if (!prefix) {
716
- for (let attr of element.attributes) {
717
- // If an attribute with "-query" suffix is found, extract prefix.
718
- if (attr.name.endsWith("-query")) {
719
- prefix = attr.name.slice(0, -6);
727
+ try {
728
+ // Initialize a Set to store unique elements.
729
+ let elements = new Set();
730
+
731
+ // If no selector is provided and the element is an element node.
732
+ if (!selector && element.nodeType === 1) {
733
+ // If no prefix is provided, derive one from the element's attributes.
734
+ if (!prefix) {
735
+ for (let attr of element.attributes) {
736
+ // If an attribute with "-query" suffix is found, extract prefix.
737
+ if (attr.name.endsWith("-query")) {
738
+ prefix = attr.name.slice(0, -6);
739
+ }
720
740
  }
741
+ // If no valid prefix is found, exit the function.
742
+ if (!prefix) return [];
721
743
  }
722
- // If no valid prefix is found, exit the function.
723
- if (!prefix) return false;
744
+ // Get the selector using the derived prefix.
745
+ selector = element.getAttribute(prefix + "-" + "query");
746
+ if (!selector) return []; // Exit if no selector is found.
724
747
  }
725
- // Get the selector using the derived prefix.
726
- selector = element.getAttribute(prefix + "-" + "query");
727
- if (!selector) return false; // Exit if no selector is found.
728
- }
729
748
 
730
- // Split complex selectors into individual ones, handling nested structures.
731
- let selectors = selector.split(/,(?![^()\[\]]*[)\]])/g);
732
- for (let i = 0; i < selectors.length; i++) {
733
- if (!selectors[i]) continue; // Skip empty selectors.
749
+ // Split complex selectors into individual ones, handling nested structures.
750
+ let selectors = selector.split(/,(?![^()\[\]]*[)\]])/g);
751
+ for (let i = 0; i < selectors.length; i++) {
752
+ if (!selectors[i]) continue; // Skip empty selectors.
734
753
 
735
- let queriedElement = element; // Start query from the current element.
754
+ let queriedElement = element; // Start query from the current element.
736
755
 
737
- // If media queries are included, verify and filter the selector accordingly.
738
- if (selectors[i].includes("@")) {
739
- selectors[i] = checkMediaQueries(selectors[i]);
740
- if (selectors[i] === false) continue; // Skip if media query is not matched.
741
- }
756
+ // If media queries are included, verify and filter the selector accordingly.
757
+ if (selectors[i].includes("@")) {
758
+ selectors[i] = checkMediaQueries(selectors[i]);
759
+ if (selectors[i] === false) continue; // Skip if media query is not matched.
760
+ }
761
+
762
+ let remainingSelector = selectors[i].trim(); // Trim any whitespace.
763
+ let match;
764
+
765
+ // Process each part of the selector that corresponds to specific query types/operators.
766
+ while (
767
+ (match = queryTypesRegex.exec(remainingSelector)) !== null
768
+ ) {
769
+ const matchIndex = match.index;
770
+ const operator = match[0];
771
+
772
+ // Process the part before the operator (if any).
773
+ const part = remainingSelector
774
+ .substring(0, matchIndex)
775
+ .trim()
776
+ .replace(/,$/, "");
777
+ if (part) {
778
+ queriedElement = querySelector(queriedElement, part);
779
+ if (!queriedElement) break; // Exit loop if no element is found.
780
+ }
781
+
782
+ // Remove the processed part and operator from the remaining selector.
783
+ remainingSelector = remainingSelector
784
+ .substring(matchIndex + operator.length)
785
+ .trim();
786
+
787
+ // Handle the $closest operator specifically.
788
+ if (operator === "$closest") {
789
+ let [closest, remaining = ""] =
790
+ remainingSelector.split(/\s+/, 2);
791
+ queriedElement = queriedElement.closest(closest);
792
+ remainingSelector = remaining.trim();
793
+ } else {
794
+ // Process other operators using the queryType function.
795
+ queriedElement = queryType(queriedElement, operator);
796
+ }
742
797
 
743
- let remainingSelector = selectors[i].trim(); // Trim any whitespace.
744
- let match;
745
-
746
- // Process each part of the selector that corresponds to specific query types/operators.
747
- while ((match = queryTypesRegex.exec(remainingSelector)) !== null) {
748
- const matchIndex = match.index;
749
- const operator = match[0];
750
-
751
- // Process the part before the operator (if any).
752
- const part = remainingSelector
753
- .substring(0, matchIndex)
754
- .trim()
755
- .replace(/,$/, "");
756
- if (part) {
757
- queriedElement = querySelector(queriedElement, part);
758
798
  if (!queriedElement) break; // Exit loop if no element is found.
759
799
  }
760
800
 
761
- // Remove the processed part and operator from the remaining selector.
762
- remainingSelector = remainingSelector
763
- .substring(matchIndex + operator.length)
764
- .trim();
801
+ if (!queriedElement) continue; // Skip if no element is found.
765
802
 
766
- // Handle the $closest operator specifically.
767
- if (operator === "$closest") {
768
- let [closest, remaining = ""] = remainingSelector.split(
769
- /\s+/,
770
- 2
803
+ // Process the remaining part after the last operator (if any).
804
+ if (remainingSelector) {
805
+ queriedElement = querySelector(
806
+ queriedElement,
807
+ remainingSelector
771
808
  );
772
- queriedElement = queriedElement.closest(closest);
773
- remainingSelector = remaining.trim();
774
- } else {
775
- // Process other operators using the queryType function.
776
- queriedElement = queryType(queriedElement, operator);
777
809
  }
778
810
 
779
- if (!queriedElement) break; // Exit loop if no element is found.
780
- }
781
-
782
- if (!queriedElement) continue; // Skip if no element is found.
783
-
784
- // Process the remaining part after the last operator (if any).
785
- if (remainingSelector) {
786
- queriedElement = querySelector(
787
- queriedElement,
788
- remainingSelector
789
- );
790
- }
791
-
792
- // Add elements to the set.
793
- if (
794
- Array.isArray(queriedElement) ||
795
- queriedElement instanceof HTMLCollection ||
796
- queriedElement instanceof NodeList
797
- ) {
798
- for (let el of queriedElement) {
799
- if (el instanceof Element) {
800
- elements.add(el);
811
+ // Add elements to the set.
812
+ if (
813
+ Array.isArray(queriedElement) ||
814
+ queriedElement instanceof HTMLCollection ||
815
+ queriedElement instanceof NodeList
816
+ ) {
817
+ for (let el of queriedElement) {
818
+ if (el instanceof Element) {
819
+ elements.add(el);
820
+ }
801
821
  }
822
+ } else if (queriedElement instanceof Element) {
823
+ elements.add(queriedElement);
802
824
  }
803
- } else if (queriedElement instanceof Element) {
804
- elements.add(queriedElement);
805
825
  }
806
- }
807
826
 
808
- return Array.from(elements); // Convert Set to Array and return found elements.
827
+ return Array.from(elements); // Convert Set to Array and return found elements.
828
+ } catch (e) {
829
+ console.error(
830
+ `CoCreate: Error in queryElements with selector: "${selector}".`,
831
+ e
832
+ );
833
+ return [];
834
+ }
809
835
  }
810
836
 
811
837
  function queryType(element, type) {
@@ -1275,6 +1301,7 @@
1275
1301
  return {
1276
1302
  getRelativePath,
1277
1303
  ObjectId,
1304
+ uid,
1278
1305
  checkValue,
1279
1306
  isValidDate,
1280
1307
  dotNotationToObject,