@react-querybuilder/core 8.20.1 → 8.21.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 (108) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +2261 -2113
  3. package/dist/cjs/react-querybuilder_core.cjs.development.js +323 -26
  4. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
  5. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +2261 -2113
  6. package/dist/cjs/react-querybuilder_core.cjs.production.js +1 -1
  7. package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -1
  8. package/dist/{convertQuery-BJKNgecE.js → convertQuery-Cw76XFIn.js} +8 -8
  9. package/dist/{convertQuery-BJKNgecE.js.map → convertQuery-Cw76XFIn.js.map} +1 -1
  10. package/dist/{convertQuery-J1CaoDxe.mjs → convertQuery-D_4J7E-Z.mjs} +2 -2
  11. package/dist/{convertQuery-J1CaoDxe.mjs.map → convertQuery-D_4J7E-Z.mjs.map} +1 -1
  12. package/dist/formatQuery.d.mts +499 -459
  13. package/dist/formatQuery.d.ts +499 -459
  14. package/dist/formatQuery.js +173 -91
  15. package/dist/formatQuery.js.map +1 -1
  16. package/dist/formatQuery.mjs +100 -23
  17. package/dist/formatQuery.mjs.map +1 -1
  18. package/dist/import-BVdxeIBO.d.mts +26 -0
  19. package/dist/import-Ddc3d_8q.d.ts +26 -0
  20. package/dist/{index-DlVg-QXo.d.mts → index-BSwFvkeI.d.mts} +679 -648
  21. package/dist/{index-DlVg-QXo.d.ts → index-BSwFvkeI.d.ts} +679 -648
  22. package/dist/{objectUtils-DBJI82bl.js → isRuleGroup-0JNiQgLg.js} +1 -26
  23. package/dist/isRuleGroup-0JNiQgLg.js.map +1 -0
  24. package/dist/{objectUtils-ZvPkF6u6.mjs → isRuleGroup-CqLThsbu.mjs} +2 -15
  25. package/dist/isRuleGroup-CqLThsbu.mjs.map +1 -0
  26. package/dist/objectUtils-Cr02aGxb.js +27 -0
  27. package/dist/objectUtils-Cr02aGxb.js.map +1 -0
  28. package/dist/objectUtils-DBlmJgBf.mjs +16 -0
  29. package/dist/objectUtils-DBlmJgBf.mjs.map +1 -0
  30. package/dist/parseCEL.d.mts +64 -30
  31. package/dist/parseCEL.d.ts +64 -30
  32. package/dist/parseCEL.js +91 -12
  33. package/dist/parseCEL.js.map +1 -1
  34. package/dist/parseCEL.mjs +85 -8
  35. package/dist/parseCEL.mjs.map +1 -1
  36. package/dist/parseCypher.d.mts +24 -25
  37. package/dist/parseCypher.d.ts +24 -25
  38. package/dist/parseGremlin.d.mts +18 -19
  39. package/dist/parseGremlin.d.ts +18 -19
  40. package/dist/parseJSONata.d.mts +207 -20
  41. package/dist/parseJSONata.d.ts +207 -20
  42. package/dist/parseJSONata.js +92 -7
  43. package/dist/parseJSONata.js.map +1 -1
  44. package/dist/parseJSONata.mjs +80 -4
  45. package/dist/parseJSONata.mjs.map +1 -1
  46. package/dist/parseJsonLogic.d.mts +51 -18
  47. package/dist/parseJsonLogic.d.ts +51 -18
  48. package/dist/parseJsonLogic.js +95 -34
  49. package/dist/parseJsonLogic.js.map +1 -1
  50. package/dist/parseJsonLogic.mjs +65 -6
  51. package/dist/parseJsonLogic.mjs.map +1 -1
  52. package/dist/parseMongoDB.d.mts +89 -58
  53. package/dist/parseMongoDB.d.ts +89 -58
  54. package/dist/parseMongoDB.js +140 -15
  55. package/dist/parseMongoDB.js.map +1 -1
  56. package/dist/parseMongoDB.mjs +128 -5
  57. package/dist/parseMongoDB.mjs.map +1 -1
  58. package/dist/parseSPARQL.d.mts +17 -18
  59. package/dist/parseSPARQL.d.ts +17 -18
  60. package/dist/parseSPARQL.js.map +1 -1
  61. package/dist/parseSPARQL.mjs.map +1 -1
  62. package/dist/parseSQL.d.mts +266 -18
  63. package/dist/parseSQL.d.ts +266 -18
  64. package/dist/parseSQL.js +163 -10
  65. package/dist/parseSQL.js.map +1 -1
  66. package/dist/parseSQL.mjs +149 -7
  67. package/dist/parseSQL.mjs.map +1 -1
  68. package/dist/parseSpEL.d.mts +193 -19
  69. package/dist/parseSpEL.d.ts +193 -19
  70. package/dist/parseSpEL.js +166 -7
  71. package/dist/parseSpEL.js.map +1 -1
  72. package/dist/parseSpEL.mjs +142 -6
  73. package/dist/parseSpEL.mjs.map +1 -1
  74. package/dist/{prepareQueryObjects-DaAXX792.js → prepareQueryObjects-C2-kTZvR.js} +6 -6
  75. package/dist/prepareQueryObjects-C2-kTZvR.js.map +1 -0
  76. package/dist/{prepareQueryObjects-Cd_tt4oy.mjs → prepareQueryObjects-Q18lHCKl.mjs} +4 -4
  77. package/dist/prepareQueryObjects-Q18lHCKl.mjs.map +1 -0
  78. package/dist/query-builder-layout.css.map +1 -1
  79. package/dist/query-builder.css.map +1 -1
  80. package/dist/react-querybuilder_core.d.mts +2261 -2113
  81. package/dist/react-querybuilder_core.legacy-esm.d.ts +2261 -2113
  82. package/dist/react-querybuilder_core.legacy-esm.js +339 -44
  83. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
  84. package/dist/react-querybuilder_core.mjs +313 -27
  85. package/dist/react-querybuilder_core.mjs.map +1 -1
  86. package/dist/react-querybuilder_core.production.d.mts +2261 -2113
  87. package/dist/react-querybuilder_core.production.mjs +1 -1
  88. package/dist/react-querybuilder_core.production.mjs.map +1 -1
  89. package/dist/styles/_layout.scss +4 -10
  90. package/dist/transformQuery.d.mts +91 -92
  91. package/dist/transformQuery.d.ts +91 -92
  92. package/dist/transformQuery.js +4 -3
  93. package/dist/transformQuery.js.map +1 -1
  94. package/dist/transformQuery.mjs +2 -1
  95. package/dist/transformQuery.mjs.map +1 -1
  96. package/dist/{utils-BpaOtylk.js → utils-DEwV7F6B.js} +108 -12
  97. package/dist/utils-DEwV7F6B.js.map +1 -0
  98. package/dist/{utils-CJRGiPb-.mjs → utils-Dt0D_DMV.mjs} +69 -3
  99. package/dist/utils-Dt0D_DMV.mjs.map +1 -0
  100. package/package.json +15 -14
  101. package/dist/import-Qs1-kgv5.d.ts +0 -27
  102. package/dist/import-ShTj5IdB.d.mts +0 -27
  103. package/dist/objectUtils-DBJI82bl.js.map +0 -1
  104. package/dist/objectUtils-ZvPkF6u6.mjs.map +0 -1
  105. package/dist/prepareQueryObjects-Cd_tt4oy.mjs.map +0 -1
  106. package/dist/prepareQueryObjects-DaAXX792.js.map +0 -1
  107. package/dist/utils-BpaOtylk.js.map +0 -1
  108. package/dist/utils-CJRGiPb-.mjs.map +0 -1
