react-conditional-ui 1.2.0 → 1.2.1
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/README.md +2 -0
- package/dist/index.cjs +458 -299
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +3 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +40 -12
- package/dist/index.d.ts +40 -12
- package/dist/index.js +453 -299
- package/dist/index.js.map +1 -1
- package/dist/styles.css +4 -0
- package/package.json +26 -1
package/dist/index.cjs
CHANGED
|
@@ -33,9 +33,14 @@ __export(index_exports, {
|
|
|
33
33
|
ConditionDataProvider: () => ConditionDataProvider,
|
|
34
34
|
ConditionParser: () => ConditionDataProvider,
|
|
35
35
|
ConditionalUI: () => ConditionalUI,
|
|
36
|
+
ControlledInput: () => ControlledInput,
|
|
37
|
+
ControlledOutput: () => ControlledOutput,
|
|
36
38
|
DEFAULT_OPERATORS: () => DEFAULT_OPERATORS,
|
|
37
39
|
Input: () => Input,
|
|
40
|
+
ManagedInput: () => ManagedInput,
|
|
41
|
+
ManagedOutput: () => ManagedOutput,
|
|
38
42
|
Output: () => Output,
|
|
43
|
+
ReadOnlyOutput: () => ReadOnlyOutput,
|
|
39
44
|
useConditionDataProvider: () => useConditionDataProvider,
|
|
40
45
|
useConditionalInput: () => useConditionalInput,
|
|
41
46
|
useConditionalOutput: () => useConditionalOutput
|
|
@@ -45,8 +50,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
45
50
|
// src/components/Input.tsx
|
|
46
51
|
var import_react3 = require("react");
|
|
47
52
|
var import_TextField = __toESM(require("@mui/material/TextField"), 1);
|
|
53
|
+
var import_ClickAwayListener = __toESM(require("@mui/material/ClickAwayListener"), 1);
|
|
48
54
|
var import_InputAdornment = __toESM(require("@mui/material/InputAdornment"), 1);
|
|
49
55
|
var import_IconButton = __toESM(require("@mui/material/IconButton"), 1);
|
|
56
|
+
var import_Stack = __toESM(require("@mui/material/Stack"), 1);
|
|
57
|
+
var import_Add = __toESM(require("@mui/icons-material/Add"), 1);
|
|
50
58
|
var import_KeyboardReturn = __toESM(require("@mui/icons-material/KeyboardReturn"), 1);
|
|
51
59
|
var import_ErrorOutline = __toESM(require("@mui/icons-material/ErrorOutline"), 1);
|
|
52
60
|
var import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
|
|
@@ -203,74 +211,70 @@ var import_debug = __toESM(require("debug"), 1);
|
|
|
203
211
|
var BASE = "react-conditional-ui";
|
|
204
212
|
var createLogger = (namespace) => (0, import_debug.default)(`${BASE}:${namespace}`);
|
|
205
213
|
|
|
206
|
-
// src/fuzzy/
|
|
207
|
-
var log = createLogger("match-engine");
|
|
208
|
-
var valueLog = createLogger("value");
|
|
214
|
+
// src/fuzzy/operator-policy.ts
|
|
209
215
|
var TYPE_ALLOWED_OPS = {
|
|
210
216
|
number: /* @__PURE__ */ new Set(["eq", "ne", "gt", "lt", "gte", "lte"]),
|
|
211
217
|
enum: /* @__PURE__ */ new Set(["eq", "ne"]),
|
|
212
218
|
text: /* @__PURE__ */ new Set(["eq", "ne", "contains", "starts_with"])
|
|
213
219
|
};
|
|
220
|
+
function allowedOperatorsForField(field, allOperators) {
|
|
221
|
+
if (field.operators) return field.operators;
|
|
222
|
+
if (field.type) {
|
|
223
|
+
const allowed = TYPE_ALLOWED_OPS[field.type];
|
|
224
|
+
return allOperators.filter((op) => allowed.has(op.value));
|
|
225
|
+
}
|
|
226
|
+
return allOperators;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/fuzzy/match-engine.ts
|
|
230
|
+
var log = createLogger("match-engine");
|
|
231
|
+
var valueLog = createLogger("value");
|
|
232
|
+
var FUSE_THRESHOLD = 0.4;
|
|
233
|
+
var OPERATOR_ALIAS_MIN_COVERAGE = 0.5;
|
|
214
234
|
var MatchEngine = class _MatchEngine {
|
|
215
235
|
constructor(fields, operators) {
|
|
216
236
|
this.fields = fields;
|
|
217
237
|
this.operators = operators;
|
|
218
238
|
this.fieldFuse = new import_fuse.default(fields, {
|
|
219
239
|
keys: ["label"],
|
|
220
|
-
threshold:
|
|
221
|
-
includeScore: true
|
|
222
|
-
});
|
|
223
|
-
const flatAliases = operators.flatMap(
|
|
224
|
-
(op) => op.aliases.map((alias) => ({ alias: alias.toLowerCase(), operator: op }))
|
|
225
|
-
);
|
|
226
|
-
this.opFuse = new import_fuse.default(flatAliases, {
|
|
227
|
-
keys: ["alias"],
|
|
228
|
-
threshold: 0.4,
|
|
240
|
+
threshold: FUSE_THRESHOLD,
|
|
229
241
|
includeScore: true
|
|
230
242
|
});
|
|
243
|
+
this.opFuse = this.createOperatorAliasFuse(operators);
|
|
231
244
|
this.perFieldOpFuse = /* @__PURE__ */ new Map();
|
|
232
245
|
for (const field of fields) {
|
|
233
246
|
const restricted = this.resolveOpsForField(field, operators);
|
|
234
247
|
if (restricted !== operators) {
|
|
235
|
-
|
|
236
|
-
(op) => op.aliases.map((alias) => ({ alias: alias.toLowerCase(), operator: op }))
|
|
237
|
-
);
|
|
238
|
-
this.perFieldOpFuse.set(
|
|
239
|
-
field.value,
|
|
240
|
-
new import_fuse.default(aliases, { keys: ["alias"], threshold: 0.4, includeScore: true })
|
|
241
|
-
);
|
|
248
|
+
this.perFieldOpFuse.set(field.value, this.createOperatorAliasFuse(restricted));
|
|
242
249
|
}
|
|
243
250
|
}
|
|
244
251
|
}
|
|
245
252
|
matchField(candidate) {
|
|
246
253
|
const results = this.fieldFuse.search(candidate);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
results[0].item.value,
|
|
252
|
-
results[0].score
|
|
253
|
-
);
|
|
254
|
-
return { option: results[0].item, score: results[0].score ?? 1 };
|
|
254
|
+
const best = results[0];
|
|
255
|
+
if (best && _MatchEngine.isWithinThreshold(best.score)) {
|
|
256
|
+
log("field match: %s -> %s (score: %f)", candidate, best.item.value, best.score);
|
|
257
|
+
return { option: best.item, score: best.score ?? 1 };
|
|
255
258
|
}
|
|
256
259
|
return null;
|
|
257
260
|
}
|
|
258
261
|
matchOperator(candidate, field) {
|
|
259
262
|
const fuse = (field && this.perFieldOpFuse.get(field.value)) ?? this.opFuse;
|
|
260
263
|
const results = fuse.search(candidate);
|
|
261
|
-
|
|
262
|
-
|
|
264
|
+
const best = results[0];
|
|
265
|
+
if (best && _MatchEngine.isWithinThreshold(best.score)) {
|
|
266
|
+
const alias = best.item.alias;
|
|
263
267
|
const candidateWords = candidate.split(/\s+/).length;
|
|
264
268
|
const aliasWords = alias.split(/\s+/).length;
|
|
265
269
|
if (candidateWords !== aliasWords) return null;
|
|
266
|
-
if (candidate.length < alias.length *
|
|
270
|
+
if (candidate.length < alias.length * OPERATOR_ALIAS_MIN_COVERAGE) return null;
|
|
267
271
|
log(
|
|
268
272
|
"operator match: %s -> %s (score: %f)",
|
|
269
273
|
candidate,
|
|
270
|
-
|
|
271
|
-
|
|
274
|
+
best.item.operator.value,
|
|
275
|
+
best.score
|
|
272
276
|
);
|
|
273
|
-
return { option:
|
|
277
|
+
return { option: best.item.operator, score: best.score ?? 1 };
|
|
274
278
|
}
|
|
275
279
|
return null;
|
|
276
280
|
}
|
|
@@ -305,18 +309,14 @@ var MatchEngine = class _MatchEngine {
|
|
|
305
309
|
if (raw.length === 0) return Value.invalid(raw, "Value not recognized");
|
|
306
310
|
const fuse = new import_fuse.default(knownValues, {
|
|
307
311
|
keys: ["label", "value"],
|
|
308
|
-
threshold:
|
|
312
|
+
threshold: FUSE_THRESHOLD,
|
|
309
313
|
includeScore: true
|
|
310
314
|
});
|
|
311
315
|
const results = fuse.search(raw);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
results[0].item.value,
|
|
317
|
-
results[0].score
|
|
318
|
-
);
|
|
319
|
-
return _MatchEngine.applyValidator(raw, results[0].item, validateValue);
|
|
316
|
+
const best = results[0];
|
|
317
|
+
if (best && _MatchEngine.isWithinThreshold(best.score)) {
|
|
318
|
+
valueLog("fuzzy match: raw=%s -> %s (score: %f)", raw, best.item.value, best.score);
|
|
319
|
+
return _MatchEngine.applyValidator(raw, best.item, validateValue);
|
|
320
320
|
}
|
|
321
321
|
valueLog("no match: raw=%s", raw);
|
|
322
322
|
return Value.invalid(raw, "Value not recognized");
|
|
@@ -329,51 +329,22 @@ var MatchEngine = class _MatchEngine {
|
|
|
329
329
|
return Value.valid(raw, matched);
|
|
330
330
|
}
|
|
331
331
|
resolveOpsForField(field, allOps) {
|
|
332
|
-
|
|
333
|
-
if (field.type) {
|
|
334
|
-
const allowed = TYPE_ALLOWED_OPS[field.type];
|
|
335
|
-
return allOps.filter((op) => allowed.has(op.value));
|
|
336
|
-
}
|
|
337
|
-
return allOps;
|
|
332
|
+
return allowedOperatorsForField(field, allOps);
|
|
338
333
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
var FREETEXT_WORD_COST = 0.1;
|
|
349
|
-
function adjustOperatorScore(baseScore, words, start, end) {
|
|
350
|
-
let score = baseScore;
|
|
351
|
-
const firstWord = words[start];
|
|
352
|
-
if (end - start === 1 && AMBIGUOUS_OP_WORDS.has(firstWord)) {
|
|
353
|
-
score += AMBIGUITY_PENALTY;
|
|
354
|
-
} else if (end - start > 1 && AMBIGUOUS_OP_WORDS.has(firstWord)) {
|
|
355
|
-
score += LINKING_VERB_PENALTY;
|
|
356
|
-
}
|
|
357
|
-
score -= (end - start) * LENGTH_BONUS_PER_WORD;
|
|
358
|
-
if (start > 0) {
|
|
359
|
-
score += start * GAP_PENALTY_PER_WORD;
|
|
334
|
+
createOperatorAliasFuse(operators) {
|
|
335
|
+
const aliases = operators.flatMap(
|
|
336
|
+
(op) => op.aliases.map((alias) => ({ alias: alias.toLowerCase(), operator: op }))
|
|
337
|
+
);
|
|
338
|
+
return new import_fuse.default(aliases, {
|
|
339
|
+
keys: ["alias"],
|
|
340
|
+
threshold: FUSE_THRESHOLD,
|
|
341
|
+
includeScore: true
|
|
342
|
+
});
|
|
360
343
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
function scoreConditions(conditions, segmentCount) {
|
|
364
|
-
const unparsed = segmentCount - conditions.length;
|
|
365
|
-
let score = unparsed * UNPARSED_PENALTY;
|
|
366
|
-
for (const c of conditions) {
|
|
367
|
-
score += c.score;
|
|
368
|
-
if (!c.field.isValid) score += UNPARSED_PENALTY;
|
|
369
|
-
if (!c.operator.isValid) score += UNPARSED_PENALTY;
|
|
370
|
-
if (!c.value.isValid) score += UNPARSED_PENALTY;
|
|
371
|
-
if (c.value.isValid && c.value.matchedOption === null) {
|
|
372
|
-
score += c.value.raw.split(/\s+/).length * FREETEXT_WORD_COST;
|
|
373
|
-
}
|
|
344
|
+
static isWithinThreshold(score) {
|
|
345
|
+
return (score ?? 1) <= FUSE_THRESHOLD;
|
|
374
346
|
}
|
|
375
|
-
|
|
376
|
-
}
|
|
347
|
+
};
|
|
377
348
|
|
|
378
349
|
// src/fuzzy/word-utils.ts
|
|
379
350
|
var NOISE_WORDS = /* @__PURE__ */ new Set([
|
|
@@ -443,18 +414,113 @@ function stripLeadingNoise(words) {
|
|
|
443
414
|
return result;
|
|
444
415
|
}
|
|
445
416
|
|
|
417
|
+
// src/fuzzy/score.ts
|
|
418
|
+
var AMBIGUOUS_OP_WORDS = /* @__PURE__ */ new Set(["is", "has"]);
|
|
419
|
+
var AMBIGUITY_PENALTY = 0.35;
|
|
420
|
+
var LINKING_VERB_PENALTY = 0.35;
|
|
421
|
+
var LENGTH_BONUS_PER_WORD = 0.01;
|
|
422
|
+
var GAP_PENALTY_PER_WORD = 0.3;
|
|
423
|
+
var UNPARSED_PENALTY = 10;
|
|
424
|
+
var FREETEXT_WORD_COST = 0.1;
|
|
425
|
+
function adjustOperatorScore(baseScore, words, start, end) {
|
|
426
|
+
let score = baseScore;
|
|
427
|
+
const firstWord = words[start];
|
|
428
|
+
if (end - start === 1 && AMBIGUOUS_OP_WORDS.has(firstWord)) {
|
|
429
|
+
score += AMBIGUITY_PENALTY;
|
|
430
|
+
} else if (end - start > 1 && AMBIGUOUS_OP_WORDS.has(firstWord)) {
|
|
431
|
+
score += LINKING_VERB_PENALTY;
|
|
432
|
+
}
|
|
433
|
+
score -= (end - start) * LENGTH_BONUS_PER_WORD;
|
|
434
|
+
if (start > 0) {
|
|
435
|
+
score += start * GAP_PENALTY_PER_WORD;
|
|
436
|
+
}
|
|
437
|
+
return score;
|
|
438
|
+
}
|
|
439
|
+
function scoreConditions(conditions, segmentCount) {
|
|
440
|
+
const unparsed = segmentCount - conditions.length;
|
|
441
|
+
let score = unparsed * UNPARSED_PENALTY;
|
|
442
|
+
for (const c of conditions) {
|
|
443
|
+
score += c.score;
|
|
444
|
+
if (!c.field.isValid) score += UNPARSED_PENALTY;
|
|
445
|
+
if (!c.operator.isValid) score += UNPARSED_PENALTY;
|
|
446
|
+
if (!c.value.isValid) score += UNPARSED_PENALTY;
|
|
447
|
+
if (c.value.isValid && c.value.matchedOption === null) {
|
|
448
|
+
score += c.value.raw.split(/\s+/).length * FREETEXT_WORD_COST;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return score;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/conditions/query-helper.ts
|
|
455
|
+
var ConditionQueryHelper = class {
|
|
456
|
+
constructor(engine, fields, operators) {
|
|
457
|
+
this.engine = engine;
|
|
458
|
+
this.fields = fields;
|
|
459
|
+
this.operators = operators;
|
|
460
|
+
}
|
|
461
|
+
getFields() {
|
|
462
|
+
return this.fields;
|
|
463
|
+
}
|
|
464
|
+
findFieldByValue(value) {
|
|
465
|
+
return this.fields.find((field) => field.value === value);
|
|
466
|
+
}
|
|
467
|
+
identifyField(words) {
|
|
468
|
+
let best = null;
|
|
469
|
+
for (let i = words.length; i >= 1; i--) {
|
|
470
|
+
const candidate = words.slice(0, i).join(" ");
|
|
471
|
+
const match = this.engine.matchField(candidate);
|
|
472
|
+
if (match && (!best || match.score < best.match.score)) {
|
|
473
|
+
best = { candidate, match, wordCount: i };
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (!best) return null;
|
|
477
|
+
return {
|
|
478
|
+
raw: best.candidate,
|
|
479
|
+
fieldOption: best.match.option,
|
|
480
|
+
fieldScore: best.match.score,
|
|
481
|
+
remaining: words.slice(best.wordCount)
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
getOperatorCandidates(words, fieldOption) {
|
|
485
|
+
const candidates = [];
|
|
486
|
+
for (let start = 0; start < words.length; start++) {
|
|
487
|
+
for (let end = start + 1; end <= words.length; end++) {
|
|
488
|
+
const opRaw = words.slice(start, end).join(" ");
|
|
489
|
+
const opMatch = this.engine.matchOperator(opRaw, fieldOption);
|
|
490
|
+
if (!opMatch) continue;
|
|
491
|
+
candidates.push({
|
|
492
|
+
match: opMatch,
|
|
493
|
+
raw: opRaw,
|
|
494
|
+
endIdx: end,
|
|
495
|
+
adjustedScore: adjustOperatorScore(opMatch.score, words, start, end)
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
candidates.sort((a, b) => a.adjustedScore - b.adjustedScore);
|
|
500
|
+
return candidates;
|
|
501
|
+
}
|
|
502
|
+
allowedOpsForField(field) {
|
|
503
|
+
return allowedOperatorsForField(field, this.operators);
|
|
504
|
+
}
|
|
505
|
+
prefixMatches(partial, candidates, limit = 6) {
|
|
506
|
+
const lower = partial.toLowerCase();
|
|
507
|
+
const results = [];
|
|
508
|
+
for (const candidate of candidates) {
|
|
509
|
+
const cl = candidate.toLowerCase();
|
|
510
|
+
if (cl.startsWith(lower) && cl !== lower) {
|
|
511
|
+
results.push({ completion: cl.slice(lower.length), display: candidate });
|
|
512
|
+
if (results.length >= limit) break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return results;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
|
|
446
519
|
// src/conditions/parser.ts
|
|
447
520
|
var log2 = createLogger("parser");
|
|
448
|
-
var TYPE_ALLOWED_OPS2 = {
|
|
449
|
-
number: /* @__PURE__ */ new Set(["eq", "ne", "gt", "lt", "gte", "lte"]),
|
|
450
|
-
enum: /* @__PURE__ */ new Set(["eq", "ne"]),
|
|
451
|
-
text: /* @__PURE__ */ new Set(["eq", "ne", "contains", "starts_with"])
|
|
452
|
-
};
|
|
453
521
|
var ConditionParser = class {
|
|
454
|
-
constructor(engine) {
|
|
455
|
-
this.
|
|
456
|
-
this.operators = engine.operators;
|
|
457
|
-
this.engine = engine;
|
|
522
|
+
constructor(engine, queryHelper) {
|
|
523
|
+
this.query = queryHelper ?? new ConditionQueryHelper(engine, engine.fields, engine.operators);
|
|
458
524
|
}
|
|
459
525
|
parse(text) {
|
|
460
526
|
const input = text.trim().toLowerCase();
|
|
@@ -462,11 +528,15 @@ var ConditionParser = class {
|
|
|
462
528
|
const allWords = input.split(/\s+/);
|
|
463
529
|
const words = stripLeadingNoise(allWords);
|
|
464
530
|
if (words.length === 0) return null;
|
|
465
|
-
const fieldResult = this.identifyField(words);
|
|
531
|
+
const fieldResult = this.query.identifyField(words);
|
|
466
532
|
if (!fieldResult) return null;
|
|
467
533
|
if (fieldResult.remaining.length === 0) {
|
|
468
534
|
return {
|
|
469
|
-
field:
|
|
535
|
+
field: new Field(
|
|
536
|
+
fieldResult.raw,
|
|
537
|
+
fieldResult.fieldOption.value,
|
|
538
|
+
fieldResult.fieldOption.label
|
|
539
|
+
),
|
|
470
540
|
operator: Operator.invalid(""),
|
|
471
541
|
value: Value.empty(),
|
|
472
542
|
score: fieldResult.fieldScore
|
|
@@ -477,7 +547,11 @@ var ConditionParser = class {
|
|
|
477
547
|
fieldResult.fieldOption
|
|
478
548
|
);
|
|
479
549
|
const result = {
|
|
480
|
-
field:
|
|
550
|
+
field: new Field(
|
|
551
|
+
fieldResult.raw,
|
|
552
|
+
fieldResult.fieldOption.value,
|
|
553
|
+
fieldResult.fieldOption.label
|
|
554
|
+
),
|
|
481
555
|
operator,
|
|
482
556
|
value,
|
|
483
557
|
score: fieldResult.fieldScore + operatorScore
|
|
@@ -497,40 +571,8 @@ var ConditionParser = class {
|
|
|
497
571
|
);
|
|
498
572
|
return result;
|
|
499
573
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
for (let i = words.length; i >= 1; i--) {
|
|
503
|
-
const candidate = words.slice(0, i).join(" ");
|
|
504
|
-
const match = this.engine.matchField(candidate);
|
|
505
|
-
if (match && (!best || match.score < best.match.score)) {
|
|
506
|
-
best = { candidate, match, wordCount: i };
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
if (!best) return null;
|
|
510
|
-
return {
|
|
511
|
-
field: new Field(best.candidate, best.match.option.value, best.match.option.label),
|
|
512
|
-
fieldOption: best.match.option,
|
|
513
|
-
fieldScore: best.match.score,
|
|
514
|
-
remaining: words.slice(best.wordCount)
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
getOperatorCandidates(words, fieldOption) {
|
|
518
|
-
const candidates = [];
|
|
519
|
-
for (let start = 0; start < words.length; start++) {
|
|
520
|
-
for (let end = start + 1; end <= words.length; end++) {
|
|
521
|
-
const opRaw = words.slice(start, end).join(" ");
|
|
522
|
-
const opMatch = this.engine.matchOperator(opRaw, fieldOption);
|
|
523
|
-
if (!opMatch) continue;
|
|
524
|
-
const adjustedScore = adjustOperatorScore(opMatch.score, words, start, end);
|
|
525
|
-
candidates.push({
|
|
526
|
-
match: opMatch,
|
|
527
|
-
raw: opRaw,
|
|
528
|
-
endIdx: end,
|
|
529
|
-
adjustedScore
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
candidates.sort((a, b) => a.adjustedScore - b.adjustedScore);
|
|
574
|
+
resolveOperator(words, fieldOption) {
|
|
575
|
+
const candidates = this.query.getOperatorCandidates(words, fieldOption);
|
|
534
576
|
if (candidates.length > 0) {
|
|
535
577
|
log2(
|
|
536
578
|
"operator candidates: %o",
|
|
@@ -539,10 +581,6 @@ var ConditionParser = class {
|
|
|
539
581
|
)
|
|
540
582
|
);
|
|
541
583
|
}
|
|
542
|
-
return candidates;
|
|
543
|
-
}
|
|
544
|
-
resolveOperator(words, fieldOption) {
|
|
545
|
-
const candidates = this.getOperatorCandidates(words, fieldOption);
|
|
546
584
|
if (candidates.length === 0) {
|
|
547
585
|
return {
|
|
548
586
|
operator: Operator.invalid(words.join(" ")),
|
|
@@ -577,33 +615,6 @@ var ConditionParser = class {
|
|
|
577
615
|
operatorScore: best.adjustedScore
|
|
578
616
|
};
|
|
579
617
|
}
|
|
580
|
-
resolveOpsForField(field, allOps) {
|
|
581
|
-
if (field.operators) return field.operators;
|
|
582
|
-
if (field.type) {
|
|
583
|
-
const allowed = TYPE_ALLOWED_OPS2[field.type];
|
|
584
|
-
return allOps.filter((op) => allowed.has(op.value));
|
|
585
|
-
}
|
|
586
|
-
return allOps;
|
|
587
|
-
}
|
|
588
|
-
allowedOpsForField(field) {
|
|
589
|
-
return this.resolveOpsForField(field, this.operators);
|
|
590
|
-
}
|
|
591
|
-
prefixMatch(partial, candidates) {
|
|
592
|
-
const matches = this.prefixMatches(partial, candidates);
|
|
593
|
-
return matches.length > 0 ? matches[0] : null;
|
|
594
|
-
}
|
|
595
|
-
prefixMatches(partial, candidates, limit = 6) {
|
|
596
|
-
const lower = partial.toLowerCase();
|
|
597
|
-
const results = [];
|
|
598
|
-
for (const candidate of candidates) {
|
|
599
|
-
const cl = candidate.toLowerCase();
|
|
600
|
-
if (cl.startsWith(lower) && cl !== lower) {
|
|
601
|
-
results.push({ completion: cl.slice(lower.length), display: candidate });
|
|
602
|
-
if (results.length >= limit) break;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
return results;
|
|
606
|
-
}
|
|
607
618
|
};
|
|
608
619
|
|
|
609
620
|
// src/consts.ts
|
|
@@ -612,8 +623,8 @@ var OR_CONJUNCTION = "or";
|
|
|
612
623
|
|
|
613
624
|
// src/fuzzy/providers/suggestions.ts
|
|
614
625
|
var SuggestionsProvider = class {
|
|
615
|
-
constructor(
|
|
616
|
-
this.
|
|
626
|
+
constructor(query, segmentResolver) {
|
|
627
|
+
this.query = query;
|
|
617
628
|
this.segmentResolver = segmentResolver;
|
|
618
629
|
}
|
|
619
630
|
getCompletions(text, limit = 6) {
|
|
@@ -639,40 +650,40 @@ var SuggestionsProvider = class {
|
|
|
639
650
|
completionsForSegment(text, limit) {
|
|
640
651
|
const input = text.trimStart().toLowerCase();
|
|
641
652
|
if (!input) {
|
|
642
|
-
return this.
|
|
653
|
+
return this.query.getFields().slice(0, limit).map((f) => ({ completion: f.label, display: f.label }));
|
|
643
654
|
}
|
|
644
655
|
const endsWithSpace = /\s$/.test(input);
|
|
645
656
|
const words = input.split(/\s+/).filter(Boolean);
|
|
646
657
|
if (words.length === 0) return [];
|
|
647
|
-
const fieldResult = this.
|
|
658
|
+
const fieldResult = this.query.identifyField(words);
|
|
648
659
|
if (!fieldResult) {
|
|
649
660
|
if (endsWithSpace) return [];
|
|
650
|
-
return this.
|
|
661
|
+
return this.query.prefixMatches(
|
|
651
662
|
words.join(" "),
|
|
652
|
-
this.
|
|
663
|
+
this.query.getFields().map((f) => f.label),
|
|
653
664
|
limit
|
|
654
665
|
);
|
|
655
666
|
}
|
|
656
667
|
const fieldOption = fieldResult.fieldOption;
|
|
657
668
|
if (fieldResult.remaining.length === 0) {
|
|
658
669
|
if (endsWithSpace) {
|
|
659
|
-
const ops = this.
|
|
670
|
+
const ops = this.query.allowedOpsForField(fieldOption);
|
|
660
671
|
return ops.slice(0, limit).map((op) => ({ completion: op.label, display: op.label }));
|
|
661
672
|
}
|
|
662
|
-
return this.
|
|
673
|
+
return this.query.prefixMatches(
|
|
663
674
|
words.join(" "),
|
|
664
|
-
this.
|
|
675
|
+
this.query.getFields().map((f) => f.label),
|
|
665
676
|
limit
|
|
666
677
|
);
|
|
667
678
|
}
|
|
668
|
-
const candidates = this.
|
|
679
|
+
const candidates = this.query.getOperatorCandidates(fieldResult.remaining, fieldOption);
|
|
669
680
|
const bestOp = candidates[0];
|
|
670
681
|
if (!bestOp || bestOp.endIdx > fieldResult.remaining.length) {
|
|
671
682
|
if (endsWithSpace) return [];
|
|
672
|
-
const ops = this.
|
|
683
|
+
const ops = this.query.allowedOpsForField(fieldOption);
|
|
673
684
|
const aliases = ops.flatMap((op) => op.aliases);
|
|
674
685
|
const opPartial = fieldResult.remaining.join(" ");
|
|
675
|
-
return this.
|
|
686
|
+
return this.query.prefixMatches(opPartial, aliases, limit);
|
|
676
687
|
}
|
|
677
688
|
const valueRaw = fieldResult.remaining.slice(bestOp.endIdx).join(" ");
|
|
678
689
|
if (!valueRaw) {
|
|
@@ -681,15 +692,15 @@ var SuggestionsProvider = class {
|
|
|
681
692
|
if (!fieldValues2?.length) return [];
|
|
682
693
|
return fieldValues2.slice(0, limit).map((v) => ({ completion: v.label, display: v.label }));
|
|
683
694
|
}
|
|
684
|
-
const ops = this.
|
|
695
|
+
const ops = this.query.allowedOpsForField(fieldOption);
|
|
685
696
|
const aliases = ops.flatMap((op) => op.aliases);
|
|
686
697
|
const opPartial = fieldResult.remaining.join(" ");
|
|
687
|
-
return this.
|
|
698
|
+
return this.query.prefixMatches(opPartial, aliases, limit);
|
|
688
699
|
}
|
|
689
700
|
if (endsWithSpace) return [];
|
|
690
701
|
const fieldValues = fieldOption.fieldValues;
|
|
691
702
|
if (!fieldValues?.length) return [];
|
|
692
|
-
return this.
|
|
703
|
+
return this.query.prefixMatches(
|
|
693
704
|
valueRaw,
|
|
694
705
|
fieldValues.map((v) => v.label),
|
|
695
706
|
limit
|
|
@@ -714,8 +725,8 @@ var SuggestionsProvider = class {
|
|
|
714
725
|
|
|
715
726
|
// src/fuzzy/providers/diagnostics.ts
|
|
716
727
|
var DiagnosticsProvider = class {
|
|
717
|
-
constructor(
|
|
718
|
-
this.
|
|
728
|
+
constructor(query, segmentResolver) {
|
|
729
|
+
this.query = query;
|
|
719
730
|
this.segmentResolver = segmentResolver;
|
|
720
731
|
}
|
|
721
732
|
diagnose(text) {
|
|
@@ -742,9 +753,7 @@ var DiagnosticsProvider = class {
|
|
|
742
753
|
}
|
|
743
754
|
if (!condition.operator.isValid) {
|
|
744
755
|
const fieldEnd = offset + condition.field.raw.length;
|
|
745
|
-
const fieldConfig = this.
|
|
746
|
-
(f) => f.value === condition.field.value
|
|
747
|
-
);
|
|
756
|
+
const fieldConfig = this.query.findFieldByValue(condition.field.value);
|
|
748
757
|
const hasRestriction = fieldConfig?.operators || fieldConfig?.type;
|
|
749
758
|
diagnostics.push({
|
|
750
759
|
start: fieldEnd,
|
|
@@ -793,60 +802,26 @@ var SegmentResolver = class {
|
|
|
793
802
|
resolve(text) {
|
|
794
803
|
const originalWords = text.split(/\s+/);
|
|
795
804
|
const lowerWords = originalWords.map((w) => w.toLowerCase());
|
|
796
|
-
const conjIndices =
|
|
797
|
-
|
|
798
|
-
if (lowerWords[i] === AND_CONJUNCTION || lowerWords[i] === OR_CONJUNCTION) {
|
|
799
|
-
conjIndices.push({ index: i, conjunction: lowerWords[i] });
|
|
800
|
-
}
|
|
801
|
-
}
|
|
805
|
+
const conjIndices = this.findConjunctionIndices(lowerWords);
|
|
806
|
+
const fallback = this.createSingleCandidate(text);
|
|
802
807
|
if (conjIndices.length === 0) {
|
|
803
|
-
|
|
804
|
-
return {
|
|
805
|
-
segments: [text],
|
|
806
|
-
conditions: single ? [single] : [],
|
|
807
|
-
connector: AND_CONJUNCTION
|
|
808
|
-
};
|
|
808
|
+
return fallback;
|
|
809
809
|
}
|
|
810
|
-
|
|
811
|
-
let best = {
|
|
812
|
-
segments: [text],
|
|
813
|
-
conditions: noSplit ? [noSplit] : [],
|
|
814
|
-
connector: AND_CONJUNCTION
|
|
815
|
-
};
|
|
810
|
+
let best = fallback;
|
|
816
811
|
let bestScore = scoreConditions(best.conditions, 1);
|
|
817
812
|
for (const subset of powerSet(conjIndices)) {
|
|
818
813
|
const connector = subset[0].conjunction;
|
|
819
814
|
if (subset.some((s) => s.conjunction !== connector)) continue;
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
const conditions = this.parseSegments(segments);
|
|
815
|
+
const next = this.buildSplitCandidate(originalWords, subset, connector);
|
|
816
|
+
if (!next) continue;
|
|
817
|
+
const { segments, conditions } = next;
|
|
824
818
|
const score = scoreConditions(conditions, segments.length);
|
|
825
819
|
if (score < bestScore) {
|
|
826
820
|
bestScore = score;
|
|
827
821
|
best = { segments, conditions, connector };
|
|
828
822
|
}
|
|
829
823
|
}
|
|
830
|
-
|
|
831
|
-
const valueWords = best.conditions[0].value.raw.split(/\s+/);
|
|
832
|
-
const conjInValue = valueWords.find(
|
|
833
|
-
(w) => w.toLowerCase() === AND_CONJUNCTION || w.toLowerCase() === OR_CONJUNCTION
|
|
834
|
-
);
|
|
835
|
-
if (conjInValue) {
|
|
836
|
-
const connector = conjInValue.toLowerCase();
|
|
837
|
-
const matching = conjIndices.filter((c) => c.conjunction === connector);
|
|
838
|
-
for (const subset of powerSet(matching).reverse()) {
|
|
839
|
-
const splitIndices = subset.map((s) => s.index);
|
|
840
|
-
const segments = splitAtIndices(originalWords, splitIndices);
|
|
841
|
-
if (segments.some((s) => !s)) continue;
|
|
842
|
-
const conditions = this.parseSegments(segments);
|
|
843
|
-
if (conditions.length === segments.length && conditions.every((c) => c.field.isValid && c.operator.isValid)) {
|
|
844
|
-
return { segments, conditions, connector };
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
return best;
|
|
824
|
+
return this.trySplitFromValueConjunction(best, originalWords, conjIndices) ?? best;
|
|
850
825
|
}
|
|
851
826
|
parseConditions(text) {
|
|
852
827
|
const input = text.trim();
|
|
@@ -869,6 +844,54 @@ var SegmentResolver = class {
|
|
|
869
844
|
}
|
|
870
845
|
return conditions;
|
|
871
846
|
}
|
|
847
|
+
createSingleCandidate(text) {
|
|
848
|
+
const parsed = this.parser.parse(text);
|
|
849
|
+
return {
|
|
850
|
+
segments: [text],
|
|
851
|
+
conditions: parsed ? [parsed] : [],
|
|
852
|
+
connector: AND_CONJUNCTION
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
findConjunctionIndices(words) {
|
|
856
|
+
const indices = [];
|
|
857
|
+
for (let i = 0; i < words.length; i++) {
|
|
858
|
+
if (words[i] === AND_CONJUNCTION || words[i] === OR_CONJUNCTION) {
|
|
859
|
+
indices.push({ index: i, conjunction: words[i] });
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return indices;
|
|
863
|
+
}
|
|
864
|
+
buildSplitCandidate(originalWords, splitPoints, connector) {
|
|
865
|
+
const splitIndices = splitPoints.map((s) => s.index);
|
|
866
|
+
const segments = splitAtIndices(originalWords, splitIndices);
|
|
867
|
+
if (segments.some((s) => !s)) return null;
|
|
868
|
+
return {
|
|
869
|
+
segments,
|
|
870
|
+
conditions: this.parseSegments(segments),
|
|
871
|
+
connector
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
trySplitFromValueConjunction(best, originalWords, conjIndices) {
|
|
875
|
+
const onlyCondition = best.conditions[0];
|
|
876
|
+
if (best.conditions.length !== 1 || !onlyCondition?.value.isValid || onlyCondition.value.matchedOption !== null) {
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
const valueWords = onlyCondition.value.raw.split(/\s+/);
|
|
880
|
+
const conjInValue = valueWords.find(
|
|
881
|
+
(w) => w.toLowerCase() === AND_CONJUNCTION || w.toLowerCase() === OR_CONJUNCTION
|
|
882
|
+
);
|
|
883
|
+
if (!conjInValue) return null;
|
|
884
|
+
const connector = conjInValue.toLowerCase();
|
|
885
|
+
const matching = conjIndices.filter((c) => c.conjunction === connector);
|
|
886
|
+
for (const subset of powerSet(matching).reverse()) {
|
|
887
|
+
const candidate = this.buildSplitCandidate(originalWords, subset, connector);
|
|
888
|
+
if (!candidate) continue;
|
|
889
|
+
if (candidate.conditions.length === candidate.segments.length && candidate.conditions.every((c) => c.field.isValid && c.operator.isValid)) {
|
|
890
|
+
return candidate;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
return null;
|
|
894
|
+
}
|
|
872
895
|
getInherited(segment, previous) {
|
|
873
896
|
if (!previous) return null;
|
|
874
897
|
const direct = this.parser.parse(segment);
|
|
@@ -893,10 +916,11 @@ var SegmentResolver = class {
|
|
|
893
916
|
var ConditionDataProvider = class {
|
|
894
917
|
constructor(fields, operators) {
|
|
895
918
|
const engine = new MatchEngine(fields, operators);
|
|
896
|
-
const
|
|
919
|
+
const query = new ConditionQueryHelper(engine, fields, operators);
|
|
920
|
+
const parser = new ConditionParser(engine, query);
|
|
897
921
|
this.segments = new SegmentResolver(parser);
|
|
898
|
-
this.suggestions = new SuggestionsProvider(
|
|
899
|
-
this.diagnostics = new DiagnosticsProvider(
|
|
922
|
+
this.suggestions = new SuggestionsProvider(query, this.segments);
|
|
923
|
+
this.diagnostics = new DiagnosticsProvider(query, this.segments);
|
|
900
924
|
}
|
|
901
925
|
parseComplexCondition(text) {
|
|
902
926
|
return this.segments.parseConditions(text);
|
|
@@ -979,9 +1003,12 @@ function useConditionalInput({
|
|
|
979
1003
|
// src/components/Input.tsx
|
|
980
1004
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
981
1005
|
function Input(props) {
|
|
982
|
-
if (
|
|
983
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1006
|
+
if (isManaged(props)) {
|
|
1007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ManagedInput, { ...props });
|
|
984
1008
|
}
|
|
1009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ControlledInput, { ...props });
|
|
1010
|
+
}
|
|
1011
|
+
function ControlledInput(props) {
|
|
985
1012
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
986
1013
|
InputView,
|
|
987
1014
|
{
|
|
@@ -997,7 +1024,7 @@ function Input(props) {
|
|
|
997
1024
|
}
|
|
998
1025
|
);
|
|
999
1026
|
}
|
|
1000
|
-
function
|
|
1027
|
+
function isManaged(props) {
|
|
1001
1028
|
return props.fields !== void 0;
|
|
1002
1029
|
}
|
|
1003
1030
|
function buildOverlaySegments(value, diagnostics) {
|
|
@@ -1046,7 +1073,7 @@ var GhostInput = (0, import_react3.forwardRef)(function GhostInput2({ ghost, dia
|
|
|
1046
1073
|
) })
|
|
1047
1074
|
] });
|
|
1048
1075
|
});
|
|
1049
|
-
function
|
|
1076
|
+
function ManagedInput({
|
|
1050
1077
|
fields,
|
|
1051
1078
|
operators,
|
|
1052
1079
|
value: controlledValue,
|
|
@@ -1082,7 +1109,7 @@ function InputView({
|
|
|
1082
1109
|
value,
|
|
1083
1110
|
onChange,
|
|
1084
1111
|
onSubmit,
|
|
1085
|
-
placeholder = "e.g. age greater than 18
|
|
1112
|
+
placeholder = "e.g. age greater than 18 \u2014 Control(Option)+Space for suggestions",
|
|
1086
1113
|
getSuggestion,
|
|
1087
1114
|
getCompletions,
|
|
1088
1115
|
diagnostics = [],
|
|
@@ -1093,11 +1120,17 @@ function InputView({
|
|
|
1093
1120
|
const [activeIndex, setActiveIndex] = (0, import_react3.useState)(-1);
|
|
1094
1121
|
const [cursorLeft, setCursorLeft] = (0, import_react3.useState)(0);
|
|
1095
1122
|
const listRef = (0, import_react3.useRef)(null);
|
|
1123
|
+
const inputRef = (0, import_react3.useRef)(null);
|
|
1096
1124
|
const ghost = getSuggestion && value ? getSuggestion(value)?.completion ?? null : null;
|
|
1097
1125
|
function closeCompletions() {
|
|
1098
1126
|
setCompletions([]);
|
|
1099
1127
|
setActiveIndex(-1);
|
|
1100
1128
|
}
|
|
1129
|
+
function handleCompletionsClickAway() {
|
|
1130
|
+
if (completions.length === 0) return;
|
|
1131
|
+
closeCompletions();
|
|
1132
|
+
queueMicrotask(() => inputRef.current?.focus());
|
|
1133
|
+
}
|
|
1101
1134
|
function openCompletions() {
|
|
1102
1135
|
if (!getCompletions) return;
|
|
1103
1136
|
const items = getCompletions(value);
|
|
@@ -1116,7 +1149,9 @@ function InputView({
|
|
|
1116
1149
|
if (ghost) onChange(value + ghost);
|
|
1117
1150
|
}
|
|
1118
1151
|
function handleKeyDown(e) {
|
|
1119
|
-
|
|
1152
|
+
const isSpace = e.key === " " || e.code === "Space";
|
|
1153
|
+
const suggestChord = isSpace && !e.shiftKey && !e.metaKey && (e.ctrlKey || e.altKey);
|
|
1154
|
+
if (suggestChord) {
|
|
1120
1155
|
e.preventDefault();
|
|
1121
1156
|
openCompletions();
|
|
1122
1157
|
return;
|
|
@@ -1174,66 +1209,106 @@ function InputView({
|
|
|
1174
1209
|
inputValue: value,
|
|
1175
1210
|
onCursorOffset: setCursorLeft
|
|
1176
1211
|
};
|
|
1177
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ClickAwayListener.default, { onClickAway: handleCompletionsClickAway, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1213
|
+
"div",
|
|
1214
|
+
{
|
|
1215
|
+
className: ["rcui-input-wrapper", className].filter(Boolean).join(" "),
|
|
1216
|
+
style,
|
|
1217
|
+
children: [
|
|
1218
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1219
|
+
import_TextField.default,
|
|
1220
|
+
{
|
|
1221
|
+
fullWidth: true,
|
|
1222
|
+
variant: "outlined",
|
|
1223
|
+
size: "small",
|
|
1224
|
+
placeholder,
|
|
1225
|
+
value,
|
|
1226
|
+
onChange: handleChange,
|
|
1227
|
+
onKeyDown: handleKeyDown,
|
|
1228
|
+
className: "rcui-input",
|
|
1229
|
+
slotProps: {
|
|
1230
|
+
input: {
|
|
1231
|
+
inputRef,
|
|
1232
|
+
inputComponent: GhostInput,
|
|
1233
|
+
inputProps: ghostInputProps,
|
|
1234
|
+
endAdornment: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_InputAdornment.default, { position: "end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Stack.default, { direction: "row", alignItems: "center", spacing: 0, children: [
|
|
1235
|
+
getCompletions ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Tooltip.default, { title: "Show suggestions", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1236
|
+
import_IconButton.default,
|
|
1237
|
+
{
|
|
1238
|
+
size: "small",
|
|
1239
|
+
"aria-label": "Show suggestions",
|
|
1240
|
+
className: "rcui-adornment-suggestions",
|
|
1241
|
+
onMouseDown: (e) => {
|
|
1242
|
+
e.preventDefault();
|
|
1243
|
+
openCompletions();
|
|
1244
|
+
},
|
|
1245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Add.default, { fontSize: "small" })
|
|
1246
|
+
}
|
|
1247
|
+
) }) : null,
|
|
1248
|
+
hasErrors ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Tooltip.default, { title: errorSummary, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1249
|
+
import_IconButton.default,
|
|
1250
|
+
{
|
|
1251
|
+
size: "small",
|
|
1252
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1253
|
+
onClick: onSubmit,
|
|
1254
|
+
edge: "end",
|
|
1255
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1256
|
+
import_ErrorOutline.default,
|
|
1257
|
+
{
|
|
1258
|
+
fontSize: "small",
|
|
1259
|
+
className: "rcui-adornment-error"
|
|
1260
|
+
}
|
|
1261
|
+
)
|
|
1262
|
+
}
|
|
1263
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1264
|
+
import_IconButton.default,
|
|
1265
|
+
{
|
|
1266
|
+
size: "small",
|
|
1267
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1268
|
+
onClick: onSubmit,
|
|
1269
|
+
edge: "end",
|
|
1270
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1271
|
+
import_KeyboardReturn.default,
|
|
1272
|
+
{
|
|
1273
|
+
fontSize: "small",
|
|
1274
|
+
className: "rcui-adornment-enter"
|
|
1275
|
+
}
|
|
1276
|
+
)
|
|
1277
|
+
}
|
|
1278
|
+
)
|
|
1279
|
+
] }) })
|
|
1205
1280
|
}
|
|
1206
|
-
|
|
1281
|
+
}
|
|
1207
1282
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
completions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1212
|
-
"ul",
|
|
1213
|
-
{
|
|
1214
|
-
ref: listRef,
|
|
1215
|
-
className: "rcui-completions",
|
|
1216
|
-
role: "listbox",
|
|
1217
|
-
style: { left: cursorLeft },
|
|
1218
|
-
children: completions.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1219
|
-
"li",
|
|
1283
|
+
),
|
|
1284
|
+
completions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1285
|
+
"ul",
|
|
1220
1286
|
{
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
"
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1287
|
+
ref: listRef,
|
|
1288
|
+
className: "rcui-completions",
|
|
1289
|
+
role: "listbox",
|
|
1290
|
+
style: { left: cursorLeft },
|
|
1291
|
+
children: completions.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1292
|
+
"li",
|
|
1293
|
+
{
|
|
1294
|
+
id: `rcui-completion-${i}`,
|
|
1295
|
+
role: "option",
|
|
1296
|
+
"aria-selected": i === activeIndex,
|
|
1297
|
+
className: `rcui-completion-item${i === activeIndex ? " rcui-completion-item--active" : ""}`,
|
|
1298
|
+
onMouseDown: (e) => {
|
|
1299
|
+
e.preventDefault();
|
|
1300
|
+
acceptCompletion(item);
|
|
1301
|
+
},
|
|
1302
|
+
onMouseEnter: () => setActiveIndex(i),
|
|
1303
|
+
children: item.display
|
|
1304
|
+
},
|
|
1305
|
+
item.display
|
|
1306
|
+
))
|
|
1307
|
+
}
|
|
1308
|
+
)
|
|
1309
|
+
]
|
|
1310
|
+
}
|
|
1311
|
+
) });
|
|
1237
1312
|
}
|
|
1238
1313
|
|
|
1239
1314
|
// src/components/Output.tsx
|
|
@@ -1424,7 +1499,7 @@ var import_react5 = require("react");
|
|
|
1424
1499
|
var import_core = require("@dnd-kit/core");
|
|
1425
1500
|
var import_sortable2 = require("@dnd-kit/sortable");
|
|
1426
1501
|
|
|
1427
|
-
// src/
|
|
1502
|
+
// src/dnd/output-drag-end.ts
|
|
1428
1503
|
var UNGROUP_ZONE_ID = "ungrouped-drop-zone";
|
|
1429
1504
|
var GROUP_DROPPABLE_PREFIX = "group:";
|
|
1430
1505
|
function findGroupByEntryId(groups, entryId) {
|
|
@@ -1679,20 +1754,91 @@ var DEFAULT_GROUP_CONFIG = {
|
|
|
1679
1754
|
removable: true,
|
|
1680
1755
|
variant: "outlined"
|
|
1681
1756
|
};
|
|
1682
|
-
function Output({
|
|
1757
|
+
function Output(props) {
|
|
1758
|
+
if (isManagedOutput(props)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ManagedOutput, { ...props });
|
|
1759
|
+
if (isReadOnlyOutput(props)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ReadOnlyOutput, { ...props });
|
|
1760
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ControlledOutput, { ...props });
|
|
1761
|
+
}
|
|
1762
|
+
function ManagedOutput({
|
|
1683
1763
|
fields,
|
|
1684
1764
|
operators,
|
|
1685
|
-
groups: controlledGroups,
|
|
1686
1765
|
onGroupsChange,
|
|
1687
1766
|
defaultGroupConfig,
|
|
1688
1767
|
className,
|
|
1689
1768
|
style
|
|
1690
1769
|
}) {
|
|
1691
|
-
const { groups, mutations } = useConditionalOutput({
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1770
|
+
const { groups, mutations } = useConditionalOutput({ onGroupsChange });
|
|
1771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1772
|
+
OutputView,
|
|
1773
|
+
{
|
|
1774
|
+
groups,
|
|
1775
|
+
mutations,
|
|
1776
|
+
readOnly: false,
|
|
1777
|
+
fields,
|
|
1778
|
+
operators,
|
|
1779
|
+
defaultGroupConfig,
|
|
1780
|
+
className,
|
|
1781
|
+
style
|
|
1782
|
+
}
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1785
|
+
function ControlledOutput({
|
|
1786
|
+
fields,
|
|
1787
|
+
operators,
|
|
1788
|
+
groups,
|
|
1789
|
+
onGroupsChange,
|
|
1790
|
+
defaultGroupConfig,
|
|
1791
|
+
className,
|
|
1792
|
+
style
|
|
1793
|
+
}) {
|
|
1794
|
+
const { mutations } = useConditionalOutput({ groups, onGroupsChange });
|
|
1795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1796
|
+
OutputView,
|
|
1797
|
+
{
|
|
1798
|
+
groups,
|
|
1799
|
+
mutations,
|
|
1800
|
+
readOnly: false,
|
|
1801
|
+
fields,
|
|
1802
|
+
operators,
|
|
1803
|
+
defaultGroupConfig,
|
|
1804
|
+
className,
|
|
1805
|
+
style
|
|
1806
|
+
}
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
function ReadOnlyOutput({
|
|
1810
|
+
fields,
|
|
1811
|
+
operators,
|
|
1812
|
+
groups,
|
|
1813
|
+
defaultGroupConfig,
|
|
1814
|
+
className,
|
|
1815
|
+
style
|
|
1816
|
+
}) {
|
|
1817
|
+
const { mutations } = useConditionalOutput({ groups });
|
|
1818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1819
|
+
OutputView,
|
|
1820
|
+
{
|
|
1821
|
+
groups,
|
|
1822
|
+
mutations,
|
|
1823
|
+
readOnly: true,
|
|
1824
|
+
fields,
|
|
1825
|
+
operators,
|
|
1826
|
+
defaultGroupConfig,
|
|
1827
|
+
className,
|
|
1828
|
+
style
|
|
1829
|
+
}
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
function OutputView({
|
|
1833
|
+
groups,
|
|
1834
|
+
mutations,
|
|
1835
|
+
readOnly,
|
|
1836
|
+
fields,
|
|
1837
|
+
operators,
|
|
1838
|
+
defaultGroupConfig,
|
|
1839
|
+
className,
|
|
1840
|
+
style
|
|
1841
|
+
}) {
|
|
1696
1842
|
const effectiveDefault = readOnly ? { editable: false, removable: false, ...defaultGroupConfig } : defaultGroupConfig;
|
|
1697
1843
|
const rootClass = ["rcui-output", className].filter(Boolean).join(" ");
|
|
1698
1844
|
const renderOverlay = (entry) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "rcui-overlay", children: [
|
|
@@ -1726,6 +1872,12 @@ function Output({
|
|
|
1726
1872
|
group.id
|
|
1727
1873
|
)) }) });
|
|
1728
1874
|
}
|
|
1875
|
+
function isManagedOutput(props) {
|
|
1876
|
+
return props.groups === void 0;
|
|
1877
|
+
}
|
|
1878
|
+
function isReadOnlyOutput(props) {
|
|
1879
|
+
return props.groups !== void 0 && props.onGroupsChange === void 0;
|
|
1880
|
+
}
|
|
1729
1881
|
function resolveConfig(groupConfig, defaultConfig) {
|
|
1730
1882
|
return { ...DEFAULT_GROUP_CONFIG, ...defaultConfig, ...groupConfig };
|
|
1731
1883
|
}
|
|
@@ -1795,6 +1947,8 @@ function ConditionalUI({
|
|
|
1795
1947
|
value,
|
|
1796
1948
|
onChange,
|
|
1797
1949
|
onConditionsChange,
|
|
1950
|
+
InputComponent = ManagedInput,
|
|
1951
|
+
OutputComponent = ControlledOutput,
|
|
1798
1952
|
className,
|
|
1799
1953
|
style
|
|
1800
1954
|
}) {
|
|
@@ -1804,7 +1958,7 @@ function ConditionalUI({
|
|
|
1804
1958
|
const rootClass = ["rcui-root", className].filter(Boolean).join(" ");
|
|
1805
1959
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: rootClass, style, children: [
|
|
1806
1960
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1807
|
-
|
|
1961
|
+
InputComponent,
|
|
1808
1962
|
{
|
|
1809
1963
|
fields,
|
|
1810
1964
|
operators,
|
|
@@ -1814,7 +1968,7 @@ function ConditionalUI({
|
|
|
1814
1968
|
}
|
|
1815
1969
|
),
|
|
1816
1970
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1817
|
-
|
|
1971
|
+
OutputComponent,
|
|
1818
1972
|
{
|
|
1819
1973
|
groups,
|
|
1820
1974
|
fields,
|
|
@@ -1829,9 +1983,14 @@ function ConditionalUI({
|
|
|
1829
1983
|
ConditionDataProvider,
|
|
1830
1984
|
ConditionParser,
|
|
1831
1985
|
ConditionalUI,
|
|
1986
|
+
ControlledInput,
|
|
1987
|
+
ControlledOutput,
|
|
1832
1988
|
DEFAULT_OPERATORS,
|
|
1833
1989
|
Input,
|
|
1990
|
+
ManagedInput,
|
|
1991
|
+
ManagedOutput,
|
|
1834
1992
|
Output,
|
|
1993
|
+
ReadOnlyOutput,
|
|
1835
1994
|
useConditionDataProvider,
|
|
1836
1995
|
useConditionalInput,
|
|
1837
1996
|
useConditionalOutput
|