@react-querybuilder/core 8.22.5 → 8.23.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/derivations/package.json +4 -0
- package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +2078 -1665
- package/dist/cjs/react-querybuilder_core.cjs.development.js +1293 -422
- package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
- package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +2078 -1665
- package/dist/cjs/react-querybuilder_core.cjs.production.js +1 -1
- package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -1
- package/dist/{convertQuery-Cw76XFIn.js → convertQuery-BLT0GIhM.js} +17 -8
- package/dist/{convertQuery-Cw76XFIn.js.map → convertQuery-BLT0GIhM.js.map} +1 -1
- package/dist/{convertQuery-D_4J7E-Z.mjs → convertQuery-DaXv3h7S.mjs} +6 -3
- package/dist/{convertQuery-D_4J7E-Z.mjs.map → convertQuery-DaXv3h7S.mjs.map} +1 -1
- package/dist/derivations.d.mts +2902 -0
- package/dist/derivations.d.ts +2902 -0
- package/dist/derivations.js +2845 -0
- package/dist/derivations.js.map +1 -0
- package/dist/derivations.mjs +2678 -0
- package/dist/derivations.mjs.map +1 -0
- package/dist/formatQuery.d.mts +2 -895
- package/dist/formatQuery.d.ts +2 -895
- package/dist/formatQuery.js +120 -140
- package/dist/formatQuery.js.map +1 -1
- package/dist/formatQuery.mjs +8 -28
- package/dist/formatQuery.mjs.map +1 -1
- package/dist/{import-DVWI7Fdh.d.mts → import-BdKPtLzo.d.mts} +2 -2
- package/dist/{import-6ExjhifL.d.ts → import-BfZTwhp2.d.ts} +2 -2
- package/dist/{index-CX9mehdL.d.mts → index-DOIE2pwx.d.mts} +274 -3
- package/dist/{index-CX9mehdL.d.ts → index-DOIE2pwx.d.ts} +274 -3
- package/dist/index-OF2Q1gTp.d.mts +895 -0
- package/dist/index-XueTy_XQ.d.ts +895 -0
- package/dist/isRuleOrGroupValid-CIMZNkt4.mjs +27 -0
- package/dist/isRuleOrGroupValid-CIMZNkt4.mjs.map +1 -0
- package/dist/isRuleOrGroupValid-CtUf4_4x.js +38 -0
- package/dist/isRuleOrGroupValid-CtUf4_4x.js.map +1 -0
- package/dist/{isRuleGroup-CqLThsbu.mjs → objectUtils-DDZ-KhV5.mjs} +25 -2
- package/dist/objectUtils-DDZ-KhV5.mjs.map +1 -0
- package/dist/{isRuleGroup-0JNiQgLg.js → objectUtils-DfnEmDSV.js} +48 -1
- package/dist/objectUtils-DfnEmDSV.js.map +1 -0
- package/dist/parseCEL.d.mts +2 -2
- package/dist/parseCEL.d.ts +2 -2
- package/dist/parseCEL.js +19 -16
- package/dist/parseCEL.js.map +1 -1
- package/dist/parseCEL.mjs +12 -9
- package/dist/parseCEL.mjs.map +1 -1
- package/dist/parseCypher.d.mts +1 -1
- package/dist/parseCypher.d.ts +1 -1
- package/dist/parseGremlin.d.mts +1 -1
- package/dist/parseGremlin.d.ts +1 -1
- package/dist/parseJSONata.d.mts +2 -2
- package/dist/parseJSONata.d.ts +2 -2
- package/dist/parseJSONata.js +17 -14
- package/dist/parseJSONata.js.map +1 -1
- package/dist/parseJSONata.mjs +11 -8
- package/dist/parseJSONata.mjs.map +1 -1
- package/dist/parseJsonLogic.d.mts +2 -2
- package/dist/parseJsonLogic.d.ts +2 -2
- package/dist/parseJsonLogic.js +38 -38
- package/dist/parseJsonLogic.js.map +1 -1
- package/dist/parseJsonLogic.mjs +5 -5
- package/dist/parseMongoDB.d.mts +2 -2
- package/dist/parseMongoDB.d.ts +2 -2
- package/dist/parseMongoDB.js +50 -47
- package/dist/parseMongoDB.js.map +1 -1
- package/dist/parseMongoDB.mjs +35 -32
- package/dist/parseMongoDB.mjs.map +1 -1
- package/dist/parseSPARQL.d.mts +1 -1
- package/dist/parseSPARQL.d.ts +1 -1
- package/dist/parseSQL.d.mts +2 -2
- package/dist/parseSQL.d.ts +2 -2
- package/dist/parseSQL.js +27 -23
- package/dist/parseSQL.js.map +1 -1
- package/dist/parseSQL.mjs +21 -17
- package/dist/parseSQL.mjs.map +1 -1
- package/dist/parseSpEL.d.mts +2 -2
- package/dist/parseSpEL.d.ts +2 -2
- package/dist/parseSpEL.js +16 -13
- package/dist/parseSpEL.js.map +1 -1
- package/dist/parseSpEL.mjs +12 -9
- package/dist/parseSpEL.mjs.map +1 -1
- package/dist/parserUtils-BKPstAaO.mjs +30 -0
- package/dist/parserUtils-BKPstAaO.mjs.map +1 -0
- package/dist/parserUtils-DbBXyAht.js +41 -0
- package/dist/parserUtils-DbBXyAht.js.map +1 -0
- package/dist/{prepareQueryObjects-BnGL91Tt.js → prepareQueryObjects-Dj9cTl9D.js} +90 -63
- package/dist/prepareQueryObjects-Dj9cTl9D.js.map +1 -0
- package/dist/{prepareQueryObjects-ChINDIap.mjs → prepareQueryObjects-Dmyf3Wi_.mjs} +56 -59
- package/dist/prepareQueryObjects-Dmyf3Wi_.mjs.map +1 -0
- package/dist/react-querybuilder_core.d.mts +2078 -1665
- package/dist/react-querybuilder_core.legacy-esm.d.ts +2078 -1665
- package/dist/react-querybuilder_core.legacy-esm.js +1445 -635
- package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
- package/dist/react-querybuilder_core.mjs +1288 -424
- package/dist/react-querybuilder_core.mjs.map +1 -1
- package/dist/react-querybuilder_core.production.d.mts +2078 -1665
- package/dist/react-querybuilder_core.production.mjs +1 -1
- package/dist/react-querybuilder_core.production.mjs.map +1 -1
- package/dist/transformQuery-B7d9AWUf.d.mts +116 -0
- package/dist/transformQuery-BXDiUBGB.d.ts +116 -0
- package/dist/transformQuery.d.mts +2 -116
- package/dist/transformQuery.d.ts +2 -116
- package/dist/transformQuery.js +3 -4
- package/dist/transformQuery.js.map +1 -1
- package/dist/transformQuery.mjs +1 -2
- package/dist/transformQuery.mjs.map +1 -1
- package/dist/utils-CP5Jqy1P.mjs +1294 -0
- package/dist/utils-CP5Jqy1P.mjs.map +1 -0
- package/dist/utils-e-7KHkjV.js +1779 -0
- package/dist/utils-e-7KHkjV.js.map +1 -0
- package/package.json +33 -22
- package/dist/isRuleGroup-0JNiQgLg.js.map +0 -1
- package/dist/isRuleGroup-CqLThsbu.mjs.map +0 -1
- package/dist/objectUtils-Cr02aGxb.js +0 -27
- package/dist/objectUtils-Cr02aGxb.js.map +0 -1
- package/dist/objectUtils-DBlmJgBf.mjs +0 -16
- package/dist/objectUtils-DBlmJgBf.mjs.map +0 -1
- package/dist/prepareQueryObjects-BnGL91Tt.js.map +0 -1
- package/dist/prepareQueryObjects-ChINDIap.mjs.map +0 -1
- package/dist/utils-4k-j5FBa.mjs +0 -537
- package/dist/utils-4k-j5FBa.mjs.map +0 -1
- package/dist/utils-C79dxwZb.js +0 -752
- package/dist/utils-C79dxwZb.js.map +0 -1
|
@@ -1,6 +1,647 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let numeric_quantity = require("numeric-quantity");
|
|
3
3
|
let immer = require("immer");
|
|
4
|
+
//#region src/controlPropKeys.ts
|
|
5
|
+
/**
|
|
6
|
+
* Runtime data describing the set of query builder controls and the props each one receives.
|
|
7
|
+
*
|
|
8
|
+
* These live in `@react-querybuilder/core` (not `react-querybuilder`) so that non-React ports
|
|
9
|
+
* can consume them without a React dependency.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here can drift from the React implementation unnoticed:
|
|
12
|
+
* `react-querybuilder`'s `types/controlPropKeys.test.ts` gates {@link controlKeys} against
|
|
13
|
+
* `defaultControlElements` and `ControlElementsProp`, and every entry of
|
|
14
|
+
* {@link controlPropKeys} against the corresponding props interface—both at runtime and at
|
|
15
|
+
* compile time, in both directions.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The name of every query builder control, alphabetized.
|
|
19
|
+
*
|
|
20
|
+
* @group Props
|
|
21
|
+
*/
|
|
22
|
+
const controlKeys = [
|
|
23
|
+
"actionElement",
|
|
24
|
+
"addGroupAction",
|
|
25
|
+
"addRuleAction",
|
|
26
|
+
"cloneGroupAction",
|
|
27
|
+
"cloneRuleAction",
|
|
28
|
+
"combinatorSelector",
|
|
29
|
+
"dragHandle",
|
|
30
|
+
"fieldSelector",
|
|
31
|
+
"inlineCombinator",
|
|
32
|
+
"lockGroupAction",
|
|
33
|
+
"lockRuleAction",
|
|
34
|
+
"matchModeEditor",
|
|
35
|
+
"muteGroupAction",
|
|
36
|
+
"muteRuleAction",
|
|
37
|
+
"notToggle",
|
|
38
|
+
"operatorSelector",
|
|
39
|
+
"removeGroupAction",
|
|
40
|
+
"removeRuleAction",
|
|
41
|
+
"rule",
|
|
42
|
+
"ruleGroup",
|
|
43
|
+
"ruleGroupBodyElements",
|
|
44
|
+
"ruleGroupHeaderElements",
|
|
45
|
+
"shiftActions",
|
|
46
|
+
"undoRedoActions",
|
|
47
|
+
"valueEditor",
|
|
48
|
+
"valueSelector",
|
|
49
|
+
"valueSourceSelector"
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* The full set of prop names each default control receives. Ports can use this to declare
|
|
53
|
+
* every prop explicitly instead of relying on fall-through/attribute inheritance.
|
|
54
|
+
*
|
|
55
|
+
* Each array is the complete, alphabetized key set of the control's props interface in
|
|
56
|
+
* `react-querybuilder`. The lists are written out in full rather than composed from shared
|
|
57
|
+
* bases because `--isolatedDeclarations` cannot infer array types built with spreads. A
|
|
58
|
+
* compile-time gate in `react-querybuilder` (`types/controlPropKeys.test.ts`) fails the build
|
|
59
|
+
* if any list drifts from its interface in either direction.
|
|
60
|
+
*
|
|
61
|
+
* @group Props
|
|
62
|
+
*/
|
|
63
|
+
const controlPropKeys = {
|
|
64
|
+
actionElement: [
|
|
65
|
+
"className",
|
|
66
|
+
"context",
|
|
67
|
+
"disabled",
|
|
68
|
+
"disabledTranslation",
|
|
69
|
+
"handleOnClick",
|
|
70
|
+
"label",
|
|
71
|
+
"level",
|
|
72
|
+
"path",
|
|
73
|
+
"ruleOrGroup",
|
|
74
|
+
"rules",
|
|
75
|
+
"schema",
|
|
76
|
+
"testID",
|
|
77
|
+
"title",
|
|
78
|
+
"validation"
|
|
79
|
+
],
|
|
80
|
+
addGroupAction: [
|
|
81
|
+
"className",
|
|
82
|
+
"context",
|
|
83
|
+
"disabled",
|
|
84
|
+
"disabledTranslation",
|
|
85
|
+
"handleOnClick",
|
|
86
|
+
"label",
|
|
87
|
+
"level",
|
|
88
|
+
"path",
|
|
89
|
+
"ruleOrGroup",
|
|
90
|
+
"rules",
|
|
91
|
+
"schema",
|
|
92
|
+
"testID",
|
|
93
|
+
"title",
|
|
94
|
+
"validation"
|
|
95
|
+
],
|
|
96
|
+
addRuleAction: [
|
|
97
|
+
"className",
|
|
98
|
+
"context",
|
|
99
|
+
"disabled",
|
|
100
|
+
"disabledTranslation",
|
|
101
|
+
"handleOnClick",
|
|
102
|
+
"label",
|
|
103
|
+
"level",
|
|
104
|
+
"path",
|
|
105
|
+
"ruleOrGroup",
|
|
106
|
+
"rules",
|
|
107
|
+
"schema",
|
|
108
|
+
"testID",
|
|
109
|
+
"title",
|
|
110
|
+
"validation"
|
|
111
|
+
],
|
|
112
|
+
cloneGroupAction: [
|
|
113
|
+
"className",
|
|
114
|
+
"context",
|
|
115
|
+
"disabled",
|
|
116
|
+
"disabledTranslation",
|
|
117
|
+
"handleOnClick",
|
|
118
|
+
"label",
|
|
119
|
+
"level",
|
|
120
|
+
"path",
|
|
121
|
+
"ruleOrGroup",
|
|
122
|
+
"rules",
|
|
123
|
+
"schema",
|
|
124
|
+
"testID",
|
|
125
|
+
"title",
|
|
126
|
+
"validation"
|
|
127
|
+
],
|
|
128
|
+
cloneRuleAction: [
|
|
129
|
+
"className",
|
|
130
|
+
"context",
|
|
131
|
+
"disabled",
|
|
132
|
+
"disabledTranslation",
|
|
133
|
+
"handleOnClick",
|
|
134
|
+
"label",
|
|
135
|
+
"level",
|
|
136
|
+
"path",
|
|
137
|
+
"ruleOrGroup",
|
|
138
|
+
"rules",
|
|
139
|
+
"schema",
|
|
140
|
+
"testID",
|
|
141
|
+
"title",
|
|
142
|
+
"validation"
|
|
143
|
+
],
|
|
144
|
+
combinatorSelector: [
|
|
145
|
+
"className",
|
|
146
|
+
"context",
|
|
147
|
+
"disabled",
|
|
148
|
+
"handleOnChange",
|
|
149
|
+
"level",
|
|
150
|
+
"options",
|
|
151
|
+
"path",
|
|
152
|
+
"ruleGroup",
|
|
153
|
+
"rules",
|
|
154
|
+
"schema",
|
|
155
|
+
"testID",
|
|
156
|
+
"title",
|
|
157
|
+
"validation",
|
|
158
|
+
"value"
|
|
159
|
+
],
|
|
160
|
+
dragHandle: [
|
|
161
|
+
"className",
|
|
162
|
+
"context",
|
|
163
|
+
"disabled",
|
|
164
|
+
"dragHandleAttributes",
|
|
165
|
+
"label",
|
|
166
|
+
"level",
|
|
167
|
+
"path",
|
|
168
|
+
"ruleOrGroup",
|
|
169
|
+
"schema",
|
|
170
|
+
"testID",
|
|
171
|
+
"title",
|
|
172
|
+
"validation"
|
|
173
|
+
],
|
|
174
|
+
fieldSelector: [
|
|
175
|
+
"className",
|
|
176
|
+
"context",
|
|
177
|
+
"disabled",
|
|
178
|
+
"handleOnChange",
|
|
179
|
+
"level",
|
|
180
|
+
"operator",
|
|
181
|
+
"options",
|
|
182
|
+
"path",
|
|
183
|
+
"rule",
|
|
184
|
+
"schema",
|
|
185
|
+
"testID",
|
|
186
|
+
"title",
|
|
187
|
+
"validation",
|
|
188
|
+
"value"
|
|
189
|
+
],
|
|
190
|
+
inlineCombinator: [
|
|
191
|
+
"className",
|
|
192
|
+
"component",
|
|
193
|
+
"context",
|
|
194
|
+
"disabled",
|
|
195
|
+
"handleOnChange",
|
|
196
|
+
"level",
|
|
197
|
+
"options",
|
|
198
|
+
"path",
|
|
199
|
+
"ruleGroup",
|
|
200
|
+
"rules",
|
|
201
|
+
"schema",
|
|
202
|
+
"testID",
|
|
203
|
+
"title",
|
|
204
|
+
"validation",
|
|
205
|
+
"value"
|
|
206
|
+
],
|
|
207
|
+
lockGroupAction: [
|
|
208
|
+
"className",
|
|
209
|
+
"context",
|
|
210
|
+
"disabled",
|
|
211
|
+
"disabledTranslation",
|
|
212
|
+
"handleOnClick",
|
|
213
|
+
"label",
|
|
214
|
+
"level",
|
|
215
|
+
"path",
|
|
216
|
+
"ruleOrGroup",
|
|
217
|
+
"rules",
|
|
218
|
+
"schema",
|
|
219
|
+
"testID",
|
|
220
|
+
"title",
|
|
221
|
+
"validation"
|
|
222
|
+
],
|
|
223
|
+
lockRuleAction: [
|
|
224
|
+
"className",
|
|
225
|
+
"context",
|
|
226
|
+
"disabled",
|
|
227
|
+
"disabledTranslation",
|
|
228
|
+
"handleOnClick",
|
|
229
|
+
"label",
|
|
230
|
+
"level",
|
|
231
|
+
"path",
|
|
232
|
+
"ruleOrGroup",
|
|
233
|
+
"rules",
|
|
234
|
+
"schema",
|
|
235
|
+
"testID",
|
|
236
|
+
"title",
|
|
237
|
+
"validation"
|
|
238
|
+
],
|
|
239
|
+
matchModeEditor: [
|
|
240
|
+
"className",
|
|
241
|
+
"classNames",
|
|
242
|
+
"context",
|
|
243
|
+
"disabled",
|
|
244
|
+
"field",
|
|
245
|
+
"fieldData",
|
|
246
|
+
"handleOnChange",
|
|
247
|
+
"level",
|
|
248
|
+
"match",
|
|
249
|
+
"numericEditorComponent",
|
|
250
|
+
"options",
|
|
251
|
+
"path",
|
|
252
|
+
"rule",
|
|
253
|
+
"schema",
|
|
254
|
+
"selectorComponent",
|
|
255
|
+
"testID",
|
|
256
|
+
"thresholdPlaceholder",
|
|
257
|
+
"title",
|
|
258
|
+
"validation",
|
|
259
|
+
"value"
|
|
260
|
+
],
|
|
261
|
+
muteGroupAction: [
|
|
262
|
+
"className",
|
|
263
|
+
"context",
|
|
264
|
+
"disabled",
|
|
265
|
+
"disabledTranslation",
|
|
266
|
+
"handleOnClick",
|
|
267
|
+
"label",
|
|
268
|
+
"level",
|
|
269
|
+
"path",
|
|
270
|
+
"ruleOrGroup",
|
|
271
|
+
"rules",
|
|
272
|
+
"schema",
|
|
273
|
+
"testID",
|
|
274
|
+
"title",
|
|
275
|
+
"validation"
|
|
276
|
+
],
|
|
277
|
+
muteRuleAction: [
|
|
278
|
+
"className",
|
|
279
|
+
"context",
|
|
280
|
+
"disabled",
|
|
281
|
+
"disabledTranslation",
|
|
282
|
+
"handleOnClick",
|
|
283
|
+
"label",
|
|
284
|
+
"level",
|
|
285
|
+
"path",
|
|
286
|
+
"ruleOrGroup",
|
|
287
|
+
"rules",
|
|
288
|
+
"schema",
|
|
289
|
+
"testID",
|
|
290
|
+
"title",
|
|
291
|
+
"validation"
|
|
292
|
+
],
|
|
293
|
+
notToggle: [
|
|
294
|
+
"checked",
|
|
295
|
+
"className",
|
|
296
|
+
"context",
|
|
297
|
+
"disabled",
|
|
298
|
+
"handleOnChange",
|
|
299
|
+
"label",
|
|
300
|
+
"level",
|
|
301
|
+
"path",
|
|
302
|
+
"ruleGroup",
|
|
303
|
+
"schema",
|
|
304
|
+
"testID",
|
|
305
|
+
"title",
|
|
306
|
+
"validation"
|
|
307
|
+
],
|
|
308
|
+
operatorSelector: [
|
|
309
|
+
"className",
|
|
310
|
+
"context",
|
|
311
|
+
"disabled",
|
|
312
|
+
"field",
|
|
313
|
+
"fieldData",
|
|
314
|
+
"handleOnChange",
|
|
315
|
+
"level",
|
|
316
|
+
"options",
|
|
317
|
+
"path",
|
|
318
|
+
"rule",
|
|
319
|
+
"schema",
|
|
320
|
+
"testID",
|
|
321
|
+
"title",
|
|
322
|
+
"validation",
|
|
323
|
+
"value"
|
|
324
|
+
],
|
|
325
|
+
removeGroupAction: [
|
|
326
|
+
"className",
|
|
327
|
+
"context",
|
|
328
|
+
"disabled",
|
|
329
|
+
"disabledTranslation",
|
|
330
|
+
"handleOnClick",
|
|
331
|
+
"label",
|
|
332
|
+
"level",
|
|
333
|
+
"path",
|
|
334
|
+
"ruleOrGroup",
|
|
335
|
+
"rules",
|
|
336
|
+
"schema",
|
|
337
|
+
"testID",
|
|
338
|
+
"title",
|
|
339
|
+
"validation"
|
|
340
|
+
],
|
|
341
|
+
removeRuleAction: [
|
|
342
|
+
"className",
|
|
343
|
+
"context",
|
|
344
|
+
"disabled",
|
|
345
|
+
"disabledTranslation",
|
|
346
|
+
"handleOnClick",
|
|
347
|
+
"label",
|
|
348
|
+
"level",
|
|
349
|
+
"path",
|
|
350
|
+
"ruleOrGroup",
|
|
351
|
+
"rules",
|
|
352
|
+
"schema",
|
|
353
|
+
"testID",
|
|
354
|
+
"title",
|
|
355
|
+
"validation"
|
|
356
|
+
],
|
|
357
|
+
rule: [
|
|
358
|
+
"actions",
|
|
359
|
+
"context",
|
|
360
|
+
"disabled",
|
|
361
|
+
"dndRef",
|
|
362
|
+
"dragHandleAttributes",
|
|
363
|
+
"dragMonitorId",
|
|
364
|
+
"dragRef",
|
|
365
|
+
"dropEffect",
|
|
366
|
+
"dropMonitorId",
|
|
367
|
+
"dropNotAllowed",
|
|
368
|
+
"field",
|
|
369
|
+
"groupItems",
|
|
370
|
+
"id",
|
|
371
|
+
"isDragging",
|
|
372
|
+
"isOver",
|
|
373
|
+
"operator",
|
|
374
|
+
"parentDisabled",
|
|
375
|
+
"parentMuted",
|
|
376
|
+
"path",
|
|
377
|
+
"rule",
|
|
378
|
+
"schema",
|
|
379
|
+
"shiftDownDisabled",
|
|
380
|
+
"shiftUpDisabled",
|
|
381
|
+
"translations",
|
|
382
|
+
"value",
|
|
383
|
+
"valueSource"
|
|
384
|
+
],
|
|
385
|
+
ruleGroup: [
|
|
386
|
+
"actions",
|
|
387
|
+
"combinator",
|
|
388
|
+
"context",
|
|
389
|
+
"disabled",
|
|
390
|
+
"dragHandleAttributes",
|
|
391
|
+
"dragMonitorId",
|
|
392
|
+
"dragRef",
|
|
393
|
+
"dropEffect",
|
|
394
|
+
"dropMonitorId",
|
|
395
|
+
"dropNotAllowed",
|
|
396
|
+
"dropRef",
|
|
397
|
+
"groupItems",
|
|
398
|
+
"id",
|
|
399
|
+
"isDragging",
|
|
400
|
+
"isOver",
|
|
401
|
+
"not",
|
|
402
|
+
"parentDisabled",
|
|
403
|
+
"parentMuted",
|
|
404
|
+
"path",
|
|
405
|
+
"previewRef",
|
|
406
|
+
"ruleGroup",
|
|
407
|
+
"rules",
|
|
408
|
+
"schema",
|
|
409
|
+
"shiftDownDisabled",
|
|
410
|
+
"shiftUpDisabled",
|
|
411
|
+
"translations"
|
|
412
|
+
],
|
|
413
|
+
ruleGroupBodyElements: [
|
|
414
|
+
"accessibleDescription",
|
|
415
|
+
"actions",
|
|
416
|
+
"addGroup",
|
|
417
|
+
"addRule",
|
|
418
|
+
"classNames",
|
|
419
|
+
"cloneGroup",
|
|
420
|
+
"combinator",
|
|
421
|
+
"context",
|
|
422
|
+
"disabled",
|
|
423
|
+
"dragHandleAttributes",
|
|
424
|
+
"dragMonitorId",
|
|
425
|
+
"dragRef",
|
|
426
|
+
"dropEffect",
|
|
427
|
+
"dropMonitorId",
|
|
428
|
+
"dropNotAllowed",
|
|
429
|
+
"dropRef",
|
|
430
|
+
"groupItems",
|
|
431
|
+
"id",
|
|
432
|
+
"isDragging",
|
|
433
|
+
"isOver",
|
|
434
|
+
"muted",
|
|
435
|
+
"not",
|
|
436
|
+
"onCombinatorChange",
|
|
437
|
+
"onGroupAdd",
|
|
438
|
+
"onIndependentCombinatorChange",
|
|
439
|
+
"onNotToggleChange",
|
|
440
|
+
"outerClassName",
|
|
441
|
+
"parentDisabled",
|
|
442
|
+
"parentMuted",
|
|
443
|
+
"path",
|
|
444
|
+
"pathsMemo",
|
|
445
|
+
"previewRef",
|
|
446
|
+
"removeGroup",
|
|
447
|
+
"ruleGroup",
|
|
448
|
+
"rules",
|
|
449
|
+
"schema",
|
|
450
|
+
"shiftDownDisabled",
|
|
451
|
+
"shiftGroupDown",
|
|
452
|
+
"shiftGroupUp",
|
|
453
|
+
"shiftUpDisabled",
|
|
454
|
+
"toggleLockGroup",
|
|
455
|
+
"toggleMuteGroup",
|
|
456
|
+
"translations",
|
|
457
|
+
"validationClassName",
|
|
458
|
+
"validationResult"
|
|
459
|
+
],
|
|
460
|
+
ruleGroupHeaderElements: [
|
|
461
|
+
"accessibleDescription",
|
|
462
|
+
"actions",
|
|
463
|
+
"addGroup",
|
|
464
|
+
"addRule",
|
|
465
|
+
"classNames",
|
|
466
|
+
"cloneGroup",
|
|
467
|
+
"combinator",
|
|
468
|
+
"context",
|
|
469
|
+
"disabled",
|
|
470
|
+
"dragHandleAttributes",
|
|
471
|
+
"dragMonitorId",
|
|
472
|
+
"dragRef",
|
|
473
|
+
"dropEffect",
|
|
474
|
+
"dropMonitorId",
|
|
475
|
+
"dropNotAllowed",
|
|
476
|
+
"dropRef",
|
|
477
|
+
"groupItems",
|
|
478
|
+
"id",
|
|
479
|
+
"isDragging",
|
|
480
|
+
"isOver",
|
|
481
|
+
"muted",
|
|
482
|
+
"not",
|
|
483
|
+
"onCombinatorChange",
|
|
484
|
+
"onGroupAdd",
|
|
485
|
+
"onIndependentCombinatorChange",
|
|
486
|
+
"onNotToggleChange",
|
|
487
|
+
"outerClassName",
|
|
488
|
+
"parentDisabled",
|
|
489
|
+
"parentMuted",
|
|
490
|
+
"path",
|
|
491
|
+
"pathsMemo",
|
|
492
|
+
"previewRef",
|
|
493
|
+
"removeGroup",
|
|
494
|
+
"ruleGroup",
|
|
495
|
+
"rules",
|
|
496
|
+
"schema",
|
|
497
|
+
"shiftDownDisabled",
|
|
498
|
+
"shiftGroupDown",
|
|
499
|
+
"shiftGroupUp",
|
|
500
|
+
"shiftUpDisabled",
|
|
501
|
+
"toggleLockGroup",
|
|
502
|
+
"toggleMuteGroup",
|
|
503
|
+
"translations",
|
|
504
|
+
"validationClassName",
|
|
505
|
+
"validationResult"
|
|
506
|
+
],
|
|
507
|
+
shiftActions: [
|
|
508
|
+
"className",
|
|
509
|
+
"context",
|
|
510
|
+
"disabled",
|
|
511
|
+
"labels",
|
|
512
|
+
"level",
|
|
513
|
+
"path",
|
|
514
|
+
"ruleOrGroup",
|
|
515
|
+
"schema",
|
|
516
|
+
"shiftDown",
|
|
517
|
+
"shiftDownDisabled",
|
|
518
|
+
"shiftUp",
|
|
519
|
+
"shiftUpDisabled",
|
|
520
|
+
"testID",
|
|
521
|
+
"title",
|
|
522
|
+
"titles",
|
|
523
|
+
"validation"
|
|
524
|
+
],
|
|
525
|
+
undoRedoActions: [
|
|
526
|
+
"className",
|
|
527
|
+
"classNames",
|
|
528
|
+
"context",
|
|
529
|
+
"disabled",
|
|
530
|
+
"labels",
|
|
531
|
+
"level",
|
|
532
|
+
"path",
|
|
533
|
+
"ruleOrGroup",
|
|
534
|
+
"schema",
|
|
535
|
+
"testID",
|
|
536
|
+
"title",
|
|
537
|
+
"titles",
|
|
538
|
+
"validation"
|
|
539
|
+
],
|
|
540
|
+
valueEditor: [
|
|
541
|
+
"className",
|
|
542
|
+
"context",
|
|
543
|
+
"disabled",
|
|
544
|
+
"field",
|
|
545
|
+
"fieldData",
|
|
546
|
+
"handleOnChange",
|
|
547
|
+
"inputType",
|
|
548
|
+
"level",
|
|
549
|
+
"listsAsArrays",
|
|
550
|
+
"operator",
|
|
551
|
+
"parseNumbers",
|
|
552
|
+
"path",
|
|
553
|
+
"rule",
|
|
554
|
+
"schema",
|
|
555
|
+
"selectorComponent",
|
|
556
|
+
"separator",
|
|
557
|
+
"skipHook",
|
|
558
|
+
"testID",
|
|
559
|
+
"title",
|
|
560
|
+
"type",
|
|
561
|
+
"validation",
|
|
562
|
+
"value",
|
|
563
|
+
"valueSource",
|
|
564
|
+
"values"
|
|
565
|
+
],
|
|
566
|
+
valueSelector: [
|
|
567
|
+
"className",
|
|
568
|
+
"context",
|
|
569
|
+
"disabled",
|
|
570
|
+
"handleOnChange",
|
|
571
|
+
"level",
|
|
572
|
+
"listsAsArrays",
|
|
573
|
+
"multiple",
|
|
574
|
+
"options",
|
|
575
|
+
"path",
|
|
576
|
+
"schema",
|
|
577
|
+
"testID",
|
|
578
|
+
"title",
|
|
579
|
+
"validation",
|
|
580
|
+
"value"
|
|
581
|
+
],
|
|
582
|
+
valueSourceSelector: [
|
|
583
|
+
"className",
|
|
584
|
+
"context",
|
|
585
|
+
"disabled",
|
|
586
|
+
"field",
|
|
587
|
+
"fieldData",
|
|
588
|
+
"handleOnChange",
|
|
589
|
+
"level",
|
|
590
|
+
"options",
|
|
591
|
+
"path",
|
|
592
|
+
"rule",
|
|
593
|
+
"schema",
|
|
594
|
+
"testID",
|
|
595
|
+
"title",
|
|
596
|
+
"validation",
|
|
597
|
+
"value"
|
|
598
|
+
]
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* Which bulk override, if any, applies to each control: `"action"` for controls that a supplied
|
|
602
|
+
* `actionElement` replaces, `"selector"` for controls that a supplied `valueSelector` replaces,
|
|
603
|
+
* and `null` for controls that neither replaces.
|
|
604
|
+
*
|
|
605
|
+
* `actionElement` and `valueSelector` are themselves `null`—they are the _source_ of a bulk
|
|
606
|
+
* override, not a target of one.
|
|
607
|
+
*
|
|
608
|
+
* Replaces name-suffix sniffing (`key.endsWith('Action')`), which would silently misclassify a
|
|
609
|
+
* future control named e.g. `pathSelector`, and which disagrees between implementations about
|
|
610
|
+
* whether `shiftActions`/`undoRedoActions` (plural) match. They do not: neither receives the
|
|
611
|
+
* `actionElement` bulk override.
|
|
612
|
+
*
|
|
613
|
+
* @group Props
|
|
614
|
+
*/
|
|
615
|
+
const controlKind = {
|
|
616
|
+
actionElement: null,
|
|
617
|
+
addGroupAction: "action",
|
|
618
|
+
addRuleAction: "action",
|
|
619
|
+
cloneGroupAction: "action",
|
|
620
|
+
cloneRuleAction: "action",
|
|
621
|
+
combinatorSelector: "selector",
|
|
622
|
+
dragHandle: null,
|
|
623
|
+
fieldSelector: "selector",
|
|
624
|
+
inlineCombinator: null,
|
|
625
|
+
lockGroupAction: "action",
|
|
626
|
+
lockRuleAction: "action",
|
|
627
|
+
matchModeEditor: null,
|
|
628
|
+
muteGroupAction: "action",
|
|
629
|
+
muteRuleAction: "action",
|
|
630
|
+
notToggle: null,
|
|
631
|
+
operatorSelector: "selector",
|
|
632
|
+
removeGroupAction: "action",
|
|
633
|
+
removeRuleAction: "action",
|
|
634
|
+
rule: null,
|
|
635
|
+
ruleGroup: null,
|
|
636
|
+
ruleGroupBodyElements: null,
|
|
637
|
+
ruleGroupHeaderElements: null,
|
|
638
|
+
shiftActions: null,
|
|
639
|
+
undoRedoActions: null,
|
|
640
|
+
valueEditor: null,
|
|
641
|
+
valueSelector: null,
|
|
642
|
+
valueSourceSelector: "selector"
|
|
643
|
+
};
|
|
644
|
+
//#endregion
|
|
4
645
|
//#region src/defaults.ts
|
|
5
646
|
/**
|
|
6
647
|
* @group Defaults
|
|
@@ -649,6 +1290,31 @@ const defaultMaxHistory = 50;
|
|
|
649
1290
|
*/
|
|
650
1291
|
const defaultCoalesceMs = 500;
|
|
651
1292
|
//#endregion
|
|
1293
|
+
//#region src/utils/abortReasons.ts
|
|
1294
|
+
/**
|
|
1295
|
+
* Abort reasons that {@link QueryManager}'s `strict` mode treats as errors. The remaining
|
|
1296
|
+
* reasons—`"same-location"` and `"no-change"`—describe valid operations that had nothing to do,
|
|
1297
|
+
* so they are reported to `onInvalidTarget` but never throw.
|
|
1298
|
+
*
|
|
1299
|
+
* Declared apart from `QueryManager` so the `@react-querybuilder/core/derivations` entry point can
|
|
1300
|
+
* export it without putting the manager in its module graph.
|
|
1301
|
+
*
|
|
1302
|
+
* @group Query Tools
|
|
1303
|
+
*/
|
|
1304
|
+
const strictAbortReasons = [
|
|
1305
|
+
"target-not-found",
|
|
1306
|
+
"parent-not-found",
|
|
1307
|
+
"parent-not-a-group",
|
|
1308
|
+
"destination-not-found",
|
|
1309
|
+
"root-not-allowed",
|
|
1310
|
+
"not-a-combinator-slot",
|
|
1311
|
+
"target-disabled",
|
|
1312
|
+
"parent-disabled",
|
|
1313
|
+
"max-levels-exceeded"
|
|
1314
|
+
];
|
|
1315
|
+
/** @internal */
|
|
1316
|
+
const strictAbortReasonSet = new Set(strictAbortReasons);
|
|
1317
|
+
//#endregion
|
|
652
1318
|
//#region src/utils/arrayUtils.ts
|
|
653
1319
|
/**
|
|
654
1320
|
* Splits a string by a given character (see {@link defaultJoinChar}). Escaped characters
|
|
@@ -751,6 +1417,94 @@ const isRuleGroupType = (rg) => isRuleGroup(rg) && typeof rg.combinator === "str
|
|
|
751
1417
|
*/
|
|
752
1418
|
const isRuleGroupTypeIC = (rg) => isRuleGroup(rg) && rg.combinator === void 0;
|
|
753
1419
|
//#endregion
|
|
1420
|
+
//#region src/utils/signature.ts
|
|
1421
|
+
/**
|
|
1422
|
+
* Signature returned when a change alters the _shape_ of the query—rules or groups added,
|
|
1423
|
+
* removed, moved, or reordered—rather than the properties of a single node. Structural changes
|
|
1424
|
+
* never coalesce with each other, so each one produces its own history entry.
|
|
1425
|
+
*/
|
|
1426
|
+
const structuralSignature = "~structural";
|
|
1427
|
+
/**
|
|
1428
|
+
* Signature returned when two queries differ by reference only, with no observable difference
|
|
1429
|
+
* in their properties.
|
|
1430
|
+
*/
|
|
1431
|
+
const unchangedSignature = "";
|
|
1432
|
+
/**
|
|
1433
|
+
* Returns the list of property names that differ between two nodes, ignoring `rules` (which is
|
|
1434
|
+
* compared structurally by the caller).
|
|
1435
|
+
*/
|
|
1436
|
+
const changedProps = (prev, next) => {
|
|
1437
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
1438
|
+
keys.delete("rules");
|
|
1439
|
+
const changed = [];
|
|
1440
|
+
for (const key of keys) if (!Object.is(prev[key], next[key])) changed.push(key);
|
|
1441
|
+
return changed.toSorted();
|
|
1442
|
+
};
|
|
1443
|
+
const signatureOfNode = (prev, next, parentId, index) => {
|
|
1444
|
+
if (prev === next) return "";
|
|
1445
|
+
if (typeof prev === "string" || typeof next === "string") return typeof prev === typeof next ? `${parentId}:combinator[${index}]` : structuralSignature;
|
|
1446
|
+
const prevIsGroup = isRuleGroup(prev);
|
|
1447
|
+
const nextIsGroup = isRuleGroup(next);
|
|
1448
|
+
if (prevIsGroup !== nextIsGroup) return structuralSignature;
|
|
1449
|
+
if (!prevIsGroup || !nextIsGroup) {
|
|
1450
|
+
const props = changedProps(prev, next);
|
|
1451
|
+
return props.length === 0 ? "" : `${next.id ?? ""}:${props.join(",")}`;
|
|
1452
|
+
}
|
|
1453
|
+
if (prev.rules.length !== next.rules.length) return structuralSignature;
|
|
1454
|
+
const ownProps = changedProps(prev, next);
|
|
1455
|
+
let changedIndex = -1;
|
|
1456
|
+
for (const [i, prevRule] of prev.rules.entries()) if (prevRule !== next.rules[i]) {
|
|
1457
|
+
if (changedIndex !== -1) return structuralSignature;
|
|
1458
|
+
changedIndex = i;
|
|
1459
|
+
}
|
|
1460
|
+
if (changedIndex === -1) return ownProps.length === 0 ? "" : `${next.id ?? ""}:${ownProps.join(",")}`;
|
|
1461
|
+
if (ownProps.length > 0) return structuralSignature;
|
|
1462
|
+
return signatureOfNode(prev.rules[changedIndex], next.rules[changedIndex], next.id ?? "", changedIndex);
|
|
1463
|
+
};
|
|
1464
|
+
/**
|
|
1465
|
+
* Describes _what changed_ between two versions of a query as a short string, so that
|
|
1466
|
+
* consecutive edits to the same property of the same rule (e.g. typing in a value editor) can
|
|
1467
|
+
* be recognized and coalesced into a single history entry.
|
|
1468
|
+
*
|
|
1469
|
+
* Returns {@link structuralSignature} for changes to the shape of the query, {@link unchangedSignature} when the
|
|
1470
|
+
* two queries differ by reference only, and `"<id>:<props>"` otherwise.
|
|
1471
|
+
*
|
|
1472
|
+
* The walk prunes on reference equality, so it costs O(depth) rather than O(size) for the
|
|
1473
|
+
* single-node edits that make up the overwhelming majority of changes.
|
|
1474
|
+
*
|
|
1475
|
+
* Note that this relies on the structural sharing that Immer—and therefore every query
|
|
1476
|
+
* produced by RQB's own update functions—guarantees: nodes that did not change keep their
|
|
1477
|
+
* identity. A query that has been wholly rebuilt (deep-cloned, round-tripped through JSON,
|
|
1478
|
+
* re-parsed from a string) shares no identity with its predecessor, so it is reported as
|
|
1479
|
+
* {@link structuralSignature} and will not coalesce. That is a graceful degradation—every change simply
|
|
1480
|
+
* gets its own history entry—but controlled components that clone the query on every change
|
|
1481
|
+
* will not benefit from coalescing.
|
|
1482
|
+
*/
|
|
1483
|
+
const signatureOf = (prev, next) => signatureOfNode(prev, next, "", -1);
|
|
1484
|
+
//#endregion
|
|
1485
|
+
//#region src/utils/coalesce.ts
|
|
1486
|
+
/**
|
|
1487
|
+
* Determines whether a change should be absorbed into the current history entry instead of
|
|
1488
|
+
* pushing a new one. This is the exact rule {@link QueryManager} applies when recording history,
|
|
1489
|
+
* exposed so non-React implementations can manage their own history stacks without
|
|
1490
|
+
* reimplementing (and drifting from) the semantics.
|
|
1491
|
+
*
|
|
1492
|
+
* A change coalesces only when all three hold:
|
|
1493
|
+
* - the change is not structural (rules/groups added, removed, moved, or reordered)
|
|
1494
|
+
* - its signature matches the previously recorded signature
|
|
1495
|
+
* - it occurred within `coalesceMs` of the previous recording
|
|
1496
|
+
*
|
|
1497
|
+
* Note that {@link unchangedSignature} is not handled here. A change with no observable
|
|
1498
|
+
* difference is never recorded at all, which is a separate decision made before this check.
|
|
1499
|
+
*
|
|
1500
|
+
* @param prevSig Signature of the previously recorded change, or `undefined` if there is none.
|
|
1501
|
+
* @param nextSig Signature of the change being recorded, from {@link signatureOf}.
|
|
1502
|
+
* @param prevAt Timestamp of the previous recording.
|
|
1503
|
+
* @param now Timestamp of the change being recorded.
|
|
1504
|
+
* @param coalesceMs Coalescing window in milliseconds.
|
|
1505
|
+
*/
|
|
1506
|
+
const shouldCoalesce = (prevSig, nextSig, prevAt, now, coalesceMs = 500) => nextSig !== "~structural" && nextSig === prevSig && now >= prevAt && now - prevAt < coalesceMs;
|
|
1507
|
+
//#endregion
|
|
754
1508
|
//#region src/utils/convertQuery.ts
|
|
755
1509
|
const combinatorLevels = [
|
|
756
1510
|
"or",
|
|
@@ -1264,6 +2018,20 @@ const uniqOptList = (originalArray) => {
|
|
|
1264
2018
|
if (isFlexibleOptionGroupArray(originalArray)) return uniqOptGroups(originalArray);
|
|
1265
2019
|
return uniqByIdentifier(originalArray.map((o) => toFullOption(o)));
|
|
1266
2020
|
};
|
|
2021
|
+
/**
|
|
2022
|
+
* Normalizes any accepted option list shape—array, option groups, or a record—into a
|
|
2023
|
+
* `FullOptionList`, applying `baseOption` properties and (when `autoSelectOption` is `false`)
|
|
2024
|
+
* a leading placeholder option. Also returns the flattened lookup map and the option that
|
|
2025
|
+
* should be selected by default.
|
|
2026
|
+
*
|
|
2027
|
+
* Note: `labelMap` overrides only apply to array/option group input (where string options are
|
|
2028
|
+
* expanded); record input derives labels from the record values themselves.
|
|
2029
|
+
*
|
|
2030
|
+
* This is the same normalization `<QueryBuilder />` applies to `fields`, `operators`,
|
|
2031
|
+
* `combinators`, and value lists, so a non-React implementation resolves options identically.
|
|
2032
|
+
*
|
|
2033
|
+
* @group Option Lists
|
|
2034
|
+
*/
|
|
1267
2035
|
const prepareOptionList = (props) => {
|
|
1268
2036
|
// v8 ignore next
|
|
1269
2037
|
const { optionList: optionListPropOriginal, baseOption = {}, labelMap = {}, placeholder: { placeholderName = "~", placeholderLabel = defaultPlaceholderLabel, placeholderGroupLabel = defaultPlaceholderLabel } = {}, autoSelectOption = true } = props;
|
|
@@ -4562,8 +5330,10 @@ const defaultRuleProcessorParameterized = (rule, opts, meta) => {
|
|
|
4562
5330
|
return finalize(`${qPre}${rule.field}${qPost} ${sqlOperator} ${paramPrefix}${firstParamName} and ${paramPrefix}${secondParamName}`);
|
|
4563
5331
|
}
|
|
4564
5332
|
let paramValue = rule.value;
|
|
4565
|
-
if (typeof rule.value === "string")
|
|
4566
|
-
|
|
5333
|
+
if (typeof rule.value === "string") {
|
|
5334
|
+
if (shouldRenderAsNumber(rule.value, parseNumbers)) paramValue = parseNumber(rule.value, { parseNumbers });
|
|
5335
|
+
else paramValue = /^'.*'$/g.test(value) ? value.replaceAll(/(^'|'$)/g, "") : /* v8 ignore next -- @preserve */ value;
|
|
5336
|
+
}
|
|
4567
5337
|
let paramName = "";
|
|
4568
5338
|
if (parameterized) params.push(paramValue);
|
|
4569
5339
|
else {
|
|
@@ -5285,6 +6055,12 @@ const derivePathInfo = (path, childCount, { disabled = false, disabledPaths = []
|
|
|
5285
6055
|
};
|
|
5286
6056
|
//#endregion
|
|
5287
6057
|
//#region src/utils/generateAccessibleDescription.ts
|
|
6058
|
+
/**
|
|
6059
|
+
* The default `accessibleDescriptionGenerator`. Produces the `aria-label` for a rule group:
|
|
6060
|
+
* `"Query builder"` for the root group, `"Rule group at path 0-1"` for any other.
|
|
6061
|
+
*
|
|
6062
|
+
* @group Accessibility
|
|
6063
|
+
*/
|
|
5288
6064
|
const generateAccessibleDescription = (params) => pathsAreEqual([], params.path) ? `Query builder` : `Rule group at path ${params.path.join("-")}`;
|
|
5289
6065
|
//#endregion
|
|
5290
6066
|
//#region src/utils/generateID.ts
|
|
@@ -5323,6 +6099,29 @@ if (cryptoModule) {
|
|
|
5323
6099
|
}
|
|
5324
6100
|
}
|
|
5325
6101
|
//#endregion
|
|
6102
|
+
//#region src/utils/immerInstances.ts
|
|
6103
|
+
/**
|
|
6104
|
+
* Globally enables or disables immer's auto-freeze, i.e. the deep freeze applied to every query
|
|
6105
|
+
* returned by {@link add}, {@link update}, {@link remove}, {@link move}, {@link insert}, and
|
|
6106
|
+
* {@link group}.
|
|
6107
|
+
*
|
|
6108
|
+
* Re-exported from immer so that consumers mixing these tools with their own `produce` calls can
|
|
6109
|
+
* switch both at once. Prefer the per-call `freeze` option, or the {@link QueryManager} option of
|
|
6110
|
+
* the same name, when the change should not be process-wide. A per-call `freeze: false` wins
|
|
6111
|
+
* regardless of this setting; a per-call `freeze: true` does not re-enable freezing once this has
|
|
6112
|
+
* turned it off, since it selects immer's default instance.
|
|
6113
|
+
*
|
|
6114
|
+
* @group Query Tools
|
|
6115
|
+
*/
|
|
6116
|
+
const setAutoFreeze = immer.setAutoFreeze;
|
|
6117
|
+
const unfrozenImmer = new immer.Immer({ autoFreeze: false });
|
|
6118
|
+
/**
|
|
6119
|
+
* The `produce` implementation matching the requested freeze behavior.
|
|
6120
|
+
*
|
|
6121
|
+
* @internal
|
|
6122
|
+
*/
|
|
6123
|
+
const producerFor = (freeze = true) => freeze ? immer.produce : unfrozenImmer.produce;
|
|
6124
|
+
//#endregion
|
|
5326
6125
|
//#region src/utils/getMatchModesUtil.ts
|
|
5327
6126
|
const dummyFD$1 = {
|
|
5328
6127
|
name: "name",
|
|
@@ -5575,6 +6374,46 @@ const resolveValueList = ({ field, operator, fieldData, getValues, placeholder,
|
|
|
5575
6374
|
autoSelectOption
|
|
5576
6375
|
}).optionList;
|
|
5577
6376
|
//#endregion
|
|
6377
|
+
//#region src/utils/optionsEqual.ts
|
|
6378
|
+
const isPlainObject = (x) => {
|
|
6379
|
+
const proto = Object.getPrototypeOf(x);
|
|
6380
|
+
return proto === null || proto === Object.prototype;
|
|
6381
|
+
};
|
|
6382
|
+
/**
|
|
6383
|
+
* Structural equality for {@link QueryManagerOptions} values. Arrays and plain objects are
|
|
6384
|
+
* compared by value; everything else — functions, class instances, `Map`s, `Date`s — by
|
|
6385
|
+
* identity.
|
|
6386
|
+
*
|
|
6387
|
+
* That split is what makes an options object rebuilt on every render compare equal as long as
|
|
6388
|
+
* its _data_ did not change, which is the entire point: a caller that passes object literals
|
|
6389
|
+
* (`fields={[...]}`, `translations={{...}}`) hands a fresh identity to every reconfigure, so an
|
|
6390
|
+
* identity-only comparison would report a change every time.
|
|
6391
|
+
*
|
|
6392
|
+
* Comparing functions by identity is deliberate rather than a limitation. Two functions cannot
|
|
6393
|
+
* be proven equivalent, so a caller that rebuilds `getDefaultValue` per render must either
|
|
6394
|
+
* memoize it or accept the reconfigure.
|
|
6395
|
+
*/
|
|
6396
|
+
const valuesEqual = (a, b) => {
|
|
6397
|
+
if (Object.is(a, b)) return true;
|
|
6398
|
+
if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => valuesEqual(v, b[i]));
|
|
6399
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
6400
|
+
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b) || !isPlainObject(a)) return false;
|
|
6401
|
+
const aKeys = Object.keys(a);
|
|
6402
|
+
return aKeys.length === Object.keys(b).length && aKeys.every((k) => valuesEqual(a[k], b[k]));
|
|
6403
|
+
};
|
|
6404
|
+
/**
|
|
6405
|
+
* Whether two {@link QueryManagerOptions} objects describe the same configuration, per
|
|
6406
|
+
* {@link valuesEqual}: data by value, functions by identity.
|
|
6407
|
+
*
|
|
6408
|
+
* {@link QueryManager.reconfigure} uses this to gate itself, so most callers never need it
|
|
6409
|
+
* directly. It is exported for framework adapters that decide whether to _call_ `reconfigure`
|
|
6410
|
+
* at all — skipping the call avoids building the merged options object in the first place.
|
|
6411
|
+
*
|
|
6412
|
+
* Nested option objects (`history`, `translations`, …) are descended into rather than compared
|
|
6413
|
+
* by identity, so `{ history: { maxHistory: 10 } }` rebuilt per render compares equal.
|
|
6414
|
+
*/
|
|
6415
|
+
const optionsEqual = (a, b) => valuesEqual(a, b);
|
|
6416
|
+
//#endregion
|
|
5578
6417
|
//#region src/utils/preferProp.ts
|
|
5579
6418
|
const preferPropDefaultTrue = (prop, context) => prop === false ? false : prop ? true : !(context === false);
|
|
5580
6419
|
const preferPropDefaultFalse = (prop, context) => prop ? true : prop === false ? false : !!context;
|
|
@@ -5711,7 +6550,7 @@ const exceedsMaxLevels = (parentPath, { maxLevels = Infinity } = {}) => !!parent
|
|
|
5711
6550
|
*
|
|
5712
6551
|
* @group Query Tools
|
|
5713
6552
|
*/
|
|
5714
|
-
const add = (query, ruleOrGroup, parentPathOrID, options = {}) => (
|
|
6553
|
+
const add = (query, ruleOrGroup, parentPathOrID, options = {}) => producerFor(options.freeze)(query, (q) => addInPlace(q, ruleOrGroup, parentPathOrID, options));
|
|
5715
6554
|
/**
|
|
5716
6555
|
* Adds a rule or group to a query in place.
|
|
5717
6556
|
*
|
|
@@ -5803,6 +6642,11 @@ const normalizeUpdateArgs = (a, b, c, d) => {
|
|
|
5803
6642
|
};
|
|
5804
6643
|
};
|
|
5805
6644
|
/**
|
|
6645
|
+
* The options argument of an {@link update} call, whose position depends on the argument form.
|
|
6646
|
+
* Cheaper than {@link normalizeUpdateArgs} when only the options are needed.
|
|
6647
|
+
*/
|
|
6648
|
+
const updateOptionsOf = (a, b, c, d) => (typeof a === "string" || Array.isArray(a) ? d : c) ?? {};
|
|
6649
|
+
/**
|
|
5806
6650
|
* Applies one or more property updates to a query in place. Shared by
|
|
5807
6651
|
* {@link update} and {@link updateInPlace}.
|
|
5808
6652
|
*/
|
|
@@ -5823,7 +6667,7 @@ const applyUpdatesInPlace = (query, a, b, c, d) => {
|
|
|
5823
6667
|
*
|
|
5824
6668
|
* @group Query Tools
|
|
5825
6669
|
*/
|
|
5826
|
-
const update = ((query, a, b, c, d) => (
|
|
6670
|
+
const update = ((query, a, b, c, d) => producerFor(updateOptionsOf(a, b, c, d).freeze)(query, (q) => {
|
|
5827
6671
|
applyUpdatesInPlace(q, a, b, c, d);
|
|
5828
6672
|
}));
|
|
5829
6673
|
/**
|
|
@@ -5871,13 +6715,14 @@ const updateInPlaceSingle = (query, prop, value, pathOrID, options = {}) => {
|
|
|
5871
6715
|
return query;
|
|
5872
6716
|
}
|
|
5873
6717
|
const parentRules = parent.rules;
|
|
5874
|
-
if (path.at(-1) % 2 === 1)
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
6718
|
+
if (path.at(-1) % 2 === 1) {
|
|
6719
|
+
if (parentRules[path.at(-1)] === value) onAbort?.({
|
|
6720
|
+
reason: "no-change",
|
|
6721
|
+
operation: "update",
|
|
6722
|
+
pathOrID
|
|
6723
|
+
});
|
|
6724
|
+
else parentRules[path.at(-1)] = value;
|
|
6725
|
+
} else onAbort?.({
|
|
5881
6726
|
reason: "not-a-combinator-slot",
|
|
5882
6727
|
operation: "update",
|
|
5883
6728
|
pathOrID
|
|
@@ -5947,7 +6792,7 @@ const updateInPlaceSingle = (query, prop, value, pathOrID, options = {}) => {
|
|
|
5947
6792
|
*
|
|
5948
6793
|
* @group Query Tools
|
|
5949
6794
|
*/
|
|
5950
|
-
const remove = (query, pathOrID, options = {}) => (
|
|
6795
|
+
const remove = (query, pathOrID, options = {}) => producerFor(options.freeze)(query, (q) => removeInPlace(q, pathOrID, options));
|
|
5951
6796
|
/**
|
|
5952
6797
|
* Removes a rule or group from a query in place.
|
|
5953
6798
|
*
|
|
@@ -6002,25 +6847,28 @@ const removeInPlace = (query, pathOrID, options = {}) => {
|
|
|
6002
6847
|
const getNextPath = (query, currentPath, newPathOrShiftDirection) => {
|
|
6003
6848
|
if (Array.isArray(newPathOrShiftDirection)) return newPathOrShiftDirection;
|
|
6004
6849
|
const ic = isRuleGroupTypeIC(query);
|
|
6005
|
-
if (newPathOrShiftDirection === "up")
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
else if (
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6850
|
+
if (newPathOrShiftDirection === "up") {
|
|
6851
|
+
if (pathsAreEqual(currentPath, [0])) return currentPath;
|
|
6852
|
+
else if (currentPath.at(-1) === 0) {
|
|
6853
|
+
const parentPath = getParentPath(currentPath);
|
|
6854
|
+
return [...getParentPath(parentPath), Math.max(0, parentPath.at(-1) - (ic ? 1 : 0))];
|
|
6855
|
+
} else {
|
|
6856
|
+
const evaluationPath = [...getParentPath(currentPath), Math.max(0, currentPath.at(-1) - (ic ? 2 : 1))];
|
|
6857
|
+
const entityAtTarget = findPath(evaluationPath, query);
|
|
6858
|
+
if (isRuleGroup(entityAtTarget)) return [...evaluationPath, entityAtTarget.rules.length];
|
|
6859
|
+
else return [...getParentPath(currentPath), Math.max(0, currentPath.at(-1) - (ic ? 3 : 1))];
|
|
6860
|
+
}
|
|
6861
|
+
} else if (newPathOrShiftDirection === "down") {
|
|
6862
|
+
if (pathsAreEqual([query.rules.length - 1], currentPath)) return currentPath;
|
|
6863
|
+
else if (currentPath.at(-1) === findPath(getParentPath(currentPath), query).rules.length - 1) {
|
|
6864
|
+
const parentPath = getParentPath(currentPath);
|
|
6865
|
+
return [...getParentPath(parentPath), parentPath.at(-1) + 1];
|
|
6866
|
+
} else {
|
|
6867
|
+
const evaluationPath = [...getParentPath(currentPath), currentPath.at(-1) + (ic ? 2 : 1)];
|
|
6868
|
+
const entityToEvaluate = findPath(evaluationPath, query);
|
|
6869
|
+
if (isRuleGroup(entityToEvaluate)) return [...evaluationPath, 0];
|
|
6870
|
+
else return [...getParentPath(currentPath), currentPath.at(-1) + (ic ? 3 : 2)];
|
|
6871
|
+
}
|
|
6024
6872
|
}
|
|
6025
6873
|
return currentPath;
|
|
6026
6874
|
};
|
|
@@ -6032,7 +6880,7 @@ const getNextPath = (query, currentPath, newPathOrShiftDirection) => {
|
|
|
6032
6880
|
*
|
|
6033
6881
|
* @group Query Tools
|
|
6034
6882
|
*/
|
|
6035
|
-
const move = (query, oldPathOrID, newPath, options = {}) => (
|
|
6883
|
+
const move = (query, oldPathOrID, newPath, options = {}) => producerFor(options.freeze)(query, (q) => moveInPlace(q, oldPathOrID, newPath, options));
|
|
6036
6884
|
/**
|
|
6037
6885
|
* Moves a rule or group from one path to another in place.
|
|
6038
6886
|
* In the options parameter, pass `{ clone: true }` to copy instead of move.
|
|
@@ -6128,9 +6976,10 @@ const moveInPlace = (query, oldPathOrID, newPath, options = {}) => {
|
|
|
6128
6976
|
*/
|
|
6129
6977
|
const insertRuleOrGroup = (...args) => parentToInsertInto.rules.splice(spliceIndex, 0, ...args);
|
|
6130
6978
|
if (parentToInsertInto.rules.length === 0 || !independentCombinators) insertRuleOrGroup(ruleOrGroup);
|
|
6131
|
-
else if (newIndex === 0)
|
|
6132
|
-
|
|
6133
|
-
|
|
6979
|
+
else if (newIndex === 0) {
|
|
6980
|
+
if (ruleToRemoveIndex === 0 && oldNextCombinator) insertRuleOrGroup(ruleOrGroup, oldNextCombinator);
|
|
6981
|
+
else insertRuleOrGroup(ruleOrGroup, parentToInsertInto.rules[1] ?? oldPrevCombinator ?? getFirstOption(combinators));
|
|
6982
|
+
} else if (oldPrevCombinator) insertRuleOrGroup(oldPrevCombinator, ruleOrGroup);
|
|
6134
6983
|
else insertRuleOrGroup(parentToInsertInto.rules[spliceIndex - 2] ?? oldNextCombinator ?? getFirstOption(combinators), ruleOrGroup);
|
|
6135
6984
|
return query;
|
|
6136
6985
|
};
|
|
@@ -6141,7 +6990,7 @@ const moveInPlace = (query, oldPathOrID, newPath, options = {}) => {
|
|
|
6141
6990
|
*
|
|
6142
6991
|
* @group Query Tools
|
|
6143
6992
|
*/
|
|
6144
|
-
const insert = (query, ruleOrGroup, path, options = {}) => (
|
|
6993
|
+
const insert = (query, ruleOrGroup, path, options = {}) => producerFor(options.freeze)(query, (q) => insertInPlace(q, ruleOrGroup, path, options));
|
|
6145
6994
|
/**
|
|
6146
6995
|
* Inserts a rule or group into a query in place.
|
|
6147
6996
|
*
|
|
@@ -6196,9 +7045,10 @@ const insertInPlace = (query, ruleOrGroup, path, options = {}) => {
|
|
|
6196
7045
|
const insertRuleOrGroup = (idx, ...args) => parentToInsertInto.rules.splice(idx, replace ? args.length : 0, ...args);
|
|
6197
7046
|
if (parentToInsertInto.rules.length === 0 || !independentCombinators) insertRuleOrGroup(newIndex, rorg);
|
|
6198
7047
|
else if (replace && independentCombinators) insertRuleOrGroup(newIndex + newIndex % 2, rorg);
|
|
6199
|
-
else if (newIndex === 0)
|
|
6200
|
-
|
|
6201
|
-
|
|
7048
|
+
else if (newIndex === 0) {
|
|
7049
|
+
if (rorg.path?.at(-1) === 0 && combinatorSucceeding) insertRuleOrGroup(newIndex, rorg, combinatorSucceeding);
|
|
7050
|
+
else insertRuleOrGroup(newIndex, rorg, parentToInsertInto.rules[1] ?? combinatorPreceding ?? getFirstOption(combinators));
|
|
7051
|
+
} else {
|
|
6202
7052
|
const normalizedNewIndex = newIndex % 2 === 0 ? newIndex - 1 : newIndex;
|
|
6203
7053
|
if (combinatorPreceding) insertRuleOrGroup(normalizedNewIndex, combinatorPreceding, rorg);
|
|
6204
7054
|
else insertRuleOrGroup(normalizedNewIndex, parentToInsertInto.rules[normalizedNewIndex - 2] ?? combinatorSucceeding ?? getFirstOption(combinators), rorg);
|
|
@@ -6214,7 +7064,7 @@ const insertInPlace = (query, ruleOrGroup, path, options = {}) => {
|
|
|
6214
7064
|
*
|
|
6215
7065
|
* @group Query Tools
|
|
6216
7066
|
*/
|
|
6217
|
-
const group = (query, sourcePathOrID, targetPathOrID, options = {}) => (
|
|
7067
|
+
const group = (query, sourcePathOrID, targetPathOrID, options = {}) => producerFor(options.freeze)(query, (q) => groupInPlace(q, sourcePathOrID, targetPathOrID, options));
|
|
6218
7068
|
/**
|
|
6219
7069
|
* Creates a new group at a target path with its `rules` array containing the current
|
|
6220
7070
|
* objects at the target path and the source path in place.
|
|
@@ -6342,7 +7192,7 @@ const groupInPlace = (query, sourcePathOrID, targetPathOrID, options = {}) => {
|
|
|
6342
7192
|
* @group Query Tools
|
|
6343
7193
|
*/
|
|
6344
7194
|
const createQueryActions = (config = {}) => {
|
|
6345
|
-
const { qbId, combinators, idGenerator, maxLevels = Infinity, queryDisabled, respectDisabled = true, disabledPaths, resetOnFieldChange, resetOnOperatorChange, getRuleDefaultOperator, getValueSources, getRuleDefaultValue, getMatchModes, onAddRule, onAddGroup, onRemove, onMoveRule, onMoveGroup, onGroupRule, onGroupGroup, onLog } = config;
|
|
7195
|
+
const { qbId, combinators, idGenerator, maxLevels = Infinity, queryDisabled, respectDisabled = true, disabledPaths, resetOnFieldChange, resetOnOperatorChange, getRuleDefaultOperator, getValueSources, getRuleDefaultValue, getMatchModes, freeze, onAddRule, onAddGroup, onRemove, onMoveRule, onMoveGroup, onGroupRule, onGroupGroup, onLog } = config;
|
|
6346
7196
|
const log = (payload) => onLog?.({
|
|
6347
7197
|
qbId,
|
|
6348
7198
|
...payload
|
|
@@ -6379,7 +7229,8 @@ const createQueryActions = (config = {}) => {
|
|
|
6379
7229
|
const newQuery = add(query, newRule, parentPath, {
|
|
6380
7230
|
combinators,
|
|
6381
7231
|
combinatorPreceding: newRule.combinatorPreceding,
|
|
6382
|
-
idGenerator
|
|
7232
|
+
idGenerator,
|
|
7233
|
+
freeze
|
|
6383
7234
|
});
|
|
6384
7235
|
log({
|
|
6385
7236
|
type: LogType.add,
|
|
@@ -6415,7 +7266,8 @@ const createQueryActions = (config = {}) => {
|
|
|
6415
7266
|
const newQuery = add(query, newGroup, parentPath, {
|
|
6416
7267
|
combinators,
|
|
6417
7268
|
combinatorPreceding: newGroup.combinatorPreceding ?? void 0,
|
|
6418
|
-
idGenerator
|
|
7269
|
+
idGenerator,
|
|
7270
|
+
freeze
|
|
6419
7271
|
});
|
|
6420
7272
|
log({
|
|
6421
7273
|
type: LogType.add,
|
|
@@ -6443,7 +7295,8 @@ const createQueryActions = (config = {}) => {
|
|
|
6443
7295
|
getRuleDefaultOperator,
|
|
6444
7296
|
getValueSources,
|
|
6445
7297
|
getRuleDefaultValue,
|
|
6446
|
-
getMatchModes
|
|
7298
|
+
getMatchModes,
|
|
7299
|
+
freeze
|
|
6447
7300
|
});
|
|
6448
7301
|
log({
|
|
6449
7302
|
type: LogType.update,
|
|
@@ -6476,7 +7329,7 @@ const createQueryActions = (config = {}) => {
|
|
|
6476
7329
|
});
|
|
6477
7330
|
return;
|
|
6478
7331
|
}
|
|
6479
|
-
const newQuery = remove(query, path);
|
|
7332
|
+
const newQuery = remove(query, path, { freeze });
|
|
6480
7333
|
log({
|
|
6481
7334
|
type: LogType.remove,
|
|
6482
7335
|
query,
|
|
@@ -6501,7 +7354,8 @@ const createQueryActions = (config = {}) => {
|
|
|
6501
7354
|
const nextQuery = move(query, oldPath, newPath, {
|
|
6502
7355
|
clone,
|
|
6503
7356
|
combinators,
|
|
6504
|
-
idGenerator
|
|
7357
|
+
idGenerator,
|
|
7358
|
+
freeze
|
|
6505
7359
|
});
|
|
6506
7360
|
const isGroup = isRuleGroup(ruleOrGroup);
|
|
6507
7361
|
const callback = isGroup ? onMoveGroup : onMoveRule;
|
|
@@ -6547,7 +7401,8 @@ const createQueryActions = (config = {}) => {
|
|
|
6547
7401
|
const nextQuery = group(query, sourcePath, targetPath, {
|
|
6548
7402
|
clone,
|
|
6549
7403
|
combinators,
|
|
6550
|
-
idGenerator
|
|
7404
|
+
idGenerator,
|
|
7405
|
+
freeze
|
|
6551
7406
|
});
|
|
6552
7407
|
const isGroup = isRuleGroup(ruleOrGroup);
|
|
6553
7408
|
const callback = isGroup ? onGroupGroup : onGroupRule;
|
|
@@ -6591,10 +7446,12 @@ const createQueryActions = (config = {}) => {
|
|
|
6591
7446
|
*/
|
|
6592
7447
|
const createRule = ({ fields, getDefaultField, getRuleDefaultOperator, getValueSources, getMatchModes, getRuleDefaultValue, idGenerator = generateID }) => {
|
|
6593
7448
|
let field = getFirstOption(fields) ?? "";
|
|
6594
|
-
if (getDefaultField)
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
7449
|
+
if (getDefaultField) {
|
|
7450
|
+
if (typeof getDefaultField === "function") {
|
|
7451
|
+
const defaultField = getDefaultField(fields);
|
|
7452
|
+
if (defaultField) field = defaultField;
|
|
7453
|
+
} else field = getDefaultField;
|
|
7454
|
+
}
|
|
6598
7455
|
const fieldData = getOption(fields, field);
|
|
6599
7456
|
const operator = getRuleDefaultOperator(field);
|
|
6600
7457
|
const valueSource = getFirstOption(getValueSources(field, operator, { fieldData })) ?? "value";
|
|
@@ -6641,92 +7498,8 @@ const createRuleGroup = ({ combinators, addRuleToNewGroups, createRule: createRu
|
|
|
6641
7498
|
};
|
|
6642
7499
|
};
|
|
6643
7500
|
//#endregion
|
|
6644
|
-
//#region src/utils/signature.ts
|
|
6645
|
-
/**
|
|
6646
|
-
* Signature returned when a change alters the _shape_ of the query—rules or groups added,
|
|
6647
|
-
* removed, moved, or reordered—rather than the properties of a single node. Structural changes
|
|
6648
|
-
* never coalesce with each other, so each one produces its own history entry.
|
|
6649
|
-
*/
|
|
6650
|
-
const structuralSignature = "~structural";
|
|
6651
|
-
/**
|
|
6652
|
-
* Signature returned when two queries differ by reference only, with no observable difference
|
|
6653
|
-
* in their properties.
|
|
6654
|
-
*/
|
|
6655
|
-
const unchangedSignature = "";
|
|
6656
|
-
/**
|
|
6657
|
-
* Returns the list of property names that differ between two nodes, ignoring `rules` (which is
|
|
6658
|
-
* compared structurally by the caller).
|
|
6659
|
-
*/
|
|
6660
|
-
const changedProps = (prev, next) => {
|
|
6661
|
-
const keys = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
6662
|
-
keys.delete("rules");
|
|
6663
|
-
const changed = [];
|
|
6664
|
-
for (const key of keys) if (!Object.is(prev[key], next[key])) changed.push(key);
|
|
6665
|
-
return changed.toSorted();
|
|
6666
|
-
};
|
|
6667
|
-
const signatureOfNode = (prev, next, parentId, index) => {
|
|
6668
|
-
if (prev === next) return "";
|
|
6669
|
-
if (typeof prev === "string" || typeof next === "string") return typeof prev === typeof next ? `${parentId}:combinator[${index}]` : structuralSignature;
|
|
6670
|
-
const prevIsGroup = isRuleGroup(prev);
|
|
6671
|
-
const nextIsGroup = isRuleGroup(next);
|
|
6672
|
-
if (prevIsGroup !== nextIsGroup) return structuralSignature;
|
|
6673
|
-
if (!prevIsGroup || !nextIsGroup) {
|
|
6674
|
-
const props = changedProps(prev, next);
|
|
6675
|
-
return props.length === 0 ? "" : `${next.id ?? ""}:${props.join(",")}`;
|
|
6676
|
-
}
|
|
6677
|
-
if (prev.rules.length !== next.rules.length) return structuralSignature;
|
|
6678
|
-
const ownProps = changedProps(prev, next);
|
|
6679
|
-
let changedIndex = -1;
|
|
6680
|
-
for (const [i, prevRule] of prev.rules.entries()) if (prevRule !== next.rules[i]) {
|
|
6681
|
-
if (changedIndex !== -1) return structuralSignature;
|
|
6682
|
-
changedIndex = i;
|
|
6683
|
-
}
|
|
6684
|
-
if (changedIndex === -1) return ownProps.length === 0 ? "" : `${next.id ?? ""}:${ownProps.join(",")}`;
|
|
6685
|
-
if (ownProps.length > 0) return structuralSignature;
|
|
6686
|
-
return signatureOfNode(prev.rules[changedIndex], next.rules[changedIndex], next.id ?? "", changedIndex);
|
|
6687
|
-
};
|
|
6688
|
-
/**
|
|
6689
|
-
* Describes _what changed_ between two versions of a query as a short string, so that
|
|
6690
|
-
* consecutive edits to the same property of the same rule (e.g. typing in a value editor) can
|
|
6691
|
-
* be recognized and coalesced into a single history entry.
|
|
6692
|
-
*
|
|
6693
|
-
* Returns {@link structuralSignature} for changes to the shape of the query, {@link unchangedSignature} when the
|
|
6694
|
-
* two queries differ by reference only, and `"<id>:<props>"` otherwise.
|
|
6695
|
-
*
|
|
6696
|
-
* The walk prunes on reference equality, so it costs O(depth) rather than O(size) for the
|
|
6697
|
-
* single-node edits that make up the overwhelming majority of changes.
|
|
6698
|
-
*
|
|
6699
|
-
* Note that this relies on the structural sharing that Immer—and therefore every query
|
|
6700
|
-
* produced by RQB's own update functions—guarantees: nodes that did not change keep their
|
|
6701
|
-
* identity. A query that has been wholly rebuilt (deep-cloned, round-tripped through JSON,
|
|
6702
|
-
* re-parsed from a string) shares no identity with its predecessor, so it is reported as
|
|
6703
|
-
* {@link structuralSignature} and will not coalesce. That is a graceful degradation—every change simply
|
|
6704
|
-
* gets its own history entry—but controlled components that clone the query on every change
|
|
6705
|
-
* will not benefit from coalescing.
|
|
6706
|
-
*/
|
|
6707
|
-
const signatureOf = (prev, next) => signatureOfNode(prev, next, "", -1);
|
|
6708
|
-
//#endregion
|
|
6709
7501
|
//#region src/utils/QueryManager.ts
|
|
6710
7502
|
/**
|
|
6711
|
-
* Abort reasons that {@link QueryManager}'s `strict` mode treats as errors. The remaining
|
|
6712
|
-
* reasons—`"same-location"` and `"no-change"`—describe valid operations that had nothing to do,
|
|
6713
|
-
* so they are reported to `onInvalidTarget` but never throw.
|
|
6714
|
-
*
|
|
6715
|
-
* @group Query Tools
|
|
6716
|
-
*/
|
|
6717
|
-
const strictAbortReasons = [
|
|
6718
|
-
"target-not-found",
|
|
6719
|
-
"parent-not-found",
|
|
6720
|
-
"parent-not-a-group",
|
|
6721
|
-
"destination-not-found",
|
|
6722
|
-
"root-not-allowed",
|
|
6723
|
-
"not-a-combinator-slot",
|
|
6724
|
-
"target-disabled",
|
|
6725
|
-
"parent-disabled",
|
|
6726
|
-
"max-levels-exceeded"
|
|
6727
|
-
];
|
|
6728
|
-
const strictAbortReasonSet = new Set(strictAbortReasons);
|
|
6729
|
-
/**
|
|
6730
7503
|
* Thrown by {@link QueryManager} methods in `strict` mode when an operation cannot be carried
|
|
6731
7504
|
* out because its target could not be used.
|
|
6732
7505
|
*
|
|
@@ -6746,6 +7519,57 @@ var QueryManagerError = class QueryManagerError extends Error {
|
|
|
6746
7519
|
}
|
|
6747
7520
|
};
|
|
6748
7521
|
/**
|
|
7522
|
+
* Key of the single own property holding every {@link QueryManager} instance's state.
|
|
7523
|
+
*
|
|
7524
|
+
* `#private` fields are unreachable from a `Proxy`: inside a method invoked through one, `this`
|
|
7525
|
+
* _is_ the proxy, and the private brand lives on the target, so every access throws
|
|
7526
|
+
* `TypeError: Cannot read private member`. Frameworks wrap objects in proxies routinely — Vue's
|
|
7527
|
+
* `reactive()`, and by extension Vue Test Utils' handling of mount props, do it implicitly — so
|
|
7528
|
+
* consumers hit that failure by accident rather than by choice.
|
|
7529
|
+
*
|
|
7530
|
+
* A `WeakMap` keyed by instance does not fix it either, for the same reason: `weakMap.get(this)`
|
|
7531
|
+
* misses the entry stored under the target. An ordinary own property is the only mechanism that
|
|
7532
|
+
* reads correctly through a proxy, because the `get` trap forwards to the target.
|
|
7533
|
+
*
|
|
7534
|
+
* The symbol is module-private and never exported. Reaching into the state bag (via
|
|
7535
|
+
* `Object.getOwnPropertySymbols`, say) is not a supported access path and its contents may change
|
|
7536
|
+
* in any release.
|
|
7537
|
+
*/
|
|
7538
|
+
const kState = Symbol("QueryManager.state");
|
|
7539
|
+
const queryChange = (0, immer.freeze)({
|
|
7540
|
+
query: true,
|
|
7541
|
+
config: false
|
|
7542
|
+
});
|
|
7543
|
+
const configChange = (0, immer.freeze)({
|
|
7544
|
+
query: false,
|
|
7545
|
+
config: true
|
|
7546
|
+
});
|
|
7547
|
+
const queryAndConfigChange = (0, immer.freeze)({
|
|
7548
|
+
query: true,
|
|
7549
|
+
config: true
|
|
7550
|
+
});
|
|
7551
|
+
/**
|
|
7552
|
+
* Builds the state bag. The option-derived members are left unset for `applyOptions` to fill in,
|
|
7553
|
+
* hence the assertion.
|
|
7554
|
+
*/
|
|
7555
|
+
const createManagerState = () => {
|
|
7556
|
+
const state = {
|
|
7557
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
7558
|
+
configVersion: 0,
|
|
7559
|
+
past: [],
|
|
7560
|
+
future: [],
|
|
7561
|
+
lastAt: 0,
|
|
7562
|
+
batchDepth: 0,
|
|
7563
|
+
historyBypassed: false,
|
|
7564
|
+
pendingConfigNotify: false
|
|
7565
|
+
};
|
|
7566
|
+
Object.defineProperty(state, "__v_skip", {
|
|
7567
|
+
value: true,
|
|
7568
|
+
enumerable: false
|
|
7569
|
+
});
|
|
7570
|
+
return state;
|
|
7571
|
+
};
|
|
7572
|
+
/**
|
|
6749
7573
|
* Stateful wrapper around the {@link add}/{@link remove}/{@link update}/{@link move}/
|
|
6750
7574
|
* {@link insert}/{@link group} query tools, plus rule/group factories, {@link defaultValidator
|
|
6751
7575
|
* validation}, and {@link formatQuery formatting}.
|
|
@@ -6753,7 +7577,8 @@ var QueryManagerError = class QueryManagerError extends Error {
|
|
|
6753
7577
|
* The query is held internally, so each method takes the same arguments as its `queryTools`
|
|
6754
7578
|
* counterpart minus the leading `query` parameter, and returns the manager itself for chaining.
|
|
6755
7579
|
* Mutations use the non-`InPlace` tools, so a query previously handed out by
|
|
6756
|
-
* {@link QueryManager.getQuery} is never modified.
|
|
7580
|
+
* {@link QueryManager.getQuery} is never modified. Under `freeze: false` that remains true, but
|
|
7581
|
+
* as a convention rather than a runtime-enforced guarantee.
|
|
6757
7582
|
*
|
|
6758
7583
|
* ```ts
|
|
6759
7584
|
* const q = new QueryManager(undefined, { fields });
|
|
@@ -6769,194 +7594,188 @@ var QueryManagerError = class QueryManagerError extends Error {
|
|
|
6769
7594
|
* @group Query Tools
|
|
6770
7595
|
*/
|
|
6771
7596
|
var QueryManager = class QueryManager {
|
|
6772
|
-
#query;
|
|
6773
|
-
#options;
|
|
6774
|
-
#fields;
|
|
6775
|
-
#fieldMap;
|
|
6776
|
-
#operators;
|
|
6777
|
-
#combinators;
|
|
6778
|
-
#idGenerator;
|
|
6779
|
-
#validator;
|
|
6780
|
-
#strict;
|
|
6781
|
-
#respectDisabled;
|
|
6782
|
-
#onInvalidTarget;
|
|
6783
|
-
#listeners = /* @__PURE__ */ new Set();
|
|
6784
|
-
#historyEnabled;
|
|
6785
|
-
#maxHistory;
|
|
6786
|
-
#coalesceMs;
|
|
6787
|
-
#now;
|
|
6788
|
-
/** Incremented by every {@link QueryManager.reconfigure} call. See `getConfigVersion`. */
|
|
6789
|
-
#configVersion = 0;
|
|
6790
|
-
#past = [];
|
|
6791
|
-
#future = [];
|
|
6792
|
-
#lastSig;
|
|
6793
|
-
#lastAt = 0;
|
|
6794
|
-
#batchDepth = 0;
|
|
6795
|
-
#batchSnapshot;
|
|
6796
|
-
/** Whether a history-stack method ran inside the batch currently in progress. */
|
|
6797
|
-
#historyBypassed = false;
|
|
6798
7597
|
/**
|
|
6799
|
-
*
|
|
6800
|
-
*
|
|
6801
|
-
*
|
|
7598
|
+
* All instance state, rather than `#private` fields. See `kState` for why.
|
|
7599
|
+
*
|
|
7600
|
+
* The property itself is symbol-keyed and installed by the constructor; this accessor exists
|
|
7601
|
+
* because `isolatedDeclarations` cannot emit a computed property name keyed by a symbol the
|
|
7602
|
+
* module does not export, and exporting it would put it in the public API surface. A
|
|
7603
|
+
* prototype accessor is proxy-safe for the same reason the own property is: `this` is the
|
|
7604
|
+
* proxy, and the `get` trap forwards to the target.
|
|
6802
7605
|
*/
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
7606
|
+
get state() {
|
|
7607
|
+
return this[kState];
|
|
7608
|
+
}
|
|
6806
7609
|
constructor(query, options = {}) {
|
|
6807
|
-
this
|
|
6808
|
-
|
|
7610
|
+
Object.defineProperty(this, kState, {
|
|
7611
|
+
value: createManagerState(),
|
|
7612
|
+
enumerable: false,
|
|
7613
|
+
writable: false,
|
|
7614
|
+
configurable: false
|
|
7615
|
+
});
|
|
7616
|
+
this.applyOptions(options);
|
|
7617
|
+
this.state.query = this.freeze(query ? prepareRuleGroup(query, { idGenerator: this.state.idGenerator }) : this.createRuleGroup());
|
|
7618
|
+
}
|
|
7619
|
+
/**
|
|
7620
|
+
* Deep-freezes `x` unless the `freeze` option is `false`. Every value the manager hands out
|
|
7621
|
+
* directly goes through here; the shallow copies returned by {@link QueryManager.getOptions}
|
|
7622
|
+
* and passed to `applyOptions` are frozen unconditionally instead.
|
|
7623
|
+
*/
|
|
7624
|
+
freeze(x) {
|
|
7625
|
+
return this.state.freezeEnabled ? (0, immer.freeze)(x, true) : x;
|
|
6809
7626
|
}
|
|
6810
7627
|
/**
|
|
6811
|
-
* Assigns
|
|
7628
|
+
* Assigns `options` and every field derived from it. Shared by the constructor and
|
|
6812
7629
|
* {@link QueryManager.reconfigure}, so the two can never drift apart. Does not touch the
|
|
6813
7630
|
* query, the history stacks, the caches, or the subscriber list.
|
|
6814
7631
|
*/
|
|
6815
|
-
|
|
6816
|
-
this
|
|
6817
|
-
this
|
|
6818
|
-
this
|
|
6819
|
-
this
|
|
6820
|
-
this
|
|
6821
|
-
this
|
|
7632
|
+
applyOptions(options) {
|
|
7633
|
+
this.state.options = options;
|
|
7634
|
+
this.state.freezeEnabled = options.freeze ?? true;
|
|
7635
|
+
this.state.idGenerator = options.idGenerator ?? generateID;
|
|
7636
|
+
this.state.validator = options.validator ?? defaultValidator;
|
|
7637
|
+
this.state.strict = options.strict ?? false;
|
|
7638
|
+
this.state.respectDisabled = options.respectDisabled ?? true;
|
|
7639
|
+
this.state.onInvalidTarget = options.onInvalidTarget;
|
|
6822
7640
|
const history = options.history ?? false;
|
|
6823
7641
|
const historyOptions = typeof history === "object" ? history : {};
|
|
6824
|
-
this
|
|
6825
|
-
this
|
|
6826
|
-
this
|
|
6827
|
-
this
|
|
7642
|
+
this.state.historyEnabled = history !== false;
|
|
7643
|
+
this.state.maxHistory = historyOptions.maxHistory ?? 50;
|
|
7644
|
+
this.state.coalesceMs = historyOptions.coalesceMs ?? 500;
|
|
7645
|
+
this.state.now = options.now ?? Date.now;
|
|
6828
7646
|
const { optionList: fields, optionsMap: fieldMap } = prepareOptionList({
|
|
6829
7647
|
optionList: options.fields,
|
|
6830
7648
|
baseOption: options.baseField,
|
|
6831
7649
|
autoSelectOption: options.autoSelectField,
|
|
6832
7650
|
placeholder: options.translations?.fields
|
|
6833
7651
|
});
|
|
6834
|
-
this
|
|
6835
|
-
this
|
|
6836
|
-
this
|
|
7652
|
+
this.state.fields = this.freeze(fields);
|
|
7653
|
+
this.state.fieldMap = this.freeze(fieldMap);
|
|
7654
|
+
this.state.operators = prepareOptionList({
|
|
6837
7655
|
optionList: options.operators ?? defaultOperators,
|
|
6838
7656
|
baseOption: options.baseOperator,
|
|
6839
7657
|
labelMap: defaultOperatorLabelMap,
|
|
6840
7658
|
autoSelectOption: options.autoSelectOperator,
|
|
6841
7659
|
placeholder: options.translations?.operators
|
|
6842
7660
|
}).optionList;
|
|
6843
|
-
this
|
|
7661
|
+
this.state.combinators = this.freeze(prepareOptionList({
|
|
6844
7662
|
optionList: options.combinators ?? defaultCombinators,
|
|
6845
7663
|
baseOption: options.baseCombinator
|
|
6846
|
-
}).optionList
|
|
7664
|
+
}).optionList);
|
|
6847
7665
|
}
|
|
6848
7666
|
/** Resolves the field configuration for a field name. */
|
|
6849
|
-
|
|
6850
|
-
return this
|
|
7667
|
+
fieldData(field) {
|
|
7668
|
+
return this.state.fieldMap[field] ?? {};
|
|
6851
7669
|
}
|
|
6852
7670
|
/** Resolves the operator list for a field, mirroring `QueryBuilder`'s precedence. */
|
|
6853
|
-
|
|
7671
|
+
operatorsFor(field) {
|
|
6854
7672
|
return resolveOperatorList({
|
|
6855
7673
|
field,
|
|
6856
|
-
fieldData: this
|
|
6857
|
-
getOperators: this
|
|
6858
|
-
operators: this
|
|
6859
|
-
baseOption: this
|
|
6860
|
-
autoSelectOption: this
|
|
6861
|
-
placeholder: this
|
|
7674
|
+
fieldData: this.fieldData(field),
|
|
7675
|
+
getOperators: this.state.options.getOperators,
|
|
7676
|
+
operators: this.state.operators,
|
|
7677
|
+
baseOption: this.state.options.baseOperator,
|
|
7678
|
+
autoSelectOption: this.state.options.autoSelectOperator,
|
|
7679
|
+
placeholder: this.state.options.translations?.operators
|
|
6862
7680
|
});
|
|
6863
7681
|
}
|
|
6864
7682
|
/** Resolves the default operator for a field, mirroring `QueryBuilder`'s precedence. */
|
|
6865
|
-
|
|
7683
|
+
defaultOperator(field) {
|
|
6866
7684
|
return resolveDefaultOperator({
|
|
6867
7685
|
field,
|
|
6868
|
-
fieldData: this
|
|
6869
|
-
getDefaultOperator: this
|
|
6870
|
-
getOperators: (f) => this
|
|
7686
|
+
fieldData: this.fieldData(field),
|
|
7687
|
+
getDefaultOperator: this.state.options.getDefaultOperator,
|
|
7688
|
+
getOperators: (f) => this.operatorsFor(f)
|
|
6871
7689
|
});
|
|
6872
7690
|
}
|
|
6873
|
-
|
|
6874
|
-
return getValueSourcesUtil(this
|
|
7691
|
+
valueSourcesFor(field, operator) {
|
|
7692
|
+
return getValueSourcesUtil(this.fieldData(field), operator, this.state.options.getValueSources);
|
|
6875
7693
|
}
|
|
6876
|
-
|
|
6877
|
-
return getMatchModesUtil(this
|
|
7694
|
+
matchModesFor(field) {
|
|
7695
|
+
return getMatchModesUtil(this.fieldData(field), this.state.options.getMatchModes);
|
|
6878
7696
|
}
|
|
6879
|
-
|
|
7697
|
+
valuesFor(field, operator) {
|
|
6880
7698
|
return resolveValueList({
|
|
6881
7699
|
field,
|
|
6882
7700
|
operator,
|
|
6883
|
-
fieldData: this
|
|
6884
|
-
getValues: this
|
|
6885
|
-
autoSelectOption: this
|
|
6886
|
-
placeholder: this
|
|
7701
|
+
fieldData: this.fieldData(field),
|
|
7702
|
+
getValues: this.state.options.getValues,
|
|
7703
|
+
autoSelectOption: this.state.options.autoSelectValue,
|
|
7704
|
+
placeholder: this.state.options.translations?.values
|
|
6887
7705
|
});
|
|
6888
7706
|
}
|
|
6889
|
-
|
|
7707
|
+
valueEditorTypeFor(field, operator) {
|
|
6890
7708
|
return resolveValueEditorType({
|
|
6891
7709
|
field,
|
|
6892
7710
|
operator,
|
|
6893
|
-
fieldData: this
|
|
6894
|
-
getValueEditorType: this
|
|
7711
|
+
fieldData: this.fieldData(field),
|
|
7712
|
+
getValueEditorType: this.state.options.getValueEditorType
|
|
6895
7713
|
});
|
|
6896
7714
|
}
|
|
6897
7715
|
/** Computes the default `value` for a rule, mirroring `QueryBuilder`'s precedence. */
|
|
6898
|
-
|
|
6899
|
-
const { getDefaultValue, getParameters, listsAsArrays } = this
|
|
7716
|
+
defaultValue(rule) {
|
|
7717
|
+
const { getDefaultValue, getParameters, listsAsArrays } = this.state.options;
|
|
6900
7718
|
return getRuleDefaultValue(rule, {
|
|
6901
|
-
fieldData: this
|
|
6902
|
-
fields: this
|
|
7719
|
+
fieldData: this.fieldData(rule.field),
|
|
7720
|
+
fields: this.state.fields,
|
|
6903
7721
|
listsAsArrays,
|
|
6904
|
-
getValueEditorType: (f, o) => this
|
|
6905
|
-
getValues: (f, o) => this
|
|
7722
|
+
getValueEditorType: (f, o) => this.valueEditorTypeFor(f, o),
|
|
7723
|
+
getValues: (f, o) => this.valuesFor(f, o),
|
|
6906
7724
|
getDefaultValue: getDefaultValue && ((r, misc) => getDefaultValue(r, misc)),
|
|
6907
|
-
getParameters: getParameters && ((f, o, misc) => this
|
|
7725
|
+
getParameters: getParameters && ((f, o, misc) => this.parametersFor(f, o, misc))
|
|
6908
7726
|
});
|
|
6909
7727
|
}
|
|
6910
7728
|
/**
|
|
6911
7729
|
* Resolves the parameter list for a field/operator pair, normalized the same way as every
|
|
6912
|
-
* other option list. Shared by {@link QueryManager
|
|
6913
|
-
*
|
|
7730
|
+
* other option list. Shared by `defaultValue` and {@link QueryManager.getRuleContext} so both
|
|
7731
|
+
* see the same shape.
|
|
6914
7732
|
*/
|
|
6915
|
-
|
|
7733
|
+
parametersFor(field, operator, misc) {
|
|
6916
7734
|
return prepareOptionList({
|
|
6917
|
-
optionList: this
|
|
6918
|
-
autoSelectOption: this
|
|
7735
|
+
optionList: this.state.options.getParameters?.(field, operator, misc) ?? [],
|
|
7736
|
+
autoSelectOption: this.state.options.autoSelectValue
|
|
6919
7737
|
}).optionList;
|
|
6920
7738
|
}
|
|
6921
7739
|
/** Defaults shared by every mutating method, overridable per call. */
|
|
6922
|
-
|
|
6923
|
-
const { maxLevels } = this
|
|
7740
|
+
guardOptions() {
|
|
7741
|
+
const { maxLevels } = this.state.options;
|
|
6924
7742
|
return {
|
|
7743
|
+
freeze: this.state.freezeEnabled,
|
|
6925
7744
|
maxLevels: (maxLevels ?? 0) > 0 ? Number(maxLevels) : Infinity,
|
|
6926
|
-
respectDisabled: this
|
|
6927
|
-
disabledPaths: this
|
|
6928
|
-
queryDisabled: this
|
|
7745
|
+
respectDisabled: this.state.respectDisabled,
|
|
7746
|
+
disabledPaths: this.state.options.disabledPaths,
|
|
7747
|
+
queryDisabled: this.state.options.queryDisabled
|
|
6929
7748
|
};
|
|
6930
7749
|
}
|
|
6931
|
-
|
|
7750
|
+
toolOptions() {
|
|
6932
7751
|
return {
|
|
6933
|
-
combinators: this
|
|
6934
|
-
idGenerator: this
|
|
6935
|
-
...this
|
|
7752
|
+
combinators: this.state.combinators,
|
|
7753
|
+
idGenerator: this.state.idGenerator,
|
|
7754
|
+
...this.guardOptions()
|
|
6936
7755
|
};
|
|
6937
7756
|
}
|
|
6938
7757
|
/**
|
|
6939
7758
|
* Builds the `onAbort` handler passed to the query tools, applying the per-call overrides on
|
|
6940
7759
|
* top of the manager's own options.
|
|
6941
7760
|
*/
|
|
6942
|
-
|
|
6943
|
-
const strictMain = strict ?? this
|
|
6944
|
-
const handler = onInvalidTarget ?? this
|
|
7761
|
+
onAbort({ strict, onInvalidTarget }) {
|
|
7762
|
+
const strictMain = strict ?? this.state.strict;
|
|
7763
|
+
const handler = onInvalidTarget ?? this.state.onInvalidTarget;
|
|
6945
7764
|
return (info) => {
|
|
6946
7765
|
handler?.(info);
|
|
6947
7766
|
if (strictMain && strictAbortReasonSet.has(info.reason)) throw new QueryManagerError(info);
|
|
6948
7767
|
};
|
|
6949
7768
|
}
|
|
6950
7769
|
/** Defaults for {@link update}, so resets mirror `QueryBuilder`'s behavior. */
|
|
6951
|
-
|
|
7770
|
+
updateOptions() {
|
|
6952
7771
|
return {
|
|
6953
|
-
getRuleDefaultOperator: (f) => this
|
|
6954
|
-
getRuleDefaultValue: (r) => this
|
|
6955
|
-
getValueSources: (f, o) => this
|
|
6956
|
-
getMatchModes: (f) => this
|
|
6957
|
-
resetOnFieldChange: this
|
|
6958
|
-
resetOnOperatorChange: this
|
|
6959
|
-
...this
|
|
7772
|
+
getRuleDefaultOperator: (f) => this.defaultOperator(f),
|
|
7773
|
+
getRuleDefaultValue: (r) => this.defaultValue(r),
|
|
7774
|
+
getValueSources: (f, o) => this.valueSourcesFor(f, o),
|
|
7775
|
+
getMatchModes: (f) => this.matchModesFor(f),
|
|
7776
|
+
resetOnFieldChange: this.state.options.resetOnFieldChange,
|
|
7777
|
+
resetOnOperatorChange: this.state.options.resetOnOperatorChange,
|
|
7778
|
+
...this.guardOptions()
|
|
6960
7779
|
};
|
|
6961
7780
|
}
|
|
6962
7781
|
/**
|
|
@@ -6964,52 +7783,52 @@ var QueryManager = class QueryManager {
|
|
|
6964
7783
|
* mutation funnels through here. A tool that could not resolve its target returns the same
|
|
6965
7784
|
* query object, which is treated as a no-op.
|
|
6966
7785
|
*/
|
|
6967
|
-
|
|
6968
|
-
const prev = this
|
|
7786
|
+
commit(next) {
|
|
7787
|
+
const prev = this.state.query;
|
|
6969
7788
|
if (prev === next) return;
|
|
6970
|
-
this
|
|
6971
|
-
if (this
|
|
6972
|
-
this
|
|
6973
|
-
this
|
|
7789
|
+
this.state.query = next;
|
|
7790
|
+
if (this.state.batchDepth > 0) return;
|
|
7791
|
+
this.record(prev, next);
|
|
7792
|
+
this.notify(queryChange);
|
|
6974
7793
|
}
|
|
6975
7794
|
/**
|
|
6976
7795
|
* Records a change, either as a new history entry or by absorbing it into the current one.
|
|
6977
7796
|
* Mirrors the recording semantics of the `react-querybuilder/history` entry point.
|
|
6978
7797
|
*/
|
|
6979
|
-
|
|
6980
|
-
if (!this
|
|
7798
|
+
record(prev, next) {
|
|
7799
|
+
if (!this.state.historyEnabled) return;
|
|
6981
7800
|
const sig = signatureOf(prev, next);
|
|
6982
7801
|
if (sig === "") return;
|
|
6983
|
-
const now = this
|
|
6984
|
-
if (!(
|
|
6985
|
-
this
|
|
6986
|
-
if (this
|
|
6987
|
-
this
|
|
7802
|
+
const now = this.state.now();
|
|
7803
|
+
if (!shouldCoalesce(this.state.lastSig, sig, this.state.lastAt, now, this.state.coalesceMs)) {
|
|
7804
|
+
this.state.past.push(prev);
|
|
7805
|
+
if (this.state.past.length > this.state.maxHistory) this.state.past.shift();
|
|
7806
|
+
this.state.future = [];
|
|
6988
7807
|
}
|
|
6989
|
-
this
|
|
6990
|
-
this
|
|
7808
|
+
this.state.lastSig = sig;
|
|
7809
|
+
this.state.lastAt = now;
|
|
6991
7810
|
}
|
|
6992
|
-
|
|
6993
|
-
for (const listener of this
|
|
7811
|
+
notify(change) {
|
|
7812
|
+
for (const listener of this.state.listeners) listener(change);
|
|
6994
7813
|
}
|
|
6995
7814
|
/**
|
|
6996
7815
|
* Records that a history-stack method ran inside the current batch. Those methods manage
|
|
6997
|
-
*
|
|
6998
|
-
* doing so would push a duplicate onto
|
|
7816
|
+
* `past`/`future` themselves, so the batch must not also record an entry on completion —
|
|
7817
|
+
* doing so would push a duplicate onto `past` and clear the redo stack that `undo` just
|
|
6999
7818
|
* populated.
|
|
7000
7819
|
*/
|
|
7001
|
-
|
|
7002
|
-
if (this
|
|
7820
|
+
markHistoryBypassed() {
|
|
7821
|
+
if (this.state.batchDepth > 0) this.state.historyBypassed = true;
|
|
7003
7822
|
}
|
|
7004
7823
|
/**
|
|
7005
7824
|
* Discards every cached derivation when the query has been replaced since they were computed.
|
|
7006
7825
|
* Called at the top of each cached reader.
|
|
7007
7826
|
*/
|
|
7008
|
-
|
|
7009
|
-
if (this
|
|
7010
|
-
this
|
|
7011
|
-
this
|
|
7012
|
-
this
|
|
7827
|
+
ensureCache() {
|
|
7828
|
+
if (this.state.cacheFor === this.state.query) return;
|
|
7829
|
+
this.state.cacheFor = this.state.query;
|
|
7830
|
+
this.state.idPathIndex = void 0;
|
|
7831
|
+
this.state.validation = void 0;
|
|
7013
7832
|
}
|
|
7014
7833
|
/**
|
|
7015
7834
|
* The single traversal implementation. Combinator strings in independent-combinator groups
|
|
@@ -7017,7 +7836,7 @@ var QueryManager = class QueryManager {
|
|
|
7017
7836
|
*
|
|
7018
7837
|
* @yields The subtree rooted at `node`, depth-first in pre-order, starting with `node` itself.
|
|
7019
7838
|
*/
|
|
7020
|
-
|
|
7839
|
+
*walkFrom(node, path, parent) {
|
|
7021
7840
|
yield {
|
|
7022
7841
|
node,
|
|
7023
7842
|
path,
|
|
@@ -7027,34 +7846,35 @@ var QueryManager = class QueryManager {
|
|
|
7027
7846
|
const startGroup = node;
|
|
7028
7847
|
for (const [index, child] of startGroup.rules.entries()) {
|
|
7029
7848
|
if (typeof child === "string") continue;
|
|
7030
|
-
yield* this
|
|
7849
|
+
yield* this.walkFrom(child, [...path, index], startGroup);
|
|
7031
7850
|
}
|
|
7032
7851
|
}
|
|
7033
7852
|
/** Builds (once per query) the `id` to {@link Path} index backing `findID`/`getPathOfID`. */
|
|
7034
|
-
|
|
7035
|
-
this
|
|
7036
|
-
if (!this
|
|
7853
|
+
index() {
|
|
7854
|
+
this.ensureCache();
|
|
7855
|
+
if (!this.state.idPathIndex) {
|
|
7037
7856
|
const index = /* @__PURE__ */ new Map();
|
|
7038
|
-
for (const { node, path } of this
|
|
7039
|
-
this
|
|
7857
|
+
for (const { node, path } of this.walkFrom(this.state.query, [], null)) if (node.id !== void 0 && !index.has(node.id)) index.set(node.id, path);
|
|
7858
|
+
this.state.idPathIndex = index;
|
|
7040
7859
|
}
|
|
7041
|
-
return this
|
|
7860
|
+
return this.state.idPathIndex;
|
|
7042
7861
|
}
|
|
7043
7862
|
/** Resolves a path or `id` to a path, or `null` when the `id` isn't present. */
|
|
7044
|
-
|
|
7045
|
-
return typeof pathOrID === "string" ? this
|
|
7863
|
+
toPath(pathOrID) {
|
|
7864
|
+
return typeof pathOrID === "string" ? this.index().get(pathOrID) ?? null : pathOrID;
|
|
7046
7865
|
}
|
|
7047
7866
|
/**
|
|
7048
|
-
* The current query. The returned object is
|
|
7049
|
-
*
|
|
7867
|
+
* The current query. The returned object is structurally shared, so it is safe to retain and
|
|
7868
|
+
* compare by reference to detect changes. It is also frozen unless the `freeze` option is
|
|
7869
|
+
* `false`.
|
|
7050
7870
|
*
|
|
7051
7871
|
* Like {@link QueryManager.subscribe}, this method is bound to the instance, so it can be
|
|
7052
7872
|
* passed as a bare reference (e.g. as the `getSnapshot` argument to `useSyncExternalStore`).
|
|
7053
7873
|
*/
|
|
7054
|
-
getQuery = () => this
|
|
7874
|
+
getQuery = () => this.state.query;
|
|
7055
7875
|
/** Replaces the current query, ensuring every rule and group has an `id`. */
|
|
7056
7876
|
setQuery(query) {
|
|
7057
|
-
this
|
|
7877
|
+
this.commit(this.freeze(prepareRuleGroup(query, { idGenerator: this.state.idGenerator })));
|
|
7058
7878
|
return this;
|
|
7059
7879
|
}
|
|
7060
7880
|
/**
|
|
@@ -7063,13 +7883,13 @@ var QueryManager = class QueryManager {
|
|
|
7063
7883
|
*/
|
|
7064
7884
|
createRule() {
|
|
7065
7885
|
return createRule({
|
|
7066
|
-
fields: this
|
|
7067
|
-
getDefaultField: this
|
|
7068
|
-
getRuleDefaultOperator: (f) => this
|
|
7069
|
-
getValueSources: (f, o) => this
|
|
7070
|
-
getMatchModes: (f) => this
|
|
7071
|
-
getRuleDefaultValue: (r) => this
|
|
7072
|
-
idGenerator: this
|
|
7886
|
+
fields: this.state.fields,
|
|
7887
|
+
getDefaultField: this.state.options.getDefaultField,
|
|
7888
|
+
getRuleDefaultOperator: (f) => this.defaultOperator(f),
|
|
7889
|
+
getValueSources: (f, o) => this.valueSourcesFor(f, o),
|
|
7890
|
+
getMatchModes: (f) => this.matchModesFor(f),
|
|
7891
|
+
getRuleDefaultValue: (r) => this.defaultValue(r),
|
|
7892
|
+
idGenerator: this.state.idGenerator
|
|
7073
7893
|
});
|
|
7074
7894
|
}
|
|
7075
7895
|
/**
|
|
@@ -7078,10 +7898,10 @@ var QueryManager = class QueryManager {
|
|
|
7078
7898
|
*/
|
|
7079
7899
|
createRuleGroup(independentCombinators) {
|
|
7080
7900
|
return createRuleGroup({
|
|
7081
|
-
combinators: this
|
|
7082
|
-
addRuleToNewGroups: this
|
|
7901
|
+
combinators: this.state.combinators,
|
|
7902
|
+
addRuleToNewGroups: this.state.options.addRuleToNewGroups,
|
|
7083
7903
|
createRule: () => this.createRule(),
|
|
7084
|
-
idGenerator: this
|
|
7904
|
+
idGenerator: this.state.idGenerator
|
|
7085
7905
|
}, independentCombinators);
|
|
7086
7906
|
}
|
|
7087
7907
|
/**
|
|
@@ -7090,10 +7910,10 @@ var QueryManager = class QueryManager {
|
|
|
7090
7910
|
*/
|
|
7091
7911
|
add(ruleOrGroup, parentPathOrID = [], options = {}) {
|
|
7092
7912
|
const { strict, onInvalidTarget, ...toolOptions } = options;
|
|
7093
|
-
this
|
|
7094
|
-
...this
|
|
7913
|
+
this.commit(add(this.state.query, ruleOrGroup, parentPathOrID, {
|
|
7914
|
+
...this.toolOptions(),
|
|
7095
7915
|
...toolOptions,
|
|
7096
|
-
onAbort: this
|
|
7916
|
+
onAbort: this.onAbort({
|
|
7097
7917
|
strict,
|
|
7098
7918
|
onInvalidTarget
|
|
7099
7919
|
})
|
|
@@ -7103,10 +7923,10 @@ var QueryManager = class QueryManager {
|
|
|
7103
7923
|
/** Removes the rule or group at the given path or `id`. The root group cannot be removed. */
|
|
7104
7924
|
remove(pathOrID, options = {}) {
|
|
7105
7925
|
const { strict, onInvalidTarget, ...toolOptions } = options;
|
|
7106
|
-
this
|
|
7107
|
-
...this
|
|
7926
|
+
this.commit(remove(this.state.query, pathOrID, {
|
|
7927
|
+
...this.guardOptions(),
|
|
7108
7928
|
...toolOptions,
|
|
7109
|
-
onAbort: this
|
|
7929
|
+
onAbort: this.onAbort({
|
|
7110
7930
|
strict,
|
|
7111
7931
|
onInvalidTarget
|
|
7112
7932
|
})
|
|
@@ -7123,23 +7943,23 @@ var QueryManager = class QueryManager {
|
|
|
7123
7943
|
];
|
|
7124
7944
|
const { strict, onInvalidTarget, ...toolOptions } = args[optionsIndex] ?? {};
|
|
7125
7945
|
args[optionsIndex] = {
|
|
7126
|
-
...this
|
|
7946
|
+
...this.updateOptions(),
|
|
7127
7947
|
...toolOptions,
|
|
7128
|
-
onAbort: this
|
|
7948
|
+
onAbort: this.onAbort({
|
|
7129
7949
|
strict,
|
|
7130
7950
|
onInvalidTarget
|
|
7131
7951
|
})
|
|
7132
7952
|
};
|
|
7133
|
-
this
|
|
7953
|
+
this.commit(update(this.state.query, ...args.slice(0, optionsIndex + 1)));
|
|
7134
7954
|
return this;
|
|
7135
7955
|
}
|
|
7136
7956
|
/** Moves the rule or group at `oldPathOrID` to `newPath`, or shifts it `'up'`/`'down'`. */
|
|
7137
7957
|
move(oldPathOrID, newPath, options = {}) {
|
|
7138
7958
|
const { strict, onInvalidTarget, ...toolOptions } = options;
|
|
7139
|
-
this
|
|
7140
|
-
...this
|
|
7959
|
+
this.commit(move(this.state.query, oldPathOrID, newPath, {
|
|
7960
|
+
...this.toolOptions(),
|
|
7141
7961
|
...toolOptions,
|
|
7142
|
-
onAbort: this
|
|
7962
|
+
onAbort: this.onAbort({
|
|
7143
7963
|
strict,
|
|
7144
7964
|
onInvalidTarget
|
|
7145
7965
|
})
|
|
@@ -7152,10 +7972,10 @@ var QueryManager = class QueryManager {
|
|
|
7152
7972
|
*/
|
|
7153
7973
|
insert(ruleOrGroup, path, options = {}) {
|
|
7154
7974
|
const { strict, onInvalidTarget, ...toolOptions } = options;
|
|
7155
|
-
this
|
|
7156
|
-
...this
|
|
7975
|
+
this.commit(insert(this.state.query, ruleOrGroup, path, {
|
|
7976
|
+
...this.toolOptions(),
|
|
7157
7977
|
...toolOptions,
|
|
7158
|
-
onAbort: this
|
|
7978
|
+
onAbort: this.onAbort({
|
|
7159
7979
|
strict,
|
|
7160
7980
|
onInvalidTarget
|
|
7161
7981
|
})
|
|
@@ -7168,10 +7988,10 @@ var QueryManager = class QueryManager {
|
|
|
7168
7988
|
*/
|
|
7169
7989
|
group(sourcePathOrID, targetPathOrID, options = {}) {
|
|
7170
7990
|
const { strict, onInvalidTarget, ...toolOptions } = options;
|
|
7171
|
-
this
|
|
7172
|
-
...this
|
|
7991
|
+
this.commit(group(this.state.query, sourcePathOrID, targetPathOrID, {
|
|
7992
|
+
...this.toolOptions(),
|
|
7173
7993
|
...toolOptions,
|
|
7174
|
-
onAbort: this
|
|
7994
|
+
onAbort: this.onAbort({
|
|
7175
7995
|
strict,
|
|
7176
7996
|
onInvalidTarget
|
|
7177
7997
|
})
|
|
@@ -7184,7 +8004,7 @@ var QueryManager = class QueryManager {
|
|
|
7184
8004
|
* defaults filled in for options that were never provided.
|
|
7185
8005
|
*/
|
|
7186
8006
|
getOptions() {
|
|
7187
|
-
return (0, immer.freeze)({ ...this
|
|
8007
|
+
return (0, immer.freeze)({ ...this.state.options });
|
|
7188
8008
|
}
|
|
7189
8009
|
/**
|
|
7190
8010
|
* Updates the manager's configuration in place, keeping the current query, the undo/redo
|
|
@@ -7207,24 +8027,37 @@ var QueryManager = class QueryManager {
|
|
|
7207
8027
|
* re-normalize.
|
|
7208
8028
|
*
|
|
7209
8029
|
* History options are honored immediately: lowering `maxHistory` trims the undo stack, and
|
|
7210
|
-
* turning history off clears both stacks.
|
|
7211
|
-
*
|
|
7212
|
-
*
|
|
8030
|
+
* turning history off clears both stacks.
|
|
8031
|
+
*
|
|
8032
|
+
* A call that resolves to the configuration already in effect is a **no-op**: nothing is
|
|
8033
|
+
* re-derived, {@link QueryManager.getConfigVersion} does not change, and subscribers are not
|
|
8034
|
+
* notified. Equality is structural for data and by identity for functions
|
|
8035
|
+
* ({@link optionsEqual}), so a caller that rebuilds its options object on every render — which
|
|
8036
|
+
* every framework adapter does — does not force a reconfigure as long as the data is the same.
|
|
8037
|
+
* Rebuilding a callback per render _does_ count as a change; memoize it to avoid that.
|
|
8038
|
+
*
|
|
8039
|
+
* Otherwise subscribers are notified once and `getConfigVersion` is incremented. Inside a
|
|
8040
|
+
* {@link QueryManager.batch batch} the options are still applied immediately — configuration
|
|
8041
|
+
* is not part of a batch's rollback — but the notification is deferred and merged into the
|
|
8042
|
+
* batch's single notification.
|
|
7213
8043
|
*/
|
|
7214
8044
|
reconfigure(options, config) {
|
|
7215
|
-
|
|
7216
|
-
...this
|
|
8045
|
+
const merged = config?.replace ? { ...options } : {
|
|
8046
|
+
...this.state.options,
|
|
7217
8047
|
...options
|
|
7218
|
-
}
|
|
7219
|
-
this
|
|
7220
|
-
this
|
|
7221
|
-
|
|
7222
|
-
this
|
|
8048
|
+
};
|
|
8049
|
+
if (optionsEqual(this.state.options, merged)) return this;
|
|
8050
|
+
this.applyOptions((0, immer.freeze)(merged));
|
|
8051
|
+
this.state.validation = void 0;
|
|
8052
|
+
this.reconcileHistoryConfig();
|
|
8053
|
+
++this.state.configVersion;
|
|
8054
|
+
if (this.state.batchDepth > 0) this.state.pendingConfigNotify = true;
|
|
8055
|
+
else this.notify(configChange);
|
|
7223
8056
|
return this;
|
|
7224
8057
|
}
|
|
7225
8058
|
/**
|
|
7226
8059
|
* Brings the history stacks in line with the current history configuration. Unlike
|
|
7227
|
-
* {@link QueryManager.clearHistory}, this does _not_ set
|
|
8060
|
+
* {@link QueryManager.clearHistory}, this does _not_ set `historyBypassed`: it reflects a
|
|
7228
8061
|
* configuration change rather than a deliberate history repositioning, so a later mutation in
|
|
7229
8062
|
* the same batch must still be recorded normally.
|
|
7230
8063
|
*
|
|
@@ -7232,13 +8065,13 @@ var QueryManager = class QueryManager {
|
|
|
7232
8065
|
* {@link QueryManager.batch batch} restores its snapshot, since that snapshot predates the
|
|
7233
8066
|
* configuration change (configuration is not part of a batch's rollback).
|
|
7234
8067
|
*/
|
|
7235
|
-
|
|
7236
|
-
if (this
|
|
7237
|
-
if (this
|
|
8068
|
+
reconcileHistoryConfig() {
|
|
8069
|
+
if (this.state.historyEnabled) {
|
|
8070
|
+
if (this.state.past.length > this.state.maxHistory) this.state.past.splice(0, this.state.past.length - this.state.maxHistory);
|
|
7238
8071
|
} else {
|
|
7239
|
-
this
|
|
7240
|
-
this
|
|
7241
|
-
this
|
|
8072
|
+
this.state.past = [];
|
|
8073
|
+
this.state.future = [];
|
|
8074
|
+
this.state.lastSig = void 0;
|
|
7242
8075
|
}
|
|
7243
8076
|
}
|
|
7244
8077
|
/**
|
|
@@ -7250,7 +8083,7 @@ var QueryManager = class QueryManager {
|
|
|
7250
8083
|
* {@link QueryManager.subscribe}. The `useQueryManager` hook from `react-querybuilder`
|
|
7251
8084
|
* already does this.
|
|
7252
8085
|
*/
|
|
7253
|
-
getConfigVersion = () => this
|
|
8086
|
+
getConfigVersion = () => this.state.configVersion;
|
|
7254
8087
|
/**
|
|
7255
8088
|
* Creates an independent manager with the same configuration and the current query.
|
|
7256
8089
|
*
|
|
@@ -7262,8 +8095,8 @@ var QueryManager = class QueryManager {
|
|
|
7262
8095
|
* is useful when both queries will be used together (e.g. inserted into the same tree).
|
|
7263
8096
|
*/
|
|
7264
8097
|
clone(options) {
|
|
7265
|
-
const query = options?.regenerateIDs ? regenerateIDs(this
|
|
7266
|
-
return new QueryManager(query, this
|
|
8098
|
+
const query = options?.regenerateIDs ? regenerateIDs(this.state.query, { idGenerator: this.state.idGenerator }) : this.state.query;
|
|
8099
|
+
return new QueryManager(query, this.state.options);
|
|
7267
8100
|
}
|
|
7268
8101
|
/**
|
|
7269
8102
|
* Registers a listener called after every change to the query, and returns a function that
|
|
@@ -7279,11 +8112,15 @@ var QueryManager = class QueryManager {
|
|
|
7279
8112
|
* ```
|
|
7280
8113
|
*
|
|
7281
8114
|
* In React, prefer the `useQueryManager` hook from `react-querybuilder`, which wraps this.
|
|
8115
|
+
*
|
|
8116
|
+
* The listener receives a {@link SubscriptionChange} describing what changed. It is optional:
|
|
8117
|
+
* a zero-argument listener — including `useSyncExternalStore`'s `onStoreChange` — is still a
|
|
8118
|
+
* valid listener and behaves as it always has.
|
|
7282
8119
|
*/
|
|
7283
8120
|
subscribe = (listener) => {
|
|
7284
|
-
this
|
|
8121
|
+
this.state.listeners.add(listener);
|
|
7285
8122
|
return () => {
|
|
7286
|
-
this
|
|
8123
|
+
this.state.listeners.delete(listener);
|
|
7287
8124
|
};
|
|
7288
8125
|
};
|
|
7289
8126
|
/**
|
|
@@ -7301,75 +8138,78 @@ var QueryManager = class QueryManager {
|
|
|
7301
8138
|
* its own, leaving the stacks exactly as those methods left them.
|
|
7302
8139
|
*/
|
|
7303
8140
|
batch(fn) {
|
|
7304
|
-
this
|
|
7305
|
-
if (this
|
|
7306
|
-
query: this
|
|
7307
|
-
past: [...this
|
|
7308
|
-
future: [...this
|
|
7309
|
-
lastSig: this
|
|
7310
|
-
lastAt: this
|
|
8141
|
+
this.state.batchDepth++;
|
|
8142
|
+
if (this.state.batchDepth === 1) this.state.batchSnapshot = {
|
|
8143
|
+
query: this.state.query,
|
|
8144
|
+
past: [...this.state.past],
|
|
8145
|
+
future: [...this.state.future],
|
|
8146
|
+
lastSig: this.state.lastSig,
|
|
8147
|
+
lastAt: this.state.lastAt
|
|
7311
8148
|
};
|
|
7312
8149
|
try {
|
|
7313
8150
|
fn();
|
|
7314
8151
|
} catch (error) {
|
|
7315
|
-
if (this
|
|
7316
|
-
const snapshot = this
|
|
7317
|
-
this
|
|
7318
|
-
this
|
|
7319
|
-
this
|
|
7320
|
-
this
|
|
7321
|
-
this
|
|
7322
|
-
this
|
|
8152
|
+
if (this.state.batchDepth === 1) {
|
|
8153
|
+
const snapshot = this.state.batchSnapshot;
|
|
8154
|
+
this.state.query = snapshot.query;
|
|
8155
|
+
this.state.past = snapshot.past;
|
|
8156
|
+
this.state.future = snapshot.future;
|
|
8157
|
+
this.state.lastSig = snapshot.lastSig;
|
|
8158
|
+
this.state.lastAt = snapshot.lastAt;
|
|
8159
|
+
this.reconcileHistoryConfig();
|
|
7323
8160
|
}
|
|
7324
8161
|
throw error;
|
|
7325
8162
|
} finally {
|
|
7326
|
-
this
|
|
7327
|
-
if (this
|
|
7328
|
-
const { query: base } = this
|
|
7329
|
-
this
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
8163
|
+
this.state.batchDepth--;
|
|
8164
|
+
if (this.state.batchDepth === 0) {
|
|
8165
|
+
const { query: base } = this.state.batchSnapshot;
|
|
8166
|
+
this.state.batchSnapshot = void 0;
|
|
8167
|
+
const queryChanged = base !== this.state.query;
|
|
8168
|
+
const configChanged = this.state.pendingConfigNotify;
|
|
8169
|
+
this.state.pendingConfigNotify = false;
|
|
8170
|
+
if (queryChanged) {
|
|
8171
|
+
if (!this.state.historyBypassed) this.record(base, this.state.query);
|
|
7333
8172
|
}
|
|
7334
|
-
this
|
|
8173
|
+
if (queryChanged || configChanged) this.notify(queryChanged ? configChanged ? queryAndConfigChange : queryChange : configChange);
|
|
8174
|
+
this.state.historyBypassed = false;
|
|
7335
8175
|
}
|
|
7336
8176
|
}
|
|
7337
8177
|
return this;
|
|
7338
8178
|
}
|
|
7339
8179
|
/** Whether there is a previous query to restore. Always `false` unless `history` is enabled. */
|
|
7340
8180
|
canUndo() {
|
|
7341
|
-
return this
|
|
8181
|
+
return this.state.past.length > 0;
|
|
7342
8182
|
}
|
|
7343
8183
|
/** Whether there is an undone query to restore. Always `false` unless `history` is enabled. */
|
|
7344
8184
|
canRedo() {
|
|
7345
|
-
return this
|
|
8185
|
+
return this.state.future.length > 0;
|
|
7346
8186
|
}
|
|
7347
8187
|
/** Restores the previous query. No-op when {@link QueryManager.canUndo} is `false`. */
|
|
7348
8188
|
undo() {
|
|
7349
|
-
if (this
|
|
7350
|
-
this
|
|
7351
|
-
this
|
|
7352
|
-
this
|
|
7353
|
-
this
|
|
7354
|
-
if (this
|
|
8189
|
+
if (this.state.past.length === 0) return this;
|
|
8190
|
+
this.state.future.unshift(this.state.query);
|
|
8191
|
+
this.state.query = this.state.past.pop();
|
|
8192
|
+
this.state.lastSig = void 0;
|
|
8193
|
+
this.markHistoryBypassed();
|
|
8194
|
+
if (this.state.batchDepth === 0) this.notify(queryChange);
|
|
7355
8195
|
return this;
|
|
7356
8196
|
}
|
|
7357
8197
|
/** Restores the most recently undone query. No-op when {@link QueryManager.canRedo} is `false`. */
|
|
7358
8198
|
redo() {
|
|
7359
|
-
if (this
|
|
7360
|
-
this
|
|
7361
|
-
this
|
|
7362
|
-
this
|
|
7363
|
-
this
|
|
7364
|
-
if (this
|
|
8199
|
+
if (this.state.future.length === 0) return this;
|
|
8200
|
+
this.state.past.push(this.state.query);
|
|
8201
|
+
this.state.query = this.state.future.shift();
|
|
8202
|
+
this.state.lastSig = void 0;
|
|
8203
|
+
this.markHistoryBypassed();
|
|
8204
|
+
if (this.state.batchDepth === 0) this.notify(queryChange);
|
|
7365
8205
|
return this;
|
|
7366
8206
|
}
|
|
7367
8207
|
/** Discards all undo/redo history without changing the current query. */
|
|
7368
8208
|
clearHistory() {
|
|
7369
|
-
this
|
|
7370
|
-
this
|
|
7371
|
-
this
|
|
7372
|
-
this
|
|
8209
|
+
this.markHistoryBypassed();
|
|
8210
|
+
this.state.past = [];
|
|
8211
|
+
this.state.future = [];
|
|
8212
|
+
this.state.lastSig = void 0;
|
|
7373
8213
|
return this;
|
|
7374
8214
|
}
|
|
7375
8215
|
/**
|
|
@@ -7378,8 +8218,8 @@ var QueryManager = class QueryManager {
|
|
|
7378
8218
|
*/
|
|
7379
8219
|
getHistory() {
|
|
7380
8220
|
return {
|
|
7381
|
-
past: [...this
|
|
7382
|
-
future: [...this
|
|
8221
|
+
past: [...this.state.past],
|
|
8222
|
+
future: [...this.state.future]
|
|
7383
8223
|
};
|
|
7384
8224
|
}
|
|
7385
8225
|
/**
|
|
@@ -7389,12 +8229,12 @@ var QueryManager = class QueryManager {
|
|
|
7389
8229
|
* one that depends on anything other than the query) may run fewer times than expected.
|
|
7390
8230
|
*/
|
|
7391
8231
|
validate() {
|
|
7392
|
-
this
|
|
7393
|
-
this
|
|
7394
|
-
return this
|
|
8232
|
+
this.ensureCache();
|
|
8233
|
+
this.state.validation ??= this.state.validator(this.state.query);
|
|
8234
|
+
return this.state.validation;
|
|
7395
8235
|
}
|
|
7396
8236
|
format(options) {
|
|
7397
|
-
return formatQuery(this
|
|
8237
|
+
return formatQuery(this.state.query, options);
|
|
7398
8238
|
}
|
|
7399
8239
|
/**
|
|
7400
8240
|
* Yields every rule and group in the query, depth-first in pre-order, starting with the root
|
|
@@ -7414,18 +8254,18 @@ var QueryManager = class QueryManager {
|
|
|
7414
8254
|
*/
|
|
7415
8255
|
*walk(options = {}) {
|
|
7416
8256
|
const { from, rulesOnly, groupsOnly } = options;
|
|
7417
|
-
let start = this
|
|
8257
|
+
let start = this.state.query;
|
|
7418
8258
|
let startPath = [];
|
|
7419
8259
|
let startParent = null;
|
|
7420
8260
|
if (from !== void 0) {
|
|
7421
|
-
const path = this
|
|
7422
|
-
const node = path && findPath(path, this
|
|
8261
|
+
const path = this.toPath(from);
|
|
8262
|
+
const node = path && findPath(path, this.state.query);
|
|
7423
8263
|
if (!path || !node) return;
|
|
7424
8264
|
start = node;
|
|
7425
8265
|
startPath = path;
|
|
7426
|
-
startParent = path.length === 0 ? null : findPath(getParentPath(path), this
|
|
8266
|
+
startParent = path.length === 0 ? null : findPath(getParentPath(path), this.state.query);
|
|
7427
8267
|
}
|
|
7428
|
-
for (const entry of this
|
|
8268
|
+
for (const entry of this.walkFrom(start, startPath, startParent)) {
|
|
7429
8269
|
if (rulesOnly && isRuleGroup(entry.node)) continue;
|
|
7430
8270
|
if (groupsOnly && !isRuleGroup(entry.node)) continue;
|
|
7431
8271
|
yield entry;
|
|
@@ -7470,34 +8310,34 @@ var QueryManager = class QueryManager {
|
|
|
7470
8310
|
* index, unresolvable paths are always normalized to `null` here.
|
|
7471
8311
|
*/
|
|
7472
8312
|
findPath(path) {
|
|
7473
|
-
return findPath(path, this
|
|
8313
|
+
return findPath(path, this.state.query) ?? null;
|
|
7474
8314
|
}
|
|
7475
8315
|
/**
|
|
7476
8316
|
* Returns the rule or group with the given `id`, or `null` if there is none. Backed by an
|
|
7477
8317
|
* index built once per query, so repeated lookups are constant time.
|
|
7478
8318
|
*/
|
|
7479
8319
|
findID(id) {
|
|
7480
|
-
const path = this
|
|
7481
|
-
return path === void 0 ? null : findPath(path, this
|
|
8320
|
+
const path = this.index().get(id);
|
|
8321
|
+
return path === void 0 ? null : findPath(path, this.state.query);
|
|
7482
8322
|
}
|
|
7483
8323
|
/**
|
|
7484
8324
|
* Returns the {@link Path} of the rule or group with the given `id`, or `null` if there is
|
|
7485
8325
|
* none. Backed by an index built once per query, so repeated lookups are constant time.
|
|
7486
8326
|
*/
|
|
7487
8327
|
getPathOfID(id) {
|
|
7488
|
-
return this
|
|
8328
|
+
return this.index().get(id) ?? null;
|
|
7489
8329
|
}
|
|
7490
8330
|
/**
|
|
7491
8331
|
* Determines whether the rule or group at the given path is disabled, either itself or by an
|
|
7492
8332
|
* ancestor group.
|
|
7493
8333
|
*/
|
|
7494
8334
|
pathIsDisabled(path) {
|
|
7495
|
-
return pathIsDisabled(path, this
|
|
8335
|
+
return pathIsDisabled(path, this.state.query);
|
|
7496
8336
|
}
|
|
7497
8337
|
/** Returns the rule or group at the given path or `id`, or `null` if it can't be resolved. */
|
|
7498
8338
|
getNode(pathOrID) {
|
|
7499
|
-
const path = this
|
|
7500
|
-
return path === null ? null : findPath(path, this
|
|
8339
|
+
const path = this.toPath(pathOrID);
|
|
8340
|
+
return path === null ? null : findPath(path, this.state.query) ?? null;
|
|
7501
8341
|
}
|
|
7502
8342
|
/**
|
|
7503
8343
|
* Returns the rule at the given path or `id`, or `null` if it can't be resolved _or_ resolves
|
|
@@ -7520,24 +8360,24 @@ var QueryManager = class QueryManager {
|
|
|
7520
8360
|
* for the root group, which has no parent, and when the target can't be resolved.
|
|
7521
8361
|
*/
|
|
7522
8362
|
getParent(pathOrID) {
|
|
7523
|
-
const path = this
|
|
8363
|
+
const path = this.toPath(pathOrID);
|
|
7524
8364
|
if (path === null || path.length === 0) return null;
|
|
7525
|
-
if (!findPath(path, this
|
|
7526
|
-
return findPath(getParentPath(path), this
|
|
8365
|
+
if (!findPath(path, this.state.query)) return null;
|
|
8366
|
+
return findPath(getParentPath(path), this.state.query);
|
|
7527
8367
|
}
|
|
7528
8368
|
/**
|
|
7529
8369
|
* The normalized field list, as the `QueryBuilder` component would render it. Needed to
|
|
7530
8370
|
* populate a field selector.
|
|
7531
8371
|
*/
|
|
7532
8372
|
getFields() {
|
|
7533
|
-
return this
|
|
8373
|
+
return this.state.fields;
|
|
7534
8374
|
}
|
|
7535
8375
|
/**
|
|
7536
8376
|
* The normalized combinator list, as the `QueryBuilder` component would render it. Needed to
|
|
7537
8377
|
* populate a combinator selector.
|
|
7538
8378
|
*/
|
|
7539
8379
|
getCombinators() {
|
|
7540
|
-
return this
|
|
8380
|
+
return this.state.combinators;
|
|
7541
8381
|
}
|
|
7542
8382
|
/**
|
|
7543
8383
|
* The field configuration for a field name. When the field isn't configured, returns the same
|
|
@@ -7545,27 +8385,51 @@ var QueryManager = class QueryManager {
|
|
|
7545
8385
|
* {@link QueryManager.getRuleContext} reports as `fieldData`, so both access paths agree.
|
|
7546
8386
|
*/
|
|
7547
8387
|
getFieldData(field) {
|
|
7548
|
-
return getFieldData(field, this
|
|
8388
|
+
return getFieldData(field, this.state.fieldMap);
|
|
7549
8389
|
}
|
|
7550
8390
|
/** The operator list for a field, mirroring `QueryBuilder`'s precedence. */
|
|
7551
8391
|
getOperators(field) {
|
|
7552
|
-
return this
|
|
8392
|
+
return this.operatorsFor(field);
|
|
7553
8393
|
}
|
|
7554
8394
|
/** The value sources available for a field/operator pair. */
|
|
7555
8395
|
getValueSources(field, operator) {
|
|
7556
|
-
return this
|
|
8396
|
+
return this.valueSourcesFor(field, operator);
|
|
7557
8397
|
}
|
|
7558
8398
|
/** The match modes available for a field. */
|
|
7559
8399
|
getMatchModes(field) {
|
|
7560
|
-
return this
|
|
8400
|
+
return this.matchModesFor(field);
|
|
7561
8401
|
}
|
|
7562
8402
|
/** The value option list for a field/operator pair. */
|
|
7563
8403
|
getValues(field, operator) {
|
|
7564
|
-
return this
|
|
8404
|
+
return this.valuesFor(field, operator);
|
|
7565
8405
|
}
|
|
7566
8406
|
/** The value editor type for a field/operator pair. */
|
|
7567
8407
|
getValueEditorType(field, operator) {
|
|
7568
|
-
return this
|
|
8408
|
+
return this.valueEditorTypeFor(field, operator);
|
|
8409
|
+
}
|
|
8410
|
+
/**
|
|
8411
|
+
* The default `operator` for a field, identical to the operator
|
|
8412
|
+
* {@link QueryManager.createRule} would assign to a new rule on that field.
|
|
8413
|
+
*/
|
|
8414
|
+
getRuleDefaultOperator(field) {
|
|
8415
|
+
return this.defaultOperator(field);
|
|
8416
|
+
}
|
|
8417
|
+
/**
|
|
8418
|
+
* The default `value` for a rule, identical to the value {@link QueryManager.createRule} and
|
|
8419
|
+
* {@link QueryManager.update} would assign after a field or operator change.
|
|
8420
|
+
*/
|
|
8421
|
+
getRuleDefaultValue(rule) {
|
|
8422
|
+
return this.defaultValue(rule);
|
|
8423
|
+
}
|
|
8424
|
+
/**
|
|
8425
|
+
* The flattened field record backing {@link QueryManager.getFieldData}, keyed by field name
|
|
8426
|
+
* with option groups flattened away.
|
|
8427
|
+
*
|
|
8428
|
+
* Treat the result as read-only. It may or may not be frozen depending on configuration, so
|
|
8429
|
+
* do not rely on frozen-ness to prevent mutation.
|
|
8430
|
+
*/
|
|
8431
|
+
getFieldMap() {
|
|
8432
|
+
return this.state.fieldMap;
|
|
7569
8433
|
}
|
|
7570
8434
|
/**
|
|
7571
8435
|
* Resolves everything about a rule that depends on the field/operator configuration—field data,
|
|
@@ -7580,16 +8444,16 @@ var QueryManager = class QueryManager {
|
|
|
7580
8444
|
if (!rule) return null;
|
|
7581
8445
|
const validation = this.validate();
|
|
7582
8446
|
return deriveRuleContext(rule, {
|
|
7583
|
-
fields: this
|
|
7584
|
-
fieldMap: this
|
|
7585
|
-
getInputType: (f, o, misc) => this
|
|
7586
|
-
getMatchModes: (f) => this
|
|
7587
|
-
getOperators: (f) => this
|
|
7588
|
-
getParameters: (f, o, misc) => this
|
|
7589
|
-
getValueEditorType: (f, o) => this
|
|
7590
|
-
getValues: (f, o) => this
|
|
8447
|
+
fields: this.state.fields,
|
|
8448
|
+
fieldMap: this.state.fieldMap,
|
|
8449
|
+
getInputType: (f, o, misc) => this.state.options.getInputType?.(f, o, misc) ?? null,
|
|
8450
|
+
getMatchModes: (f) => this.matchModesFor(f),
|
|
8451
|
+
getOperators: (f) => this.operatorsFor(f),
|
|
8452
|
+
getParameters: (f, o, misc) => this.parametersFor(f, o, misc),
|
|
8453
|
+
getValueEditorType: (f, o) => this.valueEditorTypeFor(f, o),
|
|
8454
|
+
getValues: (f, o) => this.valuesFor(f, o),
|
|
7591
8455
|
getValueSources: (f, o) => this.getValueSources(f, o),
|
|
7592
|
-
getSubQueryBuilderProps: (f, misc) => this
|
|
8456
|
+
getSubQueryBuilderProps: (f, misc) => this.state.options.getSubQueryBuilderProps?.(f, misc) ?? {}
|
|
7593
8457
|
}, {
|
|
7594
8458
|
validationMap: typeof validation === "boolean" ? {} : validation,
|
|
7595
8459
|
id: rule.id
|
|
@@ -7605,32 +8469,32 @@ var QueryManager = class QueryManager {
|
|
|
7605
8469
|
const ruleGroup = this.getGroup(pathOrID);
|
|
7606
8470
|
if (!ruleGroup) return null;
|
|
7607
8471
|
const validation = this.validate();
|
|
7608
|
-
return deriveRuleGroupContext(ruleGroup, this
|
|
8472
|
+
return deriveRuleGroupContext(ruleGroup, this.state.combinators, {
|
|
7609
8473
|
validationMap: typeof validation === "boolean" ? {} : validation,
|
|
7610
8474
|
id: ruleGroup.id
|
|
7611
8475
|
});
|
|
7612
8476
|
}
|
|
7613
8477
|
/** Whether the current query uses independent combinators. */
|
|
7614
8478
|
isIC() {
|
|
7615
|
-
return isRuleGroupTypeIC(this
|
|
8479
|
+
return isRuleGroupTypeIC(this.state.query);
|
|
7616
8480
|
}
|
|
7617
8481
|
/**
|
|
7618
8482
|
* Returns the signature describing how the current query differs from `other`, as used by
|
|
7619
8483
|
* this manager's history coalescing.
|
|
7620
8484
|
*/
|
|
7621
8485
|
signatureOf(other) {
|
|
7622
|
-
return signatureOf(this
|
|
8486
|
+
return signatureOf(this.state.query, other);
|
|
7623
8487
|
}
|
|
7624
8488
|
/** Generates a {@link DiagnosticsResult}. Shorthand for `format('diagnostics')`. */
|
|
7625
8489
|
diagnostics() {
|
|
7626
|
-
return formatQuery(this
|
|
8490
|
+
return formatQuery(this.state.query, "diagnostics");
|
|
7627
8491
|
}
|
|
7628
8492
|
/**
|
|
7629
8493
|
* Returns the current query, so `JSON.stringify(queryManager)` produces the same output as
|
|
7630
8494
|
* `JSON.stringify(queryManager.getQuery())`.
|
|
7631
8495
|
*/
|
|
7632
8496
|
toJSON() {
|
|
7633
|
-
return this
|
|
8497
|
+
return this.state.query;
|
|
7634
8498
|
}
|
|
7635
8499
|
/**
|
|
7636
8500
|
* Returns a new manager with the same configuration and the current query converted to use
|
|
@@ -7638,7 +8502,7 @@ var QueryManager = class QueryManager {
|
|
|
7638
8502
|
* {@link QueryManager.clone}, subscribers and history are not carried over.
|
|
7639
8503
|
*/
|
|
7640
8504
|
toIC() {
|
|
7641
|
-
return new QueryManager(convertToIC(this
|
|
8505
|
+
return new QueryManager(convertToIC(this.state.query), this.state.options);
|
|
7642
8506
|
}
|
|
7643
8507
|
/**
|
|
7644
8508
|
* Returns a new manager with the same configuration and the current query converted to use a
|
|
@@ -7646,7 +8510,7 @@ var QueryManager = class QueryManager {
|
|
|
7646
8510
|
* {@link QueryManager.clone}, subscribers and history are not carried over.
|
|
7647
8511
|
*/
|
|
7648
8512
|
fromIC() {
|
|
7649
|
-
return new QueryManager(convertFromIC(this
|
|
8513
|
+
return new QueryManager(convertFromIC(this.state.query), this.state.options);
|
|
7650
8514
|
}
|
|
7651
8515
|
/**
|
|
7652
8516
|
* Runs {@link transformQuery} against the current query and returns its result.
|
|
@@ -7656,7 +8520,7 @@ var QueryManager = class QueryManager {
|
|
|
7656
8520
|
* shapes that are no longer valid queries. This manager is never modified.
|
|
7657
8521
|
*/
|
|
7658
8522
|
transform(options) {
|
|
7659
|
-
return transformQuery(this
|
|
8523
|
+
return transformQuery(this.state.query, options);
|
|
7660
8524
|
}
|
|
7661
8525
|
};
|
|
7662
8526
|
//#endregion
|
|
@@ -7673,6 +8537,9 @@ exports.celCombinatorMap = celCombinatorMap;
|
|
|
7673
8537
|
exports.clsx = clsx;
|
|
7674
8538
|
exports.coerceBigIntValue = coerceBigIntValue;
|
|
7675
8539
|
exports.coerceInputType = coerceInputType;
|
|
8540
|
+
exports.controlKeys = controlKeys;
|
|
8541
|
+
exports.controlKind = controlKind;
|
|
8542
|
+
exports.controlPropKeys = controlPropKeys;
|
|
7676
8543
|
exports.convertFromIC = convertFromIC;
|
|
7677
8544
|
exports.convertQuery = convertQuery;
|
|
7678
8545
|
exports.convertToIC = convertToIC;
|
|
@@ -7848,6 +8715,7 @@ exports.numericRegex = numericRegex;
|
|
|
7848
8715
|
exports.numerifyValues = numerifyValues;
|
|
7849
8716
|
exports.objectEntries = objectEntries;
|
|
7850
8717
|
exports.objectKeys = objectKeys;
|
|
8718
|
+
exports.optionsEqual = optionsEqual;
|
|
7851
8719
|
exports.parseNumber = parseNumber;
|
|
7852
8720
|
exports.pathIsDisabled = pathIsDisabled;
|
|
7853
8721
|
exports.pathIsDisabledByPaths = pathIsDisabledByPaths;
|
|
@@ -7874,6 +8742,8 @@ exports.resolveOperatorList = resolveOperatorList;
|
|
|
7874
8742
|
exports.resolveValueEditorType = resolveValueEditorType;
|
|
7875
8743
|
exports.resolveValueList = resolveValueList;
|
|
7876
8744
|
exports.rootPath = rootPath;
|
|
8745
|
+
exports.setAutoFreeze = setAutoFreeze;
|
|
8746
|
+
exports.shouldCoalesce = shouldCoalesce;
|
|
7877
8747
|
exports.shouldRenderAsNumber = shouldRenderAsNumber;
|
|
7878
8748
|
exports.signatureOf = signatureOf;
|
|
7879
8749
|
exports.sparqlVar = sparqlVar;
|
|
@@ -7900,6 +8770,7 @@ exports.uniqOptList = uniqOptList;
|
|
|
7900
8770
|
exports.update = update;
|
|
7901
8771
|
exports.updateInPlace = updateInPlace;
|
|
7902
8772
|
exports.uuidV4regex = uuidV4regex;
|
|
8773
|
+
exports.valuesEqual = valuesEqual;
|
|
7903
8774
|
exports.withParamPrefix = withParamPrefix;
|
|
7904
8775
|
exports.wrapLikeFragment = wrapLikeFragment;
|
|
7905
8776
|
|