@@ -323,6 +323,50 @@ const defaultOperatorNegationMap = {
323
323
  null: "notNull"
324
324
  };
325
325
  /**
326
+ * Relational/comparison operators (`=`, `!=`, `<`, `>`, `<=`, `>=`).
327
+ *
328
+ * @group Defaults
329
+ */
330
+ const relationalOperators = /* @__PURE__ */ new Set([
331
+ "=",
332
+ "!=",
333
+ "<",
334
+ ">",
335
+ "<=",
336
+ ">="
337
+ ]);
338
+ /**
339
+ * Substring/text-matching operators (`contains`, `beginsWith`, `endsWith`, and negations).
340
+ *
341
+ * @group Defaults
342
+ */
343
+ const substringOperators = /* @__PURE__ */ new Set([
344
+ "contains",
345
+ "beginsWith",
346
+ "endsWith",
347
+ "doesNotContain",
348
+ "doesNotBeginWith",
349
+ "doesNotEndWith"
350
+ ]);
351
+ /**
352
+ * Null-check operators (`null`, `notNull`).
353
+ *
354
+ * @group Defaults
355
+ */
356
+ const nullOperators = /* @__PURE__ */ new Set(["null", "notNull"]);
357
+ /**
358
+ * List-membership operators (`in`, `notIn`).
359
+ *
360
+ * @group Defaults
361
+ */
362
+ const inOperators = /* @__PURE__ */ new Set(["in", "notIn"]);
363
+ /**
364
+ * Range operators (`between`, `notBetween`).
365
+ *
366
+ * @group Defaults
367
+ */
368
+ const betweenOperators = /* @__PURE__ */ new Set(["between", "notBetween"]);
369
+ /**
326
370
  * Default combinator list.
327
371
  *
328
372
  * @group Defaults
@@ -1176,6 +1220,51 @@ const mapSQLOperator = (rqbOperator) => {
1176
1220
  }
1177
1221
  };
1178
1222
  /**
1223
+ * Returns a preset-aware SQL string-concatenation function. Emits `CONCAT(a, b, ...)` when
1224
+ * `concatOperator` is `"CONCAT"` (case-insensitive), otherwise joins with the infix operator
1225
+ * (e.g. `a || b`, `a + b`).
1226
+ *
1227
+ * @group Export
1228
+ */
1229
+ const getSQLConcat = (concatOperator = "||") => (...values) => concatOperator.toUpperCase() === "CONCAT" ? `CONCAT(${values.join(", ")})` : values.join(` ${concatOperator} `);
1230
+ /**
1231
+ * Returns the `[prefix, suffix]` `LIKE` wildcards for a string-match operator (e.g. `contains`
1232
+ * → `['%', '%']`, `beginsWith` → `['', '%']`, `endsWith` → `['%', '']`). Unknown operators
1233
+ * yield `['', '']`.
1234
+ *
1235
+ * @group Export
1236
+ */
1237
+ const getLikeWildcards = (operatorLC) => {
1238
+ switch (operatorLC) {
1239
+ case "contains":
1240
+ case "doesnotcontain": return ["%", "%"];
1241
+ case "beginswith":
1242
+ case "doesnotbeginwith": return ["", "%"];
1243
+ case "endswith":
1244
+ case "doesnotendwith": return ["%", ""];
1245
+ default: return ["", ""];
1246
+ }
1247
+ };
1248
+ /**
1249
+ * Wraps an already-serialized SQL fragment (a quoted field name or an expression) with the
1250
+ * `LIKE` wildcards for the given (lowercase) string-match operator, concatenating the literal
1251
+ * `%` markers via the preset-aware {@link getSQLConcat}. Returns the fragment untouched for
1252
+ * operators without wildcards.
1253
+ *
1254
+ * @group Export
1255
+ */
1256
+ const wrapLikeFragment = (fragment, operatorLC, { concatOperator = "||", quoteValuesWith, wrapValueWith = ["", ""] } = {}) => {
1257
+ const [pre, post] = getLikeWildcards(operatorLC);
1258
+ const quoteChar = quoteValuesWith || `'`;
1259
+ const quote = (p) => `${wrapValueWith[0]}${quoteChar}${p}${quoteChar}${wrapValueWith[1]}`;
1260
+ const parts = [
1261
+ pre && quote(pre),
1262
+ fragment,
1263
+ post && quote(post)
1264
+ ].filter(Boolean);
1265
+ return parts.length > 1 ? getSQLConcat(concatOperator)(...parts) : fragment;
1266
+ };
1267
+ /**
1179
1268
  * Maps a (lowercase) {@link DefaultOperatorName} to a MongoDB operator.
1180
1269
  *
1181
1270
  * @group Export
@@ -1339,6 +1428,27 @@ const normalizeConstituentWordOrder = (input) => {
1339
1428
  return result;
1340
1429
  };
1341
1430
  /**
1431
+ * Prefixes a named-parameter value with the given `paramPrefix` unless the value already
1432
+ * begins with it. Used by {@link formatQuery} to render rules whose `valueSource` is
1433
+ * `"parameter"` (e.g. `"p1"` with prefix `":"` → `":p1"`; `":p1"` → `":p1"`).
1434
+ *
1435
+ * @group Export
1436
+ */
1437
+ const withParamPrefix = (value, paramPrefix = ":") => {
1438
+ const v = `${value ?? ""}`;
1439
+ return paramPrefix && v.startsWith(paramPrefix) ? v : `${paramPrefix}${v}`;
1440
+ };
1441
+ /**
1442
+ * Strips a leading `paramPrefix` from a named-parameter value if present. Inverse of
1443
+ * {@link withParamPrefix}; used to normalize parameter names for validation/lookup.
1444
+ *
1445
+ * @group Export
1446
+ */
1447
+ const stripParamPrefix = (value, paramPrefix = ":") => {
1448
+ const v = `${value ?? ""}`;
1449
+ return paramPrefix && v.startsWith(paramPrefix) ? v.slice(paramPrefix.length) : v;
1450
+ };
1451
+ /**
1342
1452
  * Default translations used by {@link formatQuery} for "natural_language" format.
1343
1453
  *
1344
1454
  * @group Export
@@ -1471,7 +1581,7 @@ const escapeDoubleQuotes$1 = (v, escapeQuotes) => typeof v !== "string" || !esca
1471
1581
  const defaultRuleProcessorCEL = (rule, opts = {}) => {
1472
1582
  const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
1473
1583
  const { field, operator, value, valueSource } = rule;
1474
- const valueIsField = valueSource === "field";
1584
+ const valueIsField = valueSource === "field" || valueSource === "parameter";
1475
1585
  const operatorTL = lc(operator === "=" ? "==" : operator);
1476
1586
  const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
1477
1587
  const matchEval = processMatchMode(rule);
@@ -1792,7 +1902,7 @@ const escapeSingleQuotes$2 = (v, escapeQuotes) => typeof v !== "string" || !esca
1792
1902
  const defaultRuleProcessorSpEL = (rule, opts = {}) => {
1793
1903
  const { field, operator, value, valueSource } = rule;
1794
1904
  const { escapeQuotes, parseNumbers, preserveValueOrder } = opts;
1795
- const valueIsField = valueSource === "field";
1905
+ const valueIsField = valueSource === "field" || valueSource === "parameter";
1796
1906
  const operatorTL = lc(operator === "=" ? "==" : operator);
1797
1907
  const useBareValue = typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || shouldRenderAsNumber(value, parseNumbers);
1798
1908
  const matchEval = processMatchMode(rule);
@@ -1826,11 +1936,20 @@ const defaultRuleProcessorSpEL = (rule, opts = {}) => {
1826
1936
  case ">":
1827
1937
  case ">=": return `${field} ${operatorTL} ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes$2(value, escapeQuotes)}'`}`;
1828
1938
  case "contains":
1829
- case "doesnotcontain": return wrapInNegation(`${field} matches ${valueIsField || useBareValue ? trimIfString(value) : `'${escapeSingleQuotes$2(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
1939
+ case "doesnotcontain": {
1940
+ const valueTL = valueIsField ? `'.*'.concat(${trimIfString(value)}).concat('.*')` : `'.*${escapeSingleQuotes$2(value, escapeQuotes)}.*'`;
1941
+ return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate$1(operatorTL));
1942
+ }
1830
1943
  case "beginswith":
1831
- case "doesnotbeginwith": return wrapInNegation(`${field} matches ${valueIsField ? `'^'.concat(${trimIfString(value)})` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes$2(value, escapeQuotes)}'`}`, shouldNegate$1(operatorTL));
1944
+ case "doesnotbeginwith": {
1945
+ const valueTL = valueIsField ? `'^'.concat(${trimIfString(value)}).concat('.*')` : `'${typeof value === "string" && !value.startsWith("^") || useBareValue ? "^" : ""}${escapeSingleQuotes$2(value, escapeQuotes)}.*'`;
1946
+ return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate$1(operatorTL));
1947
+ }
1832
1948
  case "endswith":
1833
- case "doesnotendwith": return wrapInNegation(`${field} matches ${valueIsField ? `${trimIfString(value)}.concat('$')` : `'${escapeSingleQuotes$2(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`}`, shouldNegate$1(operatorTL));
1949
+ case "doesnotendwith": {
1950
+ const valueTL = valueIsField ? `'.*'.concat(${trimIfString(value)}).concat('$')` : `'.*${escapeSingleQuotes$2(value, escapeQuotes)}${typeof value === "string" && !value.endsWith("$") || useBareValue ? "$" : ""}'`;
1951
+ return wrapInNegation(`${field} matches ${valueTL}`, shouldNegate$1(operatorTL));
1952
+ }
1834
1953
  case "null": return `${field} == null`;
1835
1954
  case "notnull": return `${field} != null`;
1836
1955
  case "in":
@@ -1868,7 +1987,35 @@ const escapeStringValueQuotes$1 = (v, quoteChar, escapeQuotes) => escapeQuotes &
1868
1987
  *
1869
1988
  * @group Export
1870
1989
  */
