@cocreate/element-prototype 1.30.0 → 1.31.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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.31.0](https://github.com/CoCreate-app/CoCreate-element-prototype/compare/v1.30.0...v1.31.0) (2025-11-16)
2
+
3
+
4
+ ### Features
5
+
6
+ * enhance date handling in getValue and add custom operators for number formatting and UID generation ([280a469](https://github.com/CoCreate-app/CoCreate-element-prototype/commit/280a469d7c8b007c4cb2ed35ac7f4645327ac25e))
7
+
1
8
  # [1.30.0](https://github.com/CoCreate-app/CoCreate-element-prototype/compare/v1.29.3...v1.30.0) (2025-10-11)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/element-prototype",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "A simple element-prototype component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "element-prototype",
package/src/getValue.js CHANGED
@@ -203,6 +203,8 @@ const handleDateTime = (element, value, valueType) => {
203
203
  } else if (value) {
204
204
  // Initialize a new Date from the string or object
205
205
  value = new Date(value);
206
+ } else {
207
+ value = new Date();
206
208
  }
207
209
 
208
210
  // Check if value is a valid date
@@ -255,6 +257,58 @@ const handleDateTime = (element, value, valueType) => {
255
257
  let locale = element.getAttribute("locale") || "en-US";
256
258
  value = value.toLocaleString(locale);
257
259
  break;
260
+ case "addDays":
261
+ // Add days to the current date
262
+ const addDays = parseInt(element.getAttribute("add-days") || 0, 10);
263
+ value.setDate(value.getDate() + addDays);
264
+ value = value.toISOString();
265
+ break;
266
+ case "subtractDays":
267
+ // Subtract days from the current date
268
+ const subtractDays = parseInt(element.getAttribute("subtract-days") || 0, 10);
269
+ value.setDate(value.getDate() - subtractDays);
270
+ value = value.toISOString();
271
+ break;
272
+ case "startOfDay":
273
+ // Get the start of the current day (12:00 midnight)
274
+ const startOfDay = new Date(value);
275
+ startOfDay.setHours(0, 0, 0, 0); // Set time to midnight
276
+ value = startOfDay.toISOString();
277
+ break;
278
+ case "startOfWeek":
279
+ // Get the start of the current week (Sunday by default)
280
+ const startOfWeekOffset = parseInt(element.getAttribute("week-start-day") || 0, 10); // Default to Sunday (0)
281
+ const startOfWeek = new Date(value);
282
+ startOfWeek.setDate(value.getDate() - value.getDay() + startOfWeekOffset);
283
+ startOfWeek.setHours(0, 0, 0, 0); // Set to midnight
284
+ value = startOfWeek.toISOString();
285
+ break;
286
+ case "endOfWeek":
287
+ // Get the end of the current week (Saturday by default)
288
+ const endOfWeekOffset = parseInt(element.getAttribute("week-start-day") || 0, 10); // Default to Sunday (0)
289
+ const endOfWeek = new Date(value);
290
+ endOfWeek.setDate(value.getDate() - value.getDay() + 6 + endOfWeekOffset);
291
+ endOfWeek.setHours(23, 59, 59, 999); // Set to the end of the day
292
+ value = endOfWeek.toISOString();
293
+ break;
294
+ case "startOfMonth":
295
+ // Get the start of the month
296
+ value = new Date(value.getFullYear(), value.getMonth(), 1).toISOString();
297
+ break;
298
+ case "endOfMonth":
299
+ // Get the end of the month
300
+ value = new Date(value.getFullYear(), value.getMonth() + 1, 0).toISOString();
301
+ break;
302
+ case "startOfYear":
303
+ // Get the start of the year
304
+ value = new Date(value.getFullYear(), 0, 1).toISOString();
305
+ break;
306
+ case "endOfYear":
307
+ // Get the end of the year
308
+ value = new Date(value.getFullYear(), 11, 31).toISOString();
309
+ break;
310
+
311
+
258
312
  default:
259
313
  if (typeof value[valueType] === "function") {
260
314
  value = value[valueType]();
package/src/operators.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ObjectId, queryElements, getValueFromObject } from "@cocreate/utils";
1
+ import { ObjectId, queryElements, getValueFromObject, uid } from "@cocreate/utils";
2
2
 
3
3
  // Operators handled directly for simple, synchronous value retrieval
4
4
  const customOperators = new Map(
@@ -54,7 +54,28 @@ const customOperators = new Map(
54
54
  } catch (e) {
55
55
  return value;
56
56
  }
57
- }
57
+ },
58
+ // TODO: Implement number formatting
59
+ $numberFormat: (element, args) => {
60
+ let number = parseFloat(args[0]);
61
+ // Simple, fixed arg mapping:
62
+ // args[0] = locale (internationalization)
63
+ // args[1] = options (object)
64
+ // args[2] = number (if provided). If not provided, fall back to legacy behavior where args[0] might be the number.
65
+ if (!Array.isArray(args)) args = [args];
66
+
67
+ const locale = args[0] || undefined;
68
+ const options = args[1] || {};
69
+ const numCandidate = args[2] !== undefined ? args[2] : args[0];
70
+
71
+ number = parseFloat(numCandidate);
72
+
73
+ if (isNaN(number)) return String(numCandidate ?? "");
74
+
75
+ return new Intl.NumberFormat(locale, options).format(number);
76
+ },
77
+ $uid: (element, args) => uid(args[0]) || "",
78
+
58
79
  })
59
80
  );
