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/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/match-engine.ts
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: 0.4,
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
- const aliases = restricted.flatMap(
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
- if (results.length > 0 && (results[0].score ?? 1) <= 0.4) {
248
- log(
249
- "field match: %s -> %s (score: %f)",
250
- candidate,
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
- if (results.length > 0 && (results[0].score ?? 1) <= 0.4) {
262
- const alias = results[0].item.alias;
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 * 0.5) return null;
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
- results[0].item.operator.value,
271
- results[0].score
274
+ best.item.operator.value,
275
+ best.score
272
276
  );
273
- return { option: results[0].item.operator, score: results[0].score ?? 1 };
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: 0.4,
312
+ threshold: FUSE_THRESHOLD,
309
313
  includeScore: true
310
314
  });
311
315
  const results = fuse.search(raw);
312
- if (results.length > 0 && (results[0].score ?? 1) <= 0.4) {
313
- valueLog(
314
- "fuzzy match: raw=%s -> %s (score: %f)",
315
- raw,
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
- if (field.operators) return field.operators;
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
- // src/fuzzy/score.ts
342
- var AMBIGUOUS_OP_WORDS = /* @__PURE__ */ new Set(["is", "has"]);
343
- var AMBIGUITY_PENALTY = 0.35;
344
- var LINKING_VERB_PENALTY = 0.35;
345
- var LENGTH_BONUS_PER_WORD = 0.01;
346
- var GAP_PENALTY_PER_WORD = 0.3;
347
- var UNPARSED_PENALTY = 10;
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
- return score;
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
- return score;
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.fields = engine.fields;
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: fieldResult.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: fieldResult.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
- identifyField(words) {
501
- let best = null;
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(parser, segmentResolver) {
616
- this.parser = parser;
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.parser.fields.slice(0, limit).map((f) => ({ completion: f.label, display: f.label }));
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.parser.identifyField(words);
658
+ const fieldResult = this.query.identifyField(words);
648
659
  if (!fieldResult) {
649
660
  if (endsWithSpace) return [];
650
- return this.parser.prefixMatches(
661
+ return this.query.prefixMatches(
651
662
  words.join(" "),
652
- this.parser.fields.map((f) => f.label),
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.parser.allowedOpsForField(fieldOption);
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.parser.prefixMatches(
673
+ return this.query.prefixMatches(
663
674
  words.join(" "),
664
- this.parser.fields.map((f) => f.label),
675
+ this.query.getFields().map((f) => f.label),
665
676
  limit
666
677
  );
667
678
  }
668
- const candidates = this.parser.getOperatorCandidates(fieldResult.remaining, fieldOption);
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.parser.allowedOpsForField(fieldOption);
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.parser.prefixMatches(opPartial, aliases, limit);
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.parser.allowedOpsForField(fieldOption);
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.parser.prefixMatches(opPartial, aliases, limit);
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.parser.prefixMatches(
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(parser, segmentResolver) {
718
- this.parser = parser;
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.parser.fields.find(
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
- for (let i = 0; i < lowerWords.length; i++) {
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
- const single = this.parser.parse(text);
804
- return {
805
- segments: [text],
806
- conditions: single ? [single] : [],
807
- connector: AND_CONJUNCTION
808
- };
808
+ return fallback;
809
809
  }
810
- const noSplit = this.parser.parse(text);
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 splitIndices = subset.map((s) => s.index);
821
- const segments = splitAtIndices(originalWords, splitIndices);
822
- if (segments.some((s) => !s)) continue;
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
- if (best.conditions.length === 1 && best.conditions[0].value.isValid && best.conditions[0].value.matchedOption === null) {
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 parser = new ConditionParser(engine);
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(parser, this.segments);
899
- this.diagnostics = new DiagnosticsProvider(parser, this.segments);
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 (isStandalone(props)) {
983
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StandaloneInput, { ...props });
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 isStandalone(props) {
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 StandaloneInput({
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, ctrl+space for suggestions",
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
- if (e.key === " " && e.ctrlKey) {
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.jsxs)("div", { className: ["rcui-input-wrapper", className].filter(Boolean).join(" "), style, children: [
1178
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1179
- import_TextField.default,
1180
- {
1181
- fullWidth: true,
1182
- variant: "outlined",
1183
- size: "small",
1184
- placeholder,
1185
- value,
1186
- onChange: handleChange,
1187
- onKeyDown: handleKeyDown,
1188
- onBlur: () => setTimeout(closeCompletions, 150),
1189
- className: "rcui-input",
1190
- slotProps: {
1191
- input: {
1192
- inputComponent: GhostInput,
1193
- inputProps: ghostInputProps,
1194
- endAdornment: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_InputAdornment.default, { position: "end", children: hasErrors ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Tooltip.default, { title: errorSummary, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_IconButton.default, { size: "small", onClick: onSubmit, edge: "end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1195
- import_ErrorOutline.default,
1196
- {
1197
- fontSize: "small",
1198
- className: "rcui-adornment-error"
1199
- }
1200
- ) }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_IconButton.default, { size: "small", onClick: onSubmit, edge: "end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1201
- import_KeyboardReturn.default,
1202
- {
1203
- fontSize: "small",
1204
- className: "rcui-adornment-enter"
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
- id: `rcui-completion-${i}`,
1222
- role: "option",
1223
- "aria-selected": i === activeIndex,
1224
- className: `rcui-completion-item${i === activeIndex ? " rcui-completion-item--active" : ""}`,
1225
- onMouseDown: (e) => {
1226
- e.preventDefault();
1227
- acceptCompletion(item);
1228
- },
1229
- onMouseEnter: () => setActiveIndex(i),
1230
- children: item.display
1231
- },
1232
- item.display
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/components/output-drag-end.ts
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
- groups: controlledGroups,
1693
- onGroupsChange
1694
- });
1695
- const readOnly = controlledGroups !== void 0 && !onGroupsChange;
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
- Input,
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
- Output,
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