1871
- const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith, quoteValuesWith, concatOperator = "||", fieldIdentifierSeparator, wrapValueWith = ["", ""], translations } = {}) => {
1990
+ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQuotes, parseNumbers, preserveValueOrder, quoteFieldNamesWith, quoteValuesWith, concatOperator = "||", fieldIdentifierSeparator, paramPrefix, wrapValueWith = ["", ""], translations } = {}) => {
1991
+ if (valueSource === "parameter") {
1992
+ const operatorLowerCase = lc(operator);
1993
+ if (operatorLowerCase === "between" || operatorLowerCase === "notbetween") {
1994
+ const valueAsArray = toArray(value, { retainEmptyStrings: true });
1995
+ if (valueAsArray.length < 2 || !isValidValue(valueAsArray[0]) || !isValidValue(valueAsArray[1])) return "";
1996
+ const [first, second] = valueAsArray;
1997
+ return [withParamPrefix(first, paramPrefix), withParamPrefix(second, paramPrefix)].join(` ${translations?.betweenAnd ?? translations?.and ?? "and"} `);
1998
+ }
1999
+ if (operatorLowerCase === "in" || operatorLowerCase === "notin") {
2000
+ const valueAsArray = toArray(value);
2001
+ if (valueAsArray.length === 0) return "";
2002
+ return `(${valueAsArray.map((v) => withParamPrefix(v, paramPrefix)).join(", ")})`;
2003
+ }
2004
+ const paramRef = withParamPrefix(value, paramPrefix);
2005
+ switch (operatorLowerCase) {
2006
+ case "contains":
2007
+ case "doesnotcontain":
2008
+ case "beginswith":
2009
+ case "doesnotbeginwith":
2010
+ case "endswith":
2011
+ case "doesnotendwith": return wrapLikeFragment(paramRef, operatorLowerCase, {
2012
+ concatOperator,
2013
+ quoteValuesWith,
2014
+ wrapValueWith
2015
+ });
2016
+ }
2017
+ return paramRef;
2018
+ }
1872
2019
  const valueIsField = valueSource === "field";
1873
2020
  const operatorLowerCase = lc(operator);
1874
2021
  const quoteChar = quoteValuesWith || "'";
@@ -1879,7 +2026,11 @@ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQ
1879
2026
  quoteFieldNamesWith,
1880
2027
  fieldIdentifierSeparator
1881
2028
  });