60
81
 
@@ -206,19 +227,32 @@ const findInnermostFunctionCall = (expression) => {
206
227
  * @returns {{operator: string, args: string, rawContent: string, fullMatch?: string} | {operator: null, args: string, rawContent: string}}
207
228
  */
208
229
  const findInnermostOperator = (expression) => {
209
-
230
+ // Helper function to strip leading and trailing parentheses from a string
231
+ function stripParentheses(str) {
232
+ let result = str;
233
+ if (result.startsWith("(")) {
234
+ result = result.substring(1);
235
+ }
236
+ if (result.endsWith(")")) {
237
+ result = result.substring(0, result.length - 1);
238
+ }
239
+ return result;
240
+ }
241
+ let args;
242
+
210
243
  // --- 1. PRIORITY: Find Innermost FUNCTION CALL (Operator with Parentheses) ---
211
244
  const functionCall = findInnermostFunctionCall(expression);
212
245
 
213
246
  if (functionCall) {
214
- // Return the full function expression details, including the full string section
215
- return {
216
- operator: functionCall.operator,
217
- args: functionCall.args,
218
- rawContent: functionCall.args, // The content inside the parentheses (arguments)
219
- fullMatch: functionCall.fullMatch // The operator(args) string (the complete section to replace)
220
- };
221
- }
247
+ // Return the full function expression details, including the full string section
248
+ args = stripParentheses(functionCall.args);
249
+ return {
250
+ operator: functionCall.operator,
251
+ args, // Arguments without parentheses
252
+ rawContent: functionCall.args, // The content inside the parentheses (arguments)
253
+ fullMatch: functionCall.fullMatch // The operator(args) string (the complete section to replace)
254
+ };
255
+ }
222
256
 
223
257
  // --- 2. FALLBACK: Find BARE OPERATOR (e.g., $value path) ---
224
258
 
@@ -229,18 +263,22 @@ const findInnermostOperator = (expression) => {
229
263
  const innermostOperator = findBareOperatorInPath(rawContent, knownOperatorKeys);
230
264
 
231
265
  if (innermostOperator) {
232
- const operatorArgs = rawContent.substring(innermostOperator.length).trim();
233
- return {
234
- operator: innermostOperator,
235
- args: operatorArgs,
236
- rawContent: rawContent,
237
- };
238
- }
266
+ const operatorArgs = rawContent.substring(innermostOperator.length).trim();
267
+ args = stripParentheses(operatorArgs);
268
+ return {
269
+ operator: innermostOperator,
270
+ args, // Arguments without parentheses
271
+ rawContent: rawContent,
272
+ };
273
+ }
274
+
239
275
 
276
+ args = stripParentheses(rawContent);
277
+
240
278
  // Fallback if no known operator is found
241
279
  return {
242
280
  operator: null,
243
- args: rawContent,
281
+ args,
244
282
  rawContent: rawContent
245
283
  };
246
284
  };
@@ -276,6 +314,7 @@ function processOperators(
276
314
 
277
315
  let processedValue = value;
278
316
  let hasPromise = false;
317
+ let parsedValue = null
279
318
 
280
319
  while (processedValue.includes("$")) {
281
320
 
@@ -336,9 +375,18 @@ function processOperators(
336
375
  replacement = resolvedValue ?? "";
337
376
  }
338
377
 
339
- // Manually replace the matched part of the string
378
+ if (processedValue === textToReplace) {
379
+ processedValue = replacement;
380
+ break;
381
+ }
382
+
340
383
  processedValue = processedValue.replace(textToReplace, replacement);
341
384
 
385
+ if (!processedValue.includes("$")) {
386
+ // If there are still unresolved operators, we need to continue processing
387
+ break;
388
+ }
389
+
342
390
  } else {
343
391
  // If operator is excluded, we need to advance past it to avoid infinite loop
344
392
  break;