1882
- const concat = (...values) => concatOperator.toUpperCase() === "CONCAT" ? `CONCAT(${values.join(", ")})` : values.join(` ${concatOperator} `);
2029
+ const likeOpts = {
2030
+ concatOperator,
2031
+ quoteValuesWith,
2032
+ wrapValueWith
2033
+ };
1883
2034
  switch (operatorLowerCase) {
1884
2035
  case "null":
1885
2036
  case "notnull": return "";
@@ -1906,11 +2057,11 @@ const defaultValueProcessorByRule = ({ operator, value, valueSource }, { escapeQ
1906
2057
  return (valueIsField ? valsOneAndTwoOnly.map((v) => wrapFieldName(v)) : valsOneAndTwoOnly.every((v) => shouldRenderAsNumber(v, parseNumbers)) ? valsOneAndTwoOnly.map((v) => parseNumber(v, { parseNumbers: "strict" })) : valsOneAndTwoOnly.map((v) => wrapAndEscape(v))).join(` ${translations?.betweenAnd ?? translations?.and ?? "and"} `);
1907
2058
  }
1908
2059
  case "contains":
1909
- case "doesnotcontain": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value), quoteValue("%")) : quoteValue(`%${escapeValue(value)}%`);
2060
+ case "doesnotcontain": return valueIsField ? wrapLikeFragment(wrapFieldName(value), operatorLowerCase, likeOpts) : quoteValue(`%${escapeValue(value)}%`);
1910
2061
  case "beginswith":
1911
- case "doesnotbeginwith": return valueIsField ? concat(wrapFieldName(value), quoteValue("%")) : quoteValue(`${escapeValue(value)}%`);
2062
+ case "doesnotbeginwith": return valueIsField ? wrapLikeFragment(wrapFieldName(value), operatorLowerCase, likeOpts) : quoteValue(`${escapeValue(value)}%`);
1912
2063
  case "endswith":
1913
- case "doesnotendwith": return valueIsField ? concat(quoteValue("%"), wrapFieldName(value)) : quoteValue(`%${escapeValue(value)}`);
2064
+ case "doesnotendwith": return valueIsField ? wrapLikeFragment(wrapFieldName(value), operatorLowerCase, likeOpts) : quoteValue(`%${escapeValue(value)}`);
1914
2065
  }
1915
2066
  if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
1916
2067
  return valueIsField ? wrapFieldName(value) : shouldRenderAsNumber(value, parseNumbers) ? `${trimIfString(value)}` : `${wrapAndEscape(value)}`;
@@ -2658,7 +2809,7 @@ const defaultRuleGroupProcessorTanStackDB = (ruleGroup, options) => (refs) => {
2658
2809
  };
2659
2810
  //#endregion
2660
2811
  //#region src/utils/formatQuery/defaultRuleGroupProcessorDiagnostics.ts
2661
- const numericInputTypes = new Set([
2812
+ const numericInputTypes = /* @__PURE__ */ new Set([
2662
2813
  "number",
2663
2814
  "range",
2664
2815
  "bigint"
@@ -3482,7 +3633,10 @@ const defaultRuleProcessorJsonLogic = (rule, options = {}) => {
3482
3633
  case "null":
3483
3634
  case "notnull": return { [`${operatorLC === "notnull" ? "!" : "="}=`]: [fieldObject, null] };
3484
3635
  case "in":
3485
- case "notin": return negateIfNotOp(operatorLC, { in: [fieldObject, toArray(value).map((v) => fieldOrNumberRenderer(v))] });
3636
+ case "notin": {
3637
+ const valueAsArray = toArray(value).map((v) => fieldOrNumberRenderer(v));
3638
+ return negateIfNotOp(operatorLC, { in: [fieldObject, valueAsArray] });
3639
+ }
3486
3640
  case "between":
3487
3641
  case "notbetween": {
3488
3642
  const valueAsArray = toArray(value);
@@ -3513,11 +3667,20 @@ const defaultRuleProcessorJsonLogic = (rule, options = {}) => {
3513
3667
  return false;
3514
3668
  }
3515
3669
  case "contains":
3516
- case "doesnotcontain": return negateIfNotOp(operatorLC, { in: [fieldOrNumberRenderer(value), fieldObject] });
3670
+ case "doesnotcontain": {
3671
+ const jsonRule = { in: [fieldOrNumberRenderer(value), fieldObject] };
3672
+ return negateIfNotOp(operatorLC, jsonRule);
3673
+ }
3517
3674
  case "beginswith":
3518
- case "doesnotbeginwith": return negateIfNotOp(operatorLC, { startsWith: [fieldObject, fieldOrNumberRenderer(value)] });
3675
+ case "doesnotbeginwith": {
3676
+ const jsonRule = { startsWith: [fieldObject, fieldOrNumberRenderer(value)] };
3677
+ return negateIfNotOp(operatorLC, jsonRule);
3678
+ }
3519
3679
  case "endswith":
3520
- case "doesnotendwith": return negateIfNotOp(operatorLC, { endsWith: [fieldObject, fieldOrNumberRenderer(value)] });
3680
+ case "doesnotendwith": {
3681
+ const jsonRule = { endsWith: [fieldObject, fieldOrNumberRenderer(value)] };
3682
+ return negateIfNotOp(operatorLC, jsonRule);
3683
+ }
3521
3684
  }
3522
3685
  return false;
3523
3686
  };
@@ -3551,7 +3714,10 @@ const defaultRuleProcessorLDAP = (rule, options = {}) => {
3551
3714
  case "null":
3552
3715
  case "notnull": return negateIf(`(${field}=*)`, operatorLC === "notnull");
3553
3716
  case "in":
3554
- case "notin": return negateIf(`(|${toArray(value).map((val) => `(${field}=${ldapEscape(val)})`).join("")})`, operatorLC === "notin");
3717
+ case "notin": {
3718
+ const valueAsArray = toArray(value);
3719
+ return negateIf(`(|${valueAsArray.map((val) => `(${field}=${ldapEscape(val)})`).join("")})`, operatorLC === "notin");
3720
+ }
3555
3721
  case "between":
3556
3722
  case "notbetween": {
3557
3723
  const valueAsArray = toArray(value);
@@ -3862,7 +4028,22 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
3862
4028
  const [qPre, qPost] = quoteFieldNamesWith;
3863
4029
  if ((sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in" || sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") && !value) return finalize("");
3864
4030
  else if (sqlOperatorLowerCase === "is null" || sqlOperatorLowerCase === "is not null") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator}`);
3865
- else if (rule.valueSource === "field") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${value}`.trim());
4031
+ else if (rule.valueSource === "parameter") {
4032
+ const registerParam = (v) => {
4033
+ const ref = withParamPrefix(v, paramPrefix);
4034
+ if (!parameterized) paramsNamed[paramsKeepPrefix ? ref : stripParamPrefix(v, paramPrefix)] = null;
4035
+ return ref;
4036
+ };
4037
+ if (sqlOperatorLowerCase === "between" || sqlOperatorLowerCase === "not between") {
4038
+ const [first, second] = toArray(rule.value, { retainEmptyStrings: true }).slice(0, 2);
4039
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${registerParam(first)} and ${registerParam(second)}`.trim());
4040
+ }
4041
+ if (sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in") {
4042
+ const splitValue = toArray(rule.value);
4043
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} (${splitValue.map((v) => registerParam(v)).join(", ")})`);
4044
+ }
4045
+ return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${wrapLikeFragment(registerParam(rule.value), lc(rule.operator), { concatOperator })}`.trim());
4046
+ } else if (rule.valueSource === "field") return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${value}`.trim());
3866
4047
  else if (sqlOperatorLowerCase === "in" || sqlOperatorLowerCase === "not in") {
3867
4048
  const splitValue = toArray(rule.value);
3868
4049
  if (parameterized) {
@@ -4054,7 +4235,9 @@ const defaultRuleProcessorSPARQL = (rule, opts = {}) => {
4054
4235
  if (typeof v === "bigint") return String(v);
4055
4236
  if (valueIsField) return sparqlVar(trimIfString(v));
4056
4237
  if (typeof v === "number" || shouldRenderAsNumber(v, parseNumbers)) return trimIfString(v);
4238
+ /* v8 ignore start -- @preserve */
4057
4239
  const s = typeof v === "string" ? v : JSON.stringify(v) ?? "";
4240
+ /* v8 ignore stop -- @preserve */
4058
4241
  if (s.startsWith("?") || s.startsWith("<") || s.includes(":")) return s;
4059
4242
  return `"${escapeDoubleQuotes(s, escapeQuotes)}"`;
4060
4243
  };
@@ -4298,7 +4481,7 @@ const defaultFormatQueryOptions = {
4298
4481
  translations: {},
4299
4482
  operatorMap: {}
4300
4483
  };
4301
- const valueProcessorCanActAsRuleProcessor = new Set([
4484
+ const valueProcessorCanActAsRuleProcessor = /* @__PURE__ */ new Set([
4302
4485
  "cel",
4303
4486
  "drizzle",
4304
4487
  "elasticsearch",
@@ -4312,7 +4495,7 @@ const valueProcessorCanActAsRuleProcessor = new Set([
4312
4495
  "spel",
4313
4496
  "tanstack_db"
4314
4497
  ]);
4315
- const sqlFormats = new Set([
4498
+ const sqlFormats = /* @__PURE__ */ new Set([
4316
4499
  "sql",
4317
4500
  "parameterized",
4318
4501
  "parameterized_named",
@@ -4377,6 +4560,10 @@ function formatQuery(ruleGroup, optionParam = {}) {
4377
4560
  if (typeof field.validator === "function") fieldValidator = field.validator;
4378
4561
  }
4379
4562
  }
4563
+ if (rule.valueSource === "parameter" && typeof optObj.getParameters === "function") {
4564
+ const fieldData = getOption(fields, rule.field);
4565
+ if (!new Set(toFlatOptionArray(toFullOptionList(optObj.getParameters(rule.field, rule.operator, { fieldData }))).map((p) => stripParamPrefix(p.value, optObj.paramPrefix))).has(stripParamPrefix(rule.value, optObj.paramPrefix))) validationResult = false;
4566
+ }
4380
4567
  return [validationResult, fieldValidator];
4381
4568
  };
4382
4569
  const finalOptions = {
@@ -4593,7 +4780,7 @@ if (cryptoModule) {
4593
4780
  if (typeof cryptoModule.randomUUID === "function") generateID = () => cryptoModule.randomUUID();
4594
4781
  else if (typeof cryptoModule.getRandomValues === "function") {
4595
4782
  const position19vals = "89ab";
4596
- const container = new Uint32Array(32);
4783
+ const container = /* @__PURE__ */ new Uint32Array(32);
4597
4784
  generateID = () => {
4598
4785
  cryptoModule.getRandomValues(container);
4599
4786
  let id = (container[0] % 16).toString(16);
@@ -4635,6 +4822,45 @@ const getMatchModesUtil = (fieldData, getMatchModes) => {
4635
4822
  }) ?? [];
4636
4823
  };
4637
4824
  //#endregion
4825
+ //#region src/utils/getRuleDefaultValue.ts
4826
+ const getFirstOptionsFrom = (opts, r, listsAsArrays) => {
4827
+ const firstOption = getFirstOption(opts);
4828
+ if (r.operator === "between" || r.operator === "notBetween") {
4829
+ const valueAsArray = [firstOption, firstOption];
4830
+ return listsAsArrays ? valueAsArray : joinWith(valueAsArray.map((v) => v ?? ""), ",");
4831
+ }
4832
+ return firstOption;
4833
+ };
4834
+ /**
4835
+ * Computes the default `value` for a rule given its `field`/`operator`/`valueSource`, mirroring
4836
+ * the precedence the {@link react-querybuilder!QueryBuilder QueryBuilder} applies: a field's
4837
+ * `defaultValue`, then a `getDefaultValue` override, then a value derived from the field/operator's
4838
+ * value list and editor type (first option for `select`/`radio`, `false` for `checkbox`, paired for
4839
+ * `between`/`notBetween`), or a comparator-valid field when `valueSource` is `'field'`. Falls back
4840
+ * to `''`.
4841
+ *
4842
+ * @group Option Lists
4843
+ */
4844
+ const getRuleDefaultValue = (rule, options) => {
4845
+ const { fieldData, fields, getValueEditorType, getValues, getDefaultValue, getParameters, listsAsArrays } = options;
4846
+ if (fieldData?.defaultValue !== void 0 && fieldData.defaultValue !== null) return fieldData.defaultValue;
4847
+ else if (getDefaultValue) return getDefaultValue(rule, { fieldData });
4848
+ let value = "";
4849
+ const values = getValues(rule.field, rule.operator, { fieldData });
4850
+ if (rule.valueSource === "field") {
4851
+ const filteredFields = filterFieldsByComparator(fieldData, fields, rule.operator);
4852
+ value = filteredFields.length > 0 ? getFirstOptionsFrom(filteredFields, rule, listsAsArrays) : "";
4853
+ } else if (rule.valueSource === "parameter") {
4854
+ const parameters = getParameters ? getParameters(rule.field, rule.operator, { fieldData }) : null;
4855
+ value = parameters && parameters.length > 0 ? getFirstOption(parameters) : "";
4856
+ } else if (values.length > 0) {
4857
+ const editorType = getValueEditorType(rule.field, rule.operator, { fieldData });
4858
+ if (editorType === "multiselect") value = listsAsArrays ? [] : "";
4859
+ else if (editorType === "select" || editorType === "radio") value = getFirstOptionsFrom(values, rule, listsAsArrays);
4860
+ } else if (getValueEditorType(rule.field, rule.operator, { fieldData }) === "checkbox") value = false;
4861
+ return value;
4862
+ };
4863
+ //#endregion
4638
4864
  //#region src/utils/getValidationClassNames.ts
4639
4865
  /**
4640
4866
  * Gets the standard classname for valid or invalid components
@@ -4885,21 +5111,81 @@ const addInPlace = (query, ruleOrGroup, parentPathOrID, options = {}) => {
4885
5111
  return query;
4886
5112
  };
4887
5113
  /**
4888
- * Updates a property of a rule or group within a query without mutating the original query.
5114
+ * Relative order in which properties are applied during a multi-property update.
5115
+ * Lower ranks apply first; `value` applies last so an explicitly-provided value
5116
+ * is never clobbered by a reset triggered by a `field`/`operator`/`valueSource`
5117
+ * change. Unranked properties default to `3` (between `valueSource` and `value`).
5118
+ */
5119
+ const updatePropRank = {
5120
+ field: 0,
5121
+ operator: 1,
5122
+ valueSource: 2,
5123
+ value: 4
5124
+ };
5125
+ /** Stable-sorts `[prop, value]` entries by {@link updatePropRank}. */
5126
+ const orderUpdateEntries = (entries) => entries.sort((x, y) => (updatePropRank[x[0]] ?? 3) - (updatePropRank[y[0]] ?? 3));
5127
+ /**
5128
+ * Normalizes the variadic {@link update}/{@link updateInPlace} arguments (single
5129
+ * prop+value, parallel arrays, or property map) into a canonically-ordered list
5130
+ * of `[prop, value]` entries plus the target path/ID and options.
5131
+ */
5132
+ const normalizeUpdateArgs = (a, b, c, d) => {
5133
+ if (typeof a === "string") return {
5134
+ entries: [[a, b]],
5135
+ pathOrID: c,
5136
+ options: d ?? {}
5137
+ };
5138
+ if (Array.isArray(a)) {
5139
+ const values = b;
5140
+ return {
5141
+ entries: orderUpdateEntries(a.map((prop, i) => [prop, values[i]])),
5142
+ pathOrID: c,
5143
+ options: d ?? {}
5144
+ };
5145
+ }
5146
+ return {
5147
+ entries: orderUpdateEntries(Object.entries(a)),
5148
+ pathOrID: b,
5149
+ options: c ?? {}
5150
+ };
5151
+ };
5152
+ /**
5153
+ * Applies one or more property updates to a query in place. Shared by
5154
+ * {@link update} and {@link updateInPlace}.
5155
+ */
5156
+ const applyUpdatesInPlace = (query, a, b, c, d) => {
5157
+ const { entries, pathOrID, options } = normalizeUpdateArgs(a, b, c, d);
5158
+ for (const [prop, value] of entries) updateInPlaceSingle(query, prop, value, pathOrID, options);
5159
+ return query;
5160
+ };
5161
+ /**
5162
+ * Updates one or more properties of a rule or group within a query without
5163
+ * mutating the original query. Properties may be supplied individually
5164
+ * (`prop`, `value`), as parallel arrays (`props`, `values`), or as a
5165
+ * property-to-value map. For multi-property updates, `field`, `operator`, and
5166
+ * `valueSource` are applied before `value`, so an explicit `value` is never
5167
+ * reset by a change to one of those properties.
4889
5168
  *
4890
- * @returns A new query with the rule or group property updated.
5169
+ * @returns A new query with the rule or group properties updated.
4891
5170
  *
4892
5171
  * @group Query Tools
4893
5172
  */
4894
- const update = (query, prop, value, pathOrID, options = {}) => (0, immer.produce)(query, (q) => updateInPlace(q, prop, value, pathOrID, options));
5173
+ const update = ((query, a, b, c, d) => (0, immer.produce)(query, (q) => {
5174
+ applyUpdatesInPlace(q, a, b, c, d);
5175
+ }));
4895
5176
  /**
4896
- * Updates a property of a rule or group within a query in place.
5177
+ * Updates one or more properties of a rule or group within a query in place.
5178
+ * See {@link update} for the supported argument forms and ordering semantics.
4897
5179
  *
4898
- * @returns The query (mutated in place) with the rule or group property updated.
5180
+ * @returns The query (mutated in place) with the rule or group properties updated.
4899
5181
  *
4900
5182
  * @group Query Tools
4901
5183
  */
4902
- const updateInPlace = (query, prop, value, pathOrID, options = {}) => {
5184
+ const updateInPlace = ((query, a, b, c, d) => applyUpdatesInPlace(query, a, b, c, d));
5185
+ /**
5186
+ * Updates a single property of a rule or group within a query in place.
5187
+ */
5188
+ const updateInPlaceSingle = (query, prop, value, pathOrID, options = {}) => {
4903
5189
  const { resetOnFieldChange: _resetOnFieldChange = true, resetOnOperatorChange = false, getRuleDefaultOperator = () => "=", getValueSources = () => ["value"], getRuleDefaultValue = () => "", getMatchModes = () => [] } = options;
4904
5190
  let resetOnFieldChange = _resetOnFieldChange;
4905
5191
  const path = Array.isArray(pathOrID) ? pathOrID : getPathOfID(pathOrID, query);
@@ -5150,6 +5436,7 @@ exports.LogType = LogType;
5150
5436
  exports.TestID = TestID;
5151
5437
  exports.add = add;
5152
5438
  exports.addInPlace = addInPlace;
5439
+ exports.betweenOperators = betweenOperators;
5153
5440
  exports.bigIntJsonParseReviver = bigIntJsonParseReviver;
5154
5441
  exports.bigIntJsonStringifyReplacer = bigIntJsonStringifyReplacer;
5155
5442
  exports.celCombinatorMap = celCombinatorMap;
@@ -5244,6 +5531,7 @@ Object.defineProperty(exports, "generateID", {
5244
5531
  });
5245
5532
  exports.getCommonAncestorPath = getCommonAncestorPath;
5246
5533
  exports.getFirstOption = getFirstOption;
5534
+ exports.getLikeWildcards = getLikeWildcards;
5247
5535
  exports.getMatchModesUtil = getMatchModesUtil;
5248
5536
  exports.getNLTranslataion = getNLTranslataion;
5249
5537
  exports.getOption = getOption;
@@ -5252,11 +5540,14 @@ exports.getParseNumberMethod = getParseNumberMethod;
5252
5540
  exports.getPathOfID = getPathOfID;
5253
5541
  exports.getQuoteFieldNamesWithArray = getQuoteFieldNamesWithArray;
5254
5542
  exports.getQuotedFieldName = getQuotedFieldName;
5543
+ exports.getRuleDefaultValue = getRuleDefaultValue;
5544
+ exports.getSQLConcat = getSQLConcat;
5255
5545
  exports.getValidationClassNames = getValidationClassNames;
5256
5546
  exports.getValueSourcesUtil = getValueSourcesUtil;
5257
5547
  exports.group = group;
5258
5548
  exports.groupInPlace = groupInPlace;
5259
5549
  exports.groupInvalidReasons = groupInvalidReasons;
5550
+ exports.inOperators = inOperators;
5260
5551
  exports.insert = insert;
5261
5552
  exports.insertInPlace = insertInPlace;
5262
5553
  exports.isAncestor = isAncestor;
@@ -5288,6 +5579,7 @@ exports.move = move;
5288
5579
  exports.moveInPlace = moveInPlace;
5289
5580
  exports.normalizeConstituentWordOrder = normalizeConstituentWordOrder;
5290
5581
  exports.nullFreeArray = nullFreeArray;
5582
+ exports.nullOperators = nullOperators;
5291
5583
  exports.nullOrUndefinedOrEmpty = nullOrUndefinedOrEmpty;
5292
5584
  exports.numericRegex = numericRegex;
5293
5585
  exports.numerifyValues = numerifyValues;
@@ -5309,6 +5601,7 @@ exports.processMatchMode = processMatchMode;
5309
5601
  exports.queryBuilderFlagDefaults = queryBuilderFlagDefaults;
5310
5602
  exports.regenerateID = regenerateID;
5311
5603
  exports.regenerateIDs = regenerateIDs;
5604
+ exports.relationalOperators = relationalOperators;
5312
5605
  exports.remove = remove;
5313
5606
  exports.removeInPlace = removeInPlace;
5314
5607
  exports.rootPath = rootPath;
@@ -5317,6 +5610,8 @@ exports.sparqlVar = sparqlVar;
5317
5610
  exports.splitBy = splitBy;
5318
5611
  exports.sqlDialectPresets = sqlDialectPresets;
5319
5612
  exports.standardClassnames = standardClassnames;
5613
+ exports.stripParamPrefix = stripParamPrefix;
5614
+ exports.substringOperators = substringOperators;
5320
5615
  exports.toArray = toArray;
5321
5616
  exports.toFlatOptionArray = toFlatOptionArray;
5322
5617
  exports.toFullOption = toFullOption;
@@ -5331,5 +5626,7 @@ exports.uniqOptList = uniqOptList;
5331
5626
  exports.update = update;
5332
5627
  exports.updateInPlace = updateInPlace;
5333
5628
  exports.uuidV4regex = uuidV4regex;
5629
+ exports.withParamPrefix = withParamPrefix;
5630
+ exports.wrapLikeFragment = wrapLikeFragment;
5334
5631
 
5335
5632
  //# sourceMappingURL=react-querybuilder_core.cjs.development.js.map