@yourself.create/ngx-form-designer 0.0.8 → 0.0.9
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/fesm2022/uch-web-ngx-form-designer.mjs +409 -377
- package/fesm2022/uch-web-ngx-form-designer.mjs.map +1 -1
- package/lib/data/data-provider.d.ts +0 -1
- package/lib/form-core/form-engine.d.ts +3 -0
- package/lib/form-core/models.d.ts +7 -12
- package/lib/form-designer/data-panel/data-panel.component.d.ts +1 -4
- package/lib/form-designer/designer-state.service.d.ts +1 -1
- package/lib/form-designer/dynamic-properties/dynamic-properties.component.d.ts +0 -7
- package/lib/form-designer/form-preview.component.d.ts +2 -2
- package/lib/form-designer/layout-canvas.component.d.ts +2 -2
- package/lib/form-renderer/json-form-renderer.component.d.ts +10 -3
- package/lib/website/website-preview-shell.component.d.ts +1 -1
- package/lib/widgets/field-widgets/search/search-widget.component.d.ts +3 -0
- package/lib/widgets/field-widgets/select/select-widget.component.d.ts +1 -0
- package/lib/widgets/field-widgets/text-field/text-field.component.d.ts +2 -0
- package/lib/widgets/widget-definition.d.ts +1 -1
- package/package.json +1 -1
|
@@ -23,6 +23,15 @@ import Quill from 'quill';
|
|
|
23
23
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
24
24
|
import { HttpClient, provideHttpClient } from '@angular/common/http';
|
|
25
25
|
|
|
26
|
+
function usesFieldThousandSeparator(field) {
|
|
27
|
+
return field?.useThousandSeparator === true;
|
|
28
|
+
}
|
|
29
|
+
function isFieldReadonly(field) {
|
|
30
|
+
return field?.html5?.readonly === true;
|
|
31
|
+
}
|
|
32
|
+
function isFieldDisabled(field) {
|
|
33
|
+
return field?.html5?.disabled === true;
|
|
34
|
+
}
|
|
26
35
|
const CURRENT_SCHEMA_VERSION = '1.0.0';
|
|
27
36
|
|
|
28
37
|
/**
|
|
@@ -446,8 +455,8 @@ class FormEngine {
|
|
|
446
455
|
setValue(fieldName, value) {
|
|
447
456
|
this.values[fieldName] = value;
|
|
448
457
|
this.valueSubject.next({ ...this.values }); // Emit new state
|
|
449
|
-
//
|
|
450
|
-
this.
|
|
458
|
+
// Rules and dependencies can affect other fields, so revalidate the full form.
|
|
459
|
+
this.validate();
|
|
451
460
|
}
|
|
452
461
|
getValues() {
|
|
453
462
|
return { ...this.values };
|
|
@@ -502,7 +511,7 @@ class FormEngine {
|
|
|
502
511
|
if (!field)
|
|
503
512
|
return false;
|
|
504
513
|
// 1. Dependencies (Legacy)
|
|
505
|
-
let enabled = this.evaluateDependencyRules(field, 'enable', 'disable',
|
|
514
|
+
let enabled = this.evaluateDependencyRules(field, 'enable', 'disable', !isFieldDisabled(field));
|
|
506
515
|
// 2. Enterprise Rules
|
|
507
516
|
enabled = this.evaluateEnterpriseRules(field, 'enable', 'disable', enabled);
|
|
508
517
|
return enabled;
|
|
@@ -535,10 +544,16 @@ class FormEngine {
|
|
|
535
544
|
return;
|
|
536
545
|
const value = this.values[fieldName];
|
|
537
546
|
const fieldErrors = [];
|
|
547
|
+
const ruleErrors = this.getRuleValidationErrors(field);
|
|
538
548
|
// Visibility check
|
|
539
549
|
const isVisible = this.isFieldVisible(field.id);
|
|
540
550
|
if (!isVisible) {
|
|
541
|
-
|
|
551
|
+
if (ruleErrors.length > 0) {
|
|
552
|
+
this.errors[fieldName] = ruleErrors;
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
delete this.errors[fieldName];
|
|
556
|
+
}
|
|
542
557
|
return;
|
|
543
558
|
}
|
|
544
559
|
const isRequired = this.isFieldRequired(field.id);
|
|
@@ -568,30 +583,9 @@ class FormEngine {
|
|
|
568
583
|
}
|
|
569
584
|
}
|
|
570
585
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
let isValid = true;
|
|
575
|
-
if (rule.type === 'builtin') {
|
|
576
|
-
if (rule.name === 'email') {
|
|
577
|
-
isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value));
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
else if (rule.type === 'expression' && rule.expression) {
|
|
581
|
-
try {
|
|
582
|
-
const checkFn = new Function('value', 'form', `return ${rule.expression}`);
|
|
583
|
-
isValid = checkFn(value, this.values);
|
|
584
|
-
}
|
|
585
|
-
catch (e) {
|
|
586
|
-
console.error('Validation expression error', e);
|
|
587
|
-
isValid = false;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
if (!isValid) {
|
|
591
|
-
fieldErrors.push(rule.message || 'Validation failed.');
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
}
|
|
586
|
+
}
|
|
587
|
+
if (ruleErrors.length > 0) {
|
|
588
|
+
fieldErrors.push(...ruleErrors);
|
|
595
589
|
}
|
|
596
590
|
if (fieldErrors.length > 0) {
|
|
597
591
|
this.errors[fieldName] = fieldErrors;
|
|
@@ -600,6 +594,11 @@ class FormEngine {
|
|
|
600
594
|
delete this.errors[fieldName];
|
|
601
595
|
}
|
|
602
596
|
}
|
|
597
|
+
getRuleValidationErrors(field) {
|
|
598
|
+
return this.getEnterpriseRuleOutcomes(field)
|
|
599
|
+
.filter(({ rule, conditionMet }) => rule.severity === 'error' && !conditionMet && rule.elseAction === undefined)
|
|
600
|
+
.map(({ rule }) => this.getRuleValidationMessage(rule));
|
|
601
|
+
}
|
|
603
602
|
// Generic rule evaluator
|
|
604
603
|
evaluateDependencyRules(field, positiveEffect, negativeEffect, startValue) {
|
|
605
604
|
if (!field.dependencies)
|
|
@@ -638,13 +637,31 @@ class FormEngine {
|
|
|
638
637
|
if (hasPositiveRules && startValue === true) {
|
|
639
638
|
currentState = false; // Implicitly hide/disable
|
|
640
639
|
}
|
|
641
|
-
field.
|
|
642
|
-
const conditionMet = this.ruleEvaluator.evaluateRule(rule, this.values, this.schema.fields);
|
|
643
|
-
const nextAction = conditionMet ? rule.action : rule.elseAction;
|
|
640
|
+
this.getEnterpriseRuleOutcomes(field).forEach(({ nextAction }) => {
|
|
644
641
|
currentState = this.applyRuleAction(currentState, nextAction, positiveAction, negativeAction);
|
|
645
642
|
});
|
|
646
643
|
return currentState;
|
|
647
644
|
}
|
|
645
|
+
getEnterpriseRuleOutcomes(field) {
|
|
646
|
+
if (!field.rules || field.rules.length === 0) {
|
|
647
|
+
return [];
|
|
648
|
+
}
|
|
649
|
+
return field.rules.map((rule) => {
|
|
650
|
+
const conditionMet = this.ruleEvaluator.evaluateRule(rule, this.values, this.schema.fields);
|
|
651
|
+
return {
|
|
652
|
+
rule,
|
|
653
|
+
conditionMet,
|
|
654
|
+
nextAction: conditionMet ? rule.action : rule.elseAction
|
|
655
|
+
};
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
getRuleValidationMessage(rule) {
|
|
659
|
+
const name = rule.name?.trim();
|
|
660
|
+
if (name) {
|
|
661
|
+
return name;
|
|
662
|
+
}
|
|
663
|
+
return `Rule "${rule.action}" failed.`;
|
|
664
|
+
}
|
|
648
665
|
applyRuleAction(currentState, action, positiveAction, negativeAction) {
|
|
649
666
|
if (action === positiveAction) {
|
|
650
667
|
return true;
|
|
@@ -4496,6 +4513,7 @@ class FormEventRunner {
|
|
|
4496
4513
|
const target = fields.find(f => f.id === action.targetFieldId);
|
|
4497
4514
|
if (!target)
|
|
4498
4515
|
return;
|
|
4516
|
+
const previousValue = this.engine.getValue(target.name);
|
|
4499
4517
|
let val;
|
|
4500
4518
|
if (action.valueFrom === 'literal') {
|
|
4501
4519
|
val = action.valueLiteral;
|
|
@@ -4510,6 +4528,14 @@ class FormEventRunner {
|
|
|
4510
4528
|
}
|
|
4511
4529
|
}
|
|
4512
4530
|
this.engine.setValue(target.name, val);
|
|
4531
|
+
if (!Object.is(previousValue, val)) {
|
|
4532
|
+
this.engine.emitUiEvent({
|
|
4533
|
+
fieldId: target.id,
|
|
4534
|
+
fieldName: target.name,
|
|
4535
|
+
type: 'change',
|
|
4536
|
+
value: val
|
|
4537
|
+
});
|
|
4538
|
+
}
|
|
4513
4539
|
}
|
|
4514
4540
|
async handleApiAction(action, eventId, evt, fields) {
|
|
4515
4541
|
if (!this.apiExecutor) {
|
|
@@ -5181,6 +5207,7 @@ class JsonFormRendererComponent {
|
|
|
5181
5207
|
uploadClient = inject(FILE_UPLOAD_CLIENT, { optional: true }) ?? inject(DefaultFileUploadClient);
|
|
5182
5208
|
runtimeFieldDataAccessRegistry = inject(RuntimeFieldDataAccessRegistryService);
|
|
5183
5209
|
dataCatalog = inject(DataCatalog, { optional: true });
|
|
5210
|
+
ruleEvaluationService = inject(RuleEvaluationService);
|
|
5184
5211
|
constructor(designerState) {
|
|
5185
5212
|
this.designerState = designerState;
|
|
5186
5213
|
}
|
|
@@ -5435,10 +5462,12 @@ class JsonFormRendererComponent {
|
|
|
5435
5462
|
const errors = revalidate
|
|
5436
5463
|
? (this.engine?.validate() ?? {})
|
|
5437
5464
|
: (this.engine?.getErrors() ?? {});
|
|
5465
|
+
const fields = this.buildFieldValidationState(errors);
|
|
5438
5466
|
return {
|
|
5439
5467
|
errors: { ...errors },
|
|
5440
5468
|
isValid: Object.keys(errors).length === 0,
|
|
5441
|
-
|
|
5469
|
+
isSeverityError: Object.values(fields).some(field => field.isSeverityError),
|
|
5470
|
+
fields
|
|
5442
5471
|
};
|
|
5443
5472
|
}
|
|
5444
5473
|
buildFieldValidationState(errors) {
|
|
@@ -5459,71 +5488,99 @@ class JsonFormRendererComponent {
|
|
|
5459
5488
|
visible,
|
|
5460
5489
|
required,
|
|
5461
5490
|
valid: fieldErrors.length === 0,
|
|
5491
|
+
isSeverityError: false,
|
|
5462
5492
|
errors: fieldErrors,
|
|
5463
|
-
validators: this.describeFieldValidators(field, visible, required)
|
|
5493
|
+
validators: this.describeFieldValidators(field, visible, required, fieldErrors)
|
|
5464
5494
|
};
|
|
5495
|
+
states[field.name].isSeverityError = states[field.name].validators.some(validator => validator.severity === 'error' && validator.valid === false);
|
|
5465
5496
|
}
|
|
5466
5497
|
return states;
|
|
5467
5498
|
}
|
|
5468
|
-
describeFieldValidators(field, visible, required) {
|
|
5499
|
+
describeFieldValidators(field, visible, required, fieldErrors) {
|
|
5469
5500
|
const validators = [];
|
|
5470
5501
|
const value = this.engine?.getValue(field.name);
|
|
5471
5502
|
const hasValue = !this.isValidationEmpty(value);
|
|
5503
|
+
const ruleOutcomes = this.getRuleOutcomes(field);
|
|
5504
|
+
const requiredSeverity = ruleOutcomes.some(outcome => outcome.rule.severity === 'error' && outcome.nextAction === 'required');
|
|
5472
5505
|
if (this.hasRequiredValidation(field) || required) {
|
|
5506
|
+
const message = 'This field is required.';
|
|
5473
5507
|
validators.push({
|
|
5474
5508
|
name: 'required',
|
|
5475
5509
|
source: 'required',
|
|
5476
5510
|
active: visible && required,
|
|
5477
|
-
|
|
5511
|
+
valid: !fieldErrors.includes(message),
|
|
5512
|
+
message,
|
|
5513
|
+
...(requiredSeverity ? { severity: 'error' } : {})
|
|
5478
5514
|
});
|
|
5479
5515
|
}
|
|
5480
5516
|
if (field.html5?.minLength !== undefined) {
|
|
5517
|
+
const message = `Minimum length is ${field.html5.minLength}.`;
|
|
5481
5518
|
validators.push({
|
|
5482
5519
|
name: 'minLength',
|
|
5483
5520
|
source: 'html5',
|
|
5484
5521
|
active: visible && hasValue,
|
|
5485
|
-
|
|
5522
|
+
valid: !fieldErrors.includes(message),
|
|
5523
|
+
value: field.html5.minLength,
|
|
5524
|
+
message
|
|
5486
5525
|
});
|
|
5487
5526
|
}
|
|
5488
5527
|
if (field.html5?.maxLength !== undefined) {
|
|
5528
|
+
const message = `Maximum length is ${field.html5.maxLength}.`;
|
|
5489
5529
|
validators.push({
|
|
5490
5530
|
name: 'maxLength',
|
|
5491
5531
|
source: 'html5',
|
|
5492
5532
|
active: visible && hasValue,
|
|
5493
|
-
|
|
5533
|
+
valid: !fieldErrors.includes(message),
|
|
5534
|
+
value: field.html5.maxLength,
|
|
5535
|
+
message
|
|
5494
5536
|
});
|
|
5495
5537
|
}
|
|
5496
5538
|
if (field.html5?.min !== undefined) {
|
|
5539
|
+
const message = `Minimum value is ${field.html5.min}.`;
|
|
5497
5540
|
validators.push({
|
|
5498
5541
|
name: 'min',
|
|
5499
5542
|
source: 'html5',
|
|
5500
5543
|
active: visible && hasValue,
|
|
5501
|
-
|
|
5544
|
+
valid: !fieldErrors.includes(message),
|
|
5545
|
+
value: field.html5.min,
|
|
5546
|
+
message
|
|
5502
5547
|
});
|
|
5503
5548
|
}
|
|
5504
5549
|
if (field.html5?.max !== undefined) {
|
|
5550
|
+
const message = `Maximum value is ${field.html5.max}.`;
|
|
5505
5551
|
validators.push({
|
|
5506
5552
|
name: 'max',
|
|
5507
5553
|
source: 'html5',
|
|
5508
5554
|
active: visible && hasValue,
|
|
5509
|
-
|
|
5555
|
+
valid: !fieldErrors.includes(message),
|
|
5556
|
+
value: field.html5.max,
|
|
5557
|
+
message
|
|
5510
5558
|
});
|
|
5511
5559
|
}
|
|
5512
5560
|
if (field.html5?.pattern) {
|
|
5561
|
+
const message = 'Invalid format.';
|
|
5513
5562
|
validators.push({
|
|
5514
5563
|
name: 'pattern',
|
|
5515
5564
|
source: 'html5',
|
|
5516
5565
|
active: visible && hasValue,
|
|
5517
|
-
|
|
5566
|
+
valid: !fieldErrors.includes(message),
|
|
5567
|
+
value: field.html5.pattern,
|
|
5568
|
+
message
|
|
5518
5569
|
});
|
|
5519
5570
|
}
|
|
5520
|
-
for (const
|
|
5571
|
+
for (const outcome of ruleOutcomes) {
|
|
5572
|
+
const message = this.getRuleValidationMessage(outcome.rule);
|
|
5521
5573
|
validators.push({
|
|
5522
|
-
name: rule.
|
|
5523
|
-
source: '
|
|
5524
|
-
active:
|
|
5525
|
-
|
|
5526
|
-
|
|
5574
|
+
name: outcome.rule.name?.trim() || this.describeRuleName(outcome.rule),
|
|
5575
|
+
source: 'rule',
|
|
5576
|
+
active: true,
|
|
5577
|
+
valid: outcome.conditionMet || outcome.nextAction !== undefined,
|
|
5578
|
+
value: {
|
|
5579
|
+
action: outcome.rule.action,
|
|
5580
|
+
elseAction: outcome.rule.elseAction
|
|
5581
|
+
},
|
|
5582
|
+
message,
|
|
5583
|
+
...(outcome.rule.severity ? { severity: outcome.rule.severity } : {})
|
|
5527
5584
|
});
|
|
5528
5585
|
}
|
|
5529
5586
|
return validators;
|
|
@@ -5542,16 +5599,30 @@ class JsonFormRendererComponent {
|
|
|
5542
5599
|
}
|
|
5543
5600
|
return false;
|
|
5544
5601
|
}
|
|
5545
|
-
|
|
5546
|
-
if (!
|
|
5547
|
-
return
|
|
5548
|
-
try {
|
|
5549
|
-
const checkFn = new Function('form', `return ${rule.when}`);
|
|
5550
|
-
return checkFn(this.engine?.getValues() ?? {});
|
|
5602
|
+
getRuleOutcomes(field) {
|
|
5603
|
+
if (!field.rules?.length) {
|
|
5604
|
+
return [];
|
|
5551
5605
|
}
|
|
5552
|
-
|
|
5553
|
-
|
|
5606
|
+
const schema = this.engine?.getSchema() ?? this.schema;
|
|
5607
|
+
const formValues = this.engine?.getValues() ?? {};
|
|
5608
|
+
return field.rules.map(rule => {
|
|
5609
|
+
const conditionMet = this.ruleEvaluationService.evaluateRule(rule, formValues, schema?.fields ?? []);
|
|
5610
|
+
return {
|
|
5611
|
+
rule,
|
|
5612
|
+
conditionMet,
|
|
5613
|
+
nextAction: conditionMet ? rule.action : rule.elseAction
|
|
5614
|
+
};
|
|
5615
|
+
});
|
|
5616
|
+
}
|
|
5617
|
+
describeRuleName(rule) {
|
|
5618
|
+
return rule.action.charAt(0).toUpperCase() + rule.action.slice(1);
|
|
5619
|
+
}
|
|
5620
|
+
getRuleValidationMessage(rule) {
|
|
5621
|
+
const name = rule.name?.trim();
|
|
5622
|
+
if (name) {
|
|
5623
|
+
return name;
|
|
5554
5624
|
}
|
|
5625
|
+
return `Rule "${rule.action}" failed.`;
|
|
5555
5626
|
}
|
|
5556
5627
|
isValidationEmpty(value) {
|
|
5557
5628
|
return value === null
|
|
@@ -10271,13 +10342,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
10271
10342
|
class DynamicPropertiesComponent {
|
|
10272
10343
|
onPropertyChange;
|
|
10273
10344
|
designerCtx = inject(DesignerContext);
|
|
10274
|
-
validatorTypeOptions = [
|
|
10275
|
-
{ label: 'Built-in', value: 'builtin' },
|
|
10276
|
-
{ label: 'Expression', value: 'expression' }
|
|
10277
|
-
];
|
|
10278
|
-
builtinValidatorOptions = [
|
|
10279
|
-
{ label: 'Email', value: 'email' }
|
|
10280
|
-
];
|
|
10281
10345
|
get properties() {
|
|
10282
10346
|
if (!this.config)
|
|
10283
10347
|
return [];
|
|
@@ -10609,68 +10673,6 @@ class DynamicPropertiesComponent {
|
|
|
10609
10673
|
this.setValue(path, options);
|
|
10610
10674
|
}
|
|
10611
10675
|
}
|
|
10612
|
-
// Validators editor methods
|
|
10613
|
-
addValidator(path) {
|
|
10614
|
-
if (this.readOnly)
|
|
10615
|
-
return;
|
|
10616
|
-
const validators = [...(this.getValue(path) || [])];
|
|
10617
|
-
validators.push(this.createDefaultValidationRule());
|
|
10618
|
-
this.setValue(path, validators);
|
|
10619
|
-
this.handleFieldChange();
|
|
10620
|
-
}
|
|
10621
|
-
removeValidator(path, index) {
|
|
10622
|
-
if (this.readOnly)
|
|
10623
|
-
return;
|
|
10624
|
-
const validators = [...(this.getValue(path) || [])];
|
|
10625
|
-
validators.splice(index, 1);
|
|
10626
|
-
this.setValue(path, validators);
|
|
10627
|
-
this.handleFieldChange();
|
|
10628
|
-
}
|
|
10629
|
-
updateValidator(path, index, field, value) {
|
|
10630
|
-
if (this.readOnly)
|
|
10631
|
-
return;
|
|
10632
|
-
const validators = [...(this.getValue(path) || [])];
|
|
10633
|
-
const currentRule = validators[index];
|
|
10634
|
-
if (!currentRule) {
|
|
10635
|
-
return;
|
|
10636
|
-
}
|
|
10637
|
-
let nextRule = { ...currentRule };
|
|
10638
|
-
if (field === 'type') {
|
|
10639
|
-
nextRule = value === 'expression'
|
|
10640
|
-
? {
|
|
10641
|
-
type: 'expression',
|
|
10642
|
-
expression: 'return true;',
|
|
10643
|
-
message: 'Validation failed.'
|
|
10644
|
-
}
|
|
10645
|
-
: this.createDefaultValidationRule();
|
|
10646
|
-
}
|
|
10647
|
-
else if (field === 'name') {
|
|
10648
|
-
nextRule.name = String(value);
|
|
10649
|
-
nextRule.message = this.defaultValidationMessage(nextRule);
|
|
10650
|
-
}
|
|
10651
|
-
else if (field === 'expression') {
|
|
10652
|
-
nextRule.expression = String(value);
|
|
10653
|
-
}
|
|
10654
|
-
else if (field === 'message') {
|
|
10655
|
-
nextRule.message = String(value);
|
|
10656
|
-
}
|
|
10657
|
-
validators[index] = nextRule;
|
|
10658
|
-
this.setValue(path, validators);
|
|
10659
|
-
this.handleFieldChange();
|
|
10660
|
-
}
|
|
10661
|
-
createDefaultValidationRule() {
|
|
10662
|
-
return {
|
|
10663
|
-
type: 'builtin',
|
|
10664
|
-
name: 'email',
|
|
10665
|
-
message: 'Enter a valid email address.'
|
|
10666
|
-
};
|
|
10667
|
-
}
|
|
10668
|
-
defaultValidationMessage(rule) {
|
|
10669
|
-
if (rule.type === 'builtin' && rule.name === 'email') {
|
|
10670
|
-
return 'Enter a valid email address.';
|
|
10671
|
-
}
|
|
10672
|
-
return 'Validation failed.';
|
|
10673
|
-
}
|
|
10674
10676
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DynamicPropertiesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10675
10677
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: DynamicPropertiesComponent, isStandalone: true, selector: "app-dynamic-properties", inputs: { onPropertyChange: "onPropertyChange", config: "config", readOnly: "readOnly", includeSections: "includeSections", excludeSections: "excludeSections", allFields: "allFields" }, outputs: { configChange: "configChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
10676
10678
|
<div class="dynamic-properties flex flex-col font-sans text-sm">
|
|
@@ -10813,51 +10815,6 @@ class DynamicPropertiesComponent {
|
|
|
10813
10815
|
</div>
|
|
10814
10816
|
</ui-field-wrapper>
|
|
10815
10817
|
|
|
10816
|
-
<!-- Validators Editor -->
|
|
10817
|
-
<ui-field-wrapper *ngIf="field.type === 'validators-editor'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
10818
|
-
<div class="w-full border border-gray-200 rounded-lg p-3 bg-gray-50">
|
|
10819
|
-
<div class="flex items-center justify-between mb-3">
|
|
10820
|
-
<span class="text-xs font-semibold text-gray-600 uppercase">{{field.label}}</span>
|
|
10821
|
-
<button type="button"
|
|
10822
|
-
(click)="addValidator(field.key)"
|
|
10823
|
-
class="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors">
|
|
10824
|
-
+
|
|
10825
|
-
</button>
|
|
10826
|
-
</div>
|
|
10827
|
-
<div class="space-y-2">
|
|
10828
|
-
<div *ngFor="let val of getValue(field.key) || []; let i = index" class="flex items-center gap-2 p-2 bg-white rounded border border-gray-200">
|
|
10829
|
-
<select [ngModel]="val.type || 'builtin'"
|
|
10830
|
-
(ngModelChange)="updateValidator(field.key, i, 'type', $event)"
|
|
10831
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
10832
|
-
<option *ngFor="let option of validatorTypeOptions" [value]="option.value">{{ option.label }}</option>
|
|
10833
|
-
</select>
|
|
10834
|
-
<select *ngIf="(val.type || 'builtin') === 'builtin'"
|
|
10835
|
-
[ngModel]="val.name || 'email'"
|
|
10836
|
-
(ngModelChange)="updateValidator(field.key, i, 'name', $event)"
|
|
10837
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
10838
|
-
<option *ngFor="let option of builtinValidatorOptions" [value]="option.value">{{ option.label }}</option>
|
|
10839
|
-
</select>
|
|
10840
|
-
<input *ngIf="val.type === 'expression'"
|
|
10841
|
-
type="text"
|
|
10842
|
-
[ngModel]="val.expression || ''"
|
|
10843
|
-
(ngModelChange)="updateValidator(field.key, i, 'expression', $event)"
|
|
10844
|
-
placeholder="return true;"
|
|
10845
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
10846
|
-
<input type="text"
|
|
10847
|
-
[ngModel]="val.message || ''"
|
|
10848
|
-
(ngModelChange)="updateValidator(field.key, i, 'message', $event)"
|
|
10849
|
-
placeholder="Validation message"
|
|
10850
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
10851
|
-
<button type="button"
|
|
10852
|
-
(click)="removeValidator(field.key, i)"
|
|
10853
|
-
class="w-8 h-8 flex items-center justify-center text-red-600 hover:bg-red-50 rounded transition-colors">
|
|
10854
|
-
<lucide-icon name="x" class="w-4 h-4"></lucide-icon>
|
|
10855
|
-
</button>
|
|
10856
|
-
</div>
|
|
10857
|
-
</div>
|
|
10858
|
-
</div>
|
|
10859
|
-
</ui-field-wrapper>
|
|
10860
|
-
|
|
10861
10818
|
<!-- Field Reference -->
|
|
10862
10819
|
<ui-field-wrapper *ngIf="field.type === 'field-reference'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
10863
10820
|
<select [ngModel]="getValue(field.key) || ''"
|
|
@@ -11106,51 +11063,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
11106
11063
|
</div>
|
|
11107
11064
|
</ui-field-wrapper>
|
|
11108
11065
|
|
|
11109
|
-
<!-- Validators Editor -->
|
|
11110
|
-
<ui-field-wrapper *ngIf="field.type === 'validators-editor'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
11111
|
-
<div class="w-full border border-gray-200 rounded-lg p-3 bg-gray-50">
|
|
11112
|
-
<div class="flex items-center justify-between mb-3">
|
|
11113
|
-
<span class="text-xs font-semibold text-gray-600 uppercase">{{field.label}}</span>
|
|
11114
|
-
<button type="button"
|
|
11115
|
-
(click)="addValidator(field.key)"
|
|
11116
|
-
class="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors">
|
|
11117
|
-
+
|
|
11118
|
-
</button>
|
|
11119
|
-
</div>
|
|
11120
|
-
<div class="space-y-2">
|
|
11121
|
-
<div *ngFor="let val of getValue(field.key) || []; let i = index" class="flex items-center gap-2 p-2 bg-white rounded border border-gray-200">
|
|
11122
|
-
<select [ngModel]="val.type || 'builtin'"
|
|
11123
|
-
(ngModelChange)="updateValidator(field.key, i, 'type', $event)"
|
|
11124
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
11125
|
-
<option *ngFor="let option of validatorTypeOptions" [value]="option.value">{{ option.label }}</option>
|
|
11126
|
-
</select>
|
|
11127
|
-
<select *ngIf="(val.type || 'builtin') === 'builtin'"
|
|
11128
|
-
[ngModel]="val.name || 'email'"
|
|
11129
|
-
(ngModelChange)="updateValidator(field.key, i, 'name', $event)"
|
|
11130
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
11131
|
-
<option *ngFor="let option of builtinValidatorOptions" [value]="option.value">{{ option.label }}</option>
|
|
11132
|
-
</select>
|
|
11133
|
-
<input *ngIf="val.type === 'expression'"
|
|
11134
|
-
type="text"
|
|
11135
|
-
[ngModel]="val.expression || ''"
|
|
11136
|
-
(ngModelChange)="updateValidator(field.key, i, 'expression', $event)"
|
|
11137
|
-
placeholder="return true;"
|
|
11138
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
11139
|
-
<input type="text"
|
|
11140
|
-
[ngModel]="val.message || ''"
|
|
11141
|
-
(ngModelChange)="updateValidator(field.key, i, 'message', $event)"
|
|
11142
|
-
placeholder="Validation message"
|
|
11143
|
-
class="flex-1 h-8 px-2 text-sm rounded border border-gray-300 bg-white focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
|
11144
|
-
<button type="button"
|
|
11145
|
-
(click)="removeValidator(field.key, i)"
|
|
11146
|
-
class="w-8 h-8 flex items-center justify-center text-red-600 hover:bg-red-50 rounded transition-colors">
|
|
11147
|
-
<lucide-icon name="x" class="w-4 h-4"></lucide-icon>
|
|
11148
|
-
</button>
|
|
11149
|
-
</div>
|
|
11150
|
-
</div>
|
|
11151
|
-
</div>
|
|
11152
|
-
</ui-field-wrapper>
|
|
11153
|
-
|
|
11154
11066
|
<!-- Field Reference -->
|
|
11155
11067
|
<ui-field-wrapper *ngIf="field.type === 'field-reference'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
11156
11068
|
<select [ngModel]="getValue(field.key) || ''"
|
|
@@ -15261,7 +15173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
15261
15173
|
type: Output
|
|
15262
15174
|
}] } });
|
|
15263
15175
|
|
|
15264
|
-
function parsePathSegments$
|
|
15176
|
+
function parsePathSegments$3(path) {
|
|
15265
15177
|
const segments = [];
|
|
15266
15178
|
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
15267
15179
|
let match;
|
|
@@ -15277,14 +15189,14 @@ function parsePathSegments$2(path) {
|
|
|
15277
15189
|
}
|
|
15278
15190
|
return segments;
|
|
15279
15191
|
}
|
|
15280
|
-
function resolvePathValue$
|
|
15192
|
+
function resolvePathValue$2(value, path) {
|
|
15281
15193
|
if (!path)
|
|
15282
15194
|
return value;
|
|
15283
15195
|
const normalized = path.trim();
|
|
15284
15196
|
if (!normalized)
|
|
15285
15197
|
return value;
|
|
15286
15198
|
let current = value;
|
|
15287
|
-
for (const segment of parsePathSegments$
|
|
15199
|
+
for (const segment of parsePathSegments$3(normalized)) {
|
|
15288
15200
|
if (current === null || current === undefined)
|
|
15289
15201
|
return undefined;
|
|
15290
15202
|
if (Array.isArray(current)) {
|
|
@@ -15301,7 +15213,7 @@ function resolvePathValue$1(value, path) {
|
|
|
15301
15213
|
return current;
|
|
15302
15214
|
}
|
|
15303
15215
|
function assignPathValue(target, path, value) {
|
|
15304
|
-
const segments = parsePathSegments$
|
|
15216
|
+
const segments = parsePathSegments$3(path);
|
|
15305
15217
|
if (!segments.length) {
|
|
15306
15218
|
return;
|
|
15307
15219
|
}
|
|
@@ -15437,7 +15349,6 @@ class DataPanelComponent {
|
|
|
15437
15349
|
selectionFieldId;
|
|
15438
15350
|
selectionMatchPath;
|
|
15439
15351
|
childRowsPath;
|
|
15440
|
-
formatNumericOptionLabels = false;
|
|
15441
15352
|
optionLabelPrefixPath;
|
|
15442
15353
|
rootPathOptions = [];
|
|
15443
15354
|
rowPathOptions = [];
|
|
@@ -15679,7 +15590,6 @@ class DataPanelComponent {
|
|
|
15679
15590
|
this.selectionFieldId = undefined;
|
|
15680
15591
|
this.selectionMatchPath = undefined;
|
|
15681
15592
|
this.childRowsPath = undefined;
|
|
15682
|
-
this.formatNumericOptionLabels = false;
|
|
15683
15593
|
this.optionLabelPrefixPath = undefined;
|
|
15684
15594
|
this.rootPathOptions = [];
|
|
15685
15595
|
this.rowPathOptions = [];
|
|
@@ -15721,7 +15631,6 @@ class DataPanelComponent {
|
|
|
15721
15631
|
this.selectionFieldId = d.selectionFieldId;
|
|
15722
15632
|
this.selectionMatchPath = d.selectionMatchPath;
|
|
15723
15633
|
this.childRowsPath = d.childRowsPath;
|
|
15724
|
-
this.formatNumericOptionLabels = d.formatNumericOptionLabels === true;
|
|
15725
15634
|
this.optionLabelPrefixPath = d.optionLabelPrefixPath;
|
|
15726
15635
|
// Search
|
|
15727
15636
|
this.searchEnabled = !!d.searchEnabled;
|
|
@@ -15774,10 +15683,7 @@ class DataPanelComponent {
|
|
|
15774
15683
|
labelKey: this.sourceType === 'source' ? this.labelKey : undefined,
|
|
15775
15684
|
valueKey: this.sourceType === 'source' ? this.valueKey : undefined,
|
|
15776
15685
|
rowsPath: this.sourceType === 'source' ? this.normalizedRowsPath() : undefined,
|
|
15777
|
-
|
|
15778
|
-
? this.formatNumericOptionLabels
|
|
15779
|
-
: undefined,
|
|
15780
|
-
optionLabelPrefixPath: this.shouldPersistOptionLabelFormatting()
|
|
15686
|
+
optionLabelPrefixPath: this.shouldPersistOptionLabelPrefix()
|
|
15781
15687
|
? this.optionLabelPrefixPath
|
|
15782
15688
|
: undefined,
|
|
15783
15689
|
rowSelectionMode: this.sourceType === 'source' && this.bindingShape === 'scalar' && this.rowSelectionMode === 'selected'
|
|
@@ -15896,9 +15802,6 @@ class DataPanelComponent {
|
|
|
15896
15802
|
&& this.bindingShape === 'scalar'
|
|
15897
15803
|
&& (this.widgetType === 'text' || this.widgetType === 'number');
|
|
15898
15804
|
}
|
|
15899
|
-
supportsNumericDisplayFormatting() {
|
|
15900
|
-
return this.widgetType === 'select' || this.widgetType === 'number';
|
|
15901
|
-
}
|
|
15902
15805
|
displayFormattingTitle() {
|
|
15903
15806
|
return this.widgetType === 'select' ? 'Amount Display' : 'Field Display';
|
|
15904
15807
|
}
|
|
@@ -15907,15 +15810,10 @@ class DataPanelComponent {
|
|
|
15907
15810
|
return 'Format the visible dropdown label without changing the stored option value.';
|
|
15908
15811
|
}
|
|
15909
15812
|
if (this.widgetType === 'number') {
|
|
15910
|
-
return 'Show a fixed prefix
|
|
15813
|
+
return 'Show a fixed prefix in the visible field value without changing the stored number.';
|
|
15911
15814
|
}
|
|
15912
15815
|
return 'Show a fixed prefix beside the editable value without changing the stored field value.';
|
|
15913
15816
|
}
|
|
15914
|
-
numericDisplayFormattingLabel() {
|
|
15915
|
-
return this.widgetType === 'select'
|
|
15916
|
-
? 'Show thousand separators for numeric labels'
|
|
15917
|
-
: 'Show thousand separators for numeric values';
|
|
15918
|
-
}
|
|
15919
15817
|
showStaticOptionsEditor() {
|
|
15920
15818
|
return this.sourceType === 'static' && this.widgetType !== 'table' && this.usesOptionMapping();
|
|
15921
15819
|
}
|
|
@@ -15944,12 +15842,12 @@ class DataPanelComponent {
|
|
|
15944
15842
|
}
|
|
15945
15843
|
getPreviewLabel(row) {
|
|
15946
15844
|
const key = this.labelKey || 'label';
|
|
15947
|
-
const value = resolvePathValue$
|
|
15845
|
+
const value = resolvePathValue$2(row, key);
|
|
15948
15846
|
return value === undefined || value === null || value === '' ? '(no label)' : String(value);
|
|
15949
15847
|
}
|
|
15950
15848
|
getPreviewValue(row) {
|
|
15951
15849
|
const key = this.valueKey || 'value';
|
|
15952
|
-
const value = resolvePathValue$
|
|
15850
|
+
const value = resolvePathValue$2(row, key);
|
|
15953
15851
|
return value === undefined || value === null ? '' : String(value);
|
|
15954
15852
|
}
|
|
15955
15853
|
availableRootPaths() {
|
|
@@ -15966,7 +15864,7 @@ class DataPanelComponent {
|
|
|
15966
15864
|
const sample = this.extractPreviewRows(this.previewRows, this.effectiveRowsPath())[0];
|
|
15967
15865
|
return sample ? collectArrayPaths(sample) : [];
|
|
15968
15866
|
}
|
|
15969
|
-
|
|
15867
|
+
shouldPersistOptionLabelPrefix() {
|
|
15970
15868
|
if (this.widgetType === 'select' && this.usesOptionMapping()) {
|
|
15971
15869
|
return true;
|
|
15972
15870
|
}
|
|
@@ -15982,7 +15880,7 @@ class DataPanelComponent {
|
|
|
15982
15880
|
return normalized ? normalized : 'defaultValue';
|
|
15983
15881
|
}
|
|
15984
15882
|
readScalarTargetValue() {
|
|
15985
|
-
const resolved = resolvePathValue$
|
|
15883
|
+
const resolved = resolvePathValue$2(this.config, this.scalarTargetPath());
|
|
15986
15884
|
if (resolved !== undefined) {
|
|
15987
15885
|
return resolved;
|
|
15988
15886
|
}
|
|
@@ -16005,7 +15903,7 @@ class DataPanelComponent {
|
|
|
16005
15903
|
}
|
|
16006
15904
|
const flattened = [];
|
|
16007
15905
|
for (const row of rows) {
|
|
16008
|
-
const resolved = resolvePathValue$
|
|
15906
|
+
const resolved = resolvePathValue$2(row, normalizedPath);
|
|
16009
15907
|
if (Array.isArray(resolved)) {
|
|
16010
15908
|
flattened.push(...resolved);
|
|
16011
15909
|
continue;
|
|
@@ -16297,15 +16195,6 @@ class DataPanelComponent {
|
|
|
16297
16195
|
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16298
16196
|
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16299
16197
|
|
|
16300
|
-
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700" *ngIf="supportsNumericDisplayFormatting()">
|
|
16301
|
-
<input
|
|
16302
|
-
type="checkbox"
|
|
16303
|
-
[checked]="formatNumericOptionLabels"
|
|
16304
|
-
(change)="formatNumericOptionLabels = $any($event.target).checked; emitChange()"
|
|
16305
|
-
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
16306
|
-
<span>{{ numericDisplayFormattingLabel() }}</span>
|
|
16307
|
-
</label>
|
|
16308
|
-
|
|
16309
16198
|
<div class="mt-3 flex flex-col gap-1">
|
|
16310
16199
|
<label class="text-xs font-medium text-gray-500">Prefix Key</label>
|
|
16311
16200
|
<input
|
|
@@ -16916,15 +16805,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
16916
16805
|
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16917
16806
|
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16918
16807
|
|
|
16919
|
-
<label class="mt-3 flex items-center gap-2 text-sm text-gray-700" *ngIf="supportsNumericDisplayFormatting()">
|
|
16920
|
-
<input
|
|
16921
|
-
type="checkbox"
|
|
16922
|
-
[checked]="formatNumericOptionLabels"
|
|
16923
|
-
(change)="formatNumericOptionLabels = $any($event.target).checked; emitChange()"
|
|
16924
|
-
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
16925
|
-
<span>{{ numericDisplayFormattingLabel() }}</span>
|
|
16926
|
-
</label>
|
|
16927
|
-
|
|
16928
16808
|
<div class="mt-3 flex flex-col gap-1">
|
|
16929
16809
|
<label class="text-xs font-medium text-gray-500">Prefix Key</label>
|
|
16930
16810
|
<input
|
|
@@ -17866,7 +17746,7 @@ class RulesPanelComponent {
|
|
|
17866
17746
|
<div class="flex flex-col gap-2">
|
|
17867
17747
|
<div class="flex items-center gap-2 bg-amber-50 p-2 rounded-md border border-amber-100">
|
|
17868
17748
|
<span class="text-xs font-semibold text-amber-700 uppercase">Severity</span>
|
|
17869
|
-
<span class="text-xs text-amber-800 italic">
|
|
17749
|
+
<span class="text-xs text-amber-800 italic">Error severity is emitted in runtime validation; warn stays informational.</span>
|
|
17870
17750
|
</div>
|
|
17871
17751
|
|
|
17872
17752
|
<div class="flex items-center gap-2">
|
|
@@ -17988,7 +17868,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
17988
17868
|
<div class="flex flex-col gap-2">
|
|
17989
17869
|
<div class="flex items-center gap-2 bg-amber-50 p-2 rounded-md border border-amber-100">
|
|
17990
17870
|
<span class="text-xs font-semibold text-amber-700 uppercase">Severity</span>
|
|
17991
|
-
<span class="text-xs text-amber-800 italic">
|
|
17871
|
+
<span class="text-xs text-amber-800 italic">Error severity is emitted in runtime validation; warn stays informational.</span>
|
|
17992
17872
|
</div>
|
|
17993
17873
|
|
|
17994
17874
|
<div class="flex items-center gap-2">
|
|
@@ -20255,13 +20135,13 @@ async function updateFieldSettings(state, args, widgetDefs = []) {
|
|
|
20255
20135
|
updates[key] = value;
|
|
20256
20136
|
}
|
|
20257
20137
|
}
|
|
20138
|
+
const html5Patch = {};
|
|
20258
20139
|
if (typeof a['disabled'] === 'boolean') {
|
|
20259
|
-
|
|
20140
|
+
html5Patch['disabled'] = a['disabled'];
|
|
20260
20141
|
}
|
|
20261
20142
|
if (typeof a['readonly'] === 'boolean') {
|
|
20262
|
-
|
|
20143
|
+
html5Patch['readonly'] = a['readonly'];
|
|
20263
20144
|
}
|
|
20264
|
-
const html5Patch = {};
|
|
20265
20145
|
const html5Keys = ['required', 'min', 'max', 'step', 'minLength', 'maxLength', 'pattern'];
|
|
20266
20146
|
for (const key of html5Keys) {
|
|
20267
20147
|
if (typeof a[key] !== 'undefined') {
|
|
@@ -22071,7 +21951,7 @@ const DATA_SOURCES_TEMPLATE = {
|
|
|
22071
21951
|
"type": "text",
|
|
22072
21952
|
"label": "Selected country code",
|
|
22073
21953
|
"placeholder": "Auto-filled",
|
|
22074
|
-
"readonly": true,
|
|
21954
|
+
"html5": { "readonly": true },
|
|
22075
21955
|
"helpText": "Updated by an event binding on the Country field."
|
|
22076
21956
|
},
|
|
22077
21957
|
{
|
|
@@ -22477,8 +22357,8 @@ const TRANSACTION_KYC_REVIEW_TEMPLATE = {
|
|
|
22477
22357
|
"name": "clientDisplay",
|
|
22478
22358
|
"type": "text",
|
|
22479
22359
|
"label": "Client",
|
|
22480
|
-
"readonly": true,
|
|
22481
22360
|
"html5": {
|
|
22361
|
+
"readonly": true,
|
|
22482
22362
|
"required": false
|
|
22483
22363
|
},
|
|
22484
22364
|
"rules": [
|
|
@@ -22524,7 +22404,7 @@ const TRANSACTION_KYC_REVIEW_TEMPLATE = {
|
|
|
22524
22404
|
"type": "text",
|
|
22525
22405
|
"label": "Balance",
|
|
22526
22406
|
"defaultValue": "USD 24,580.00",
|
|
22527
|
-
"readonly": true,
|
|
22407
|
+
"html5": { "readonly": true },
|
|
22528
22408
|
"rules": [
|
|
22529
22409
|
{
|
|
22530
22410
|
"id": "rule_balance_visible",
|
|
@@ -23292,7 +23172,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_TWO = {
|
|
|
23292
23172
|
"name": "summaryCountryCode",
|
|
23293
23173
|
"type": "text",
|
|
23294
23174
|
"label": "Country Code",
|
|
23295
|
-
"readonly": true,
|
|
23175
|
+
"html5": { "readonly": true },
|
|
23296
23176
|
"dataConfig": {
|
|
23297
23177
|
"type": "source",
|
|
23298
23178
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -23497,7 +23377,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_THREE = {
|
|
|
23497
23377
|
"name": "summaryCurrency",
|
|
23498
23378
|
"type": "text",
|
|
23499
23379
|
"label": "Currency",
|
|
23500
|
-
"readonly": true,
|
|
23380
|
+
"html5": { "readonly": true },
|
|
23501
23381
|
"dataConfig": {
|
|
23502
23382
|
"type": "source",
|
|
23503
23383
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -23510,7 +23390,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_THREE = {
|
|
|
23510
23390
|
"name": "summaryTimezone",
|
|
23511
23391
|
"type": "text",
|
|
23512
23392
|
"label": "Timezone",
|
|
23513
|
-
"readonly": true,
|
|
23393
|
+
"html5": { "readonly": true },
|
|
23514
23394
|
"dataConfig": {
|
|
23515
23395
|
"type": "source",
|
|
23516
23396
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -31742,7 +31622,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
31742
31622
|
}]
|
|
31743
31623
|
}] });
|
|
31744
31624
|
|
|
31745
|
-
function parsePathSegments$
|
|
31625
|
+
function parsePathSegments$2(path) {
|
|
31746
31626
|
const segments = [];
|
|
31747
31627
|
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
31748
31628
|
let match;
|
|
@@ -31758,14 +31638,14 @@ function parsePathSegments$1(path) {
|
|
|
31758
31638
|
}
|
|
31759
31639
|
return segments;
|
|
31760
31640
|
}
|
|
31761
|
-
function resolvePathValue(value, path) {
|
|
31641
|
+
function resolvePathValue$1(value, path) {
|
|
31762
31642
|
if (!path)
|
|
31763
31643
|
return value;
|
|
31764
31644
|
const normalizedPath = path.trim();
|
|
31765
31645
|
if (!normalizedPath)
|
|
31766
31646
|
return value;
|
|
31767
31647
|
let current = value;
|
|
31768
|
-
for (const segment of parsePathSegments$
|
|
31648
|
+
for (const segment of parsePathSegments$2(normalizedPath)) {
|
|
31769
31649
|
if (current === null || current === undefined) {
|
|
31770
31650
|
return undefined;
|
|
31771
31651
|
}
|
|
@@ -31789,7 +31669,7 @@ function hasPathSyntax(path) {
|
|
|
31789
31669
|
return false;
|
|
31790
31670
|
return path.includes('.') || path.includes('[');
|
|
31791
31671
|
}
|
|
31792
|
-
function valuesMatch(left, right) {
|
|
31672
|
+
function valuesMatch$1(left, right) {
|
|
31793
31673
|
if (Object.is(left, right))
|
|
31794
31674
|
return true;
|
|
31795
31675
|
if (left === undefined || left === null || right === undefined || right === null)
|
|
@@ -31845,8 +31725,8 @@ class DataProvider {
|
|
|
31845
31725
|
if (query.sort && query.sort.length > 0) {
|
|
31846
31726
|
rows = [...rows].sort((a, b) => {
|
|
31847
31727
|
for (const s of query.sort) {
|
|
31848
|
-
const valA = resolvePathValue(a, s.column);
|
|
31849
|
-
const valB = resolvePathValue(b, s.column);
|
|
31728
|
+
const valA = resolvePathValue$1(a, s.column);
|
|
31729
|
+
const valB = resolvePathValue$1(b, s.column);
|
|
31850
31730
|
if (valA === valB)
|
|
31851
31731
|
continue;
|
|
31852
31732
|
const result = compareSortableValues(valA, valB);
|
|
@@ -32006,12 +31886,12 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32006
31886
|
}
|
|
32007
31887
|
const row = context.row;
|
|
32008
31888
|
const resolvedPath = cfg.valueKey;
|
|
32009
|
-
const resolvedValue = resolvePathValue(row, resolvedPath);
|
|
31889
|
+
const resolvedValue = resolvePathValue$1(row, resolvedPath);
|
|
32010
31890
|
if (resolvedPath && resolvedValue !== undefined) {
|
|
32011
31891
|
return resolvedValue;
|
|
32012
31892
|
}
|
|
32013
|
-
if (resolvePathValue(row, 'value') !== undefined) {
|
|
32014
|
-
return resolvePathValue(row, 'value');
|
|
31893
|
+
if (resolvePathValue$1(row, 'value') !== undefined) {
|
|
31894
|
+
return resolvePathValue$1(row, 'value');
|
|
32015
31895
|
}
|
|
32016
31896
|
return row;
|
|
32017
31897
|
}
|
|
@@ -32028,7 +31908,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32028
31908
|
for (const candidate of [context.row, context.parentRow, context.sourceRow]) {
|
|
32029
31909
|
if (!candidate)
|
|
32030
31910
|
continue;
|
|
32031
|
-
const resolved = resolvePathValue(candidate, prefixPath);
|
|
31911
|
+
const resolved = resolvePathValue$1(candidate, prefixPath);
|
|
32032
31912
|
const value = toDisplayText(resolved);
|
|
32033
31913
|
if (value) {
|
|
32034
31914
|
return value;
|
|
@@ -32131,7 +32011,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32131
32011
|
}
|
|
32132
32012
|
const flattened = [];
|
|
32133
32013
|
for (const row of rows) {
|
|
32134
|
-
const resolved = resolvePathValue(row, normalizedPath);
|
|
32014
|
+
const resolved = resolvePathValue$1(row, normalizedPath);
|
|
32135
32015
|
if (Array.isArray(resolved)) {
|
|
32136
32016
|
for (const entry of resolved) {
|
|
32137
32017
|
flattened.push({
|
|
@@ -32159,7 +32039,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32159
32039
|
}
|
|
32160
32040
|
const flattened = [];
|
|
32161
32041
|
for (const row of rows) {
|
|
32162
|
-
const resolved = resolvePathValue(row, normalizedPath);
|
|
32042
|
+
const resolved = resolvePathValue$1(row, normalizedPath);
|
|
32163
32043
|
if (Array.isArray(resolved)) {
|
|
32164
32044
|
for (const entry of resolved) {
|
|
32165
32045
|
flattened.push(this.toRowRecord(entry));
|
|
@@ -32187,7 +32067,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32187
32067
|
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32188
32068
|
return undefined;
|
|
32189
32069
|
}
|
|
32190
|
-
return rows.find(row => valuesMatch(resolvePathValue(row, cfg.selectionMatchPath), selectorValue));
|
|
32070
|
+
return rows.find(row => valuesMatch$1(resolvePathValue$1(row, cfg.selectionMatchPath), selectorValue));
|
|
32191
32071
|
}
|
|
32192
32072
|
selectOptionContext(contexts, cfg, engine) {
|
|
32193
32073
|
if (contexts.length === 0)
|
|
@@ -32204,7 +32084,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32204
32084
|
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32205
32085
|
return undefined;
|
|
32206
32086
|
}
|
|
32207
|
-
return contexts.find(context => valuesMatch(resolvePathValue(context.row, cfg.selectionMatchPath), selectorValue));
|
|
32087
|
+
return contexts.find(context => valuesMatch$1(resolvePathValue$1(context.row, cfg.selectionMatchPath), selectorValue));
|
|
32208
32088
|
}
|
|
32209
32089
|
applyRowFilters(rows, filters, engine) {
|
|
32210
32090
|
if (!filters || filters.length === 0)
|
|
@@ -32221,7 +32101,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32221
32101
|
const expected = this.resolveFilterValue(filter, engine);
|
|
32222
32102
|
if (expected === undefined)
|
|
32223
32103
|
return true;
|
|
32224
|
-
const actual = resolvePathValue(row, filter.column);
|
|
32104
|
+
const actual = resolvePathValue$1(row, filter.column);
|
|
32225
32105
|
const val = expected;
|
|
32226
32106
|
switch (filter.op) {
|
|
32227
32107
|
case 'eq': return actual === val;
|
|
@@ -32293,17 +32173,16 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32293
32173
|
}
|
|
32294
32174
|
mapRowToOption(row, labelKey, valueKey) {
|
|
32295
32175
|
return {
|
|
32296
|
-
label: String(resolvePathValue(row, labelKey) ?? ''),
|
|
32297
|
-
value: this.toOptionValue(resolvePathValue(row, valueKey))
|
|
32176
|
+
label: String(resolvePathValue$1(row, labelKey) ?? ''),
|
|
32177
|
+
value: this.toOptionValue(resolvePathValue$1(row, valueKey))
|
|
32298
32178
|
};
|
|
32299
32179
|
}
|
|
32300
32180
|
mapContextToOption(context, labelKey, valueKey, cfg) {
|
|
32301
|
-
const rawLabel = String(resolvePathValue(context.row, labelKey) ?? '');
|
|
32302
32181
|
const prefix = this.resolveOptionLabelPrefix(context, cfg);
|
|
32303
|
-
const label = this.formatOptionLabel(rawLabel, cfg);
|
|
32304
32182
|
return {
|
|
32305
|
-
label:
|
|
32306
|
-
|
|
32183
|
+
label: String(resolvePathValue$1(context.row, labelKey) ?? ''),
|
|
32184
|
+
displayPrefix: prefix || undefined,
|
|
32185
|
+
value: this.toOptionValue(resolvePathValue$1(context.row, valueKey))
|
|
32307
32186
|
};
|
|
32308
32187
|
}
|
|
32309
32188
|
resolveOptionLabelPrefix(context, cfg) {
|
|
@@ -32314,7 +32193,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32314
32193
|
for (const candidate of [context.row, context.parentRow, context.sourceRow]) {
|
|
32315
32194
|
if (!candidate)
|
|
32316
32195
|
continue;
|
|
32317
|
-
const resolved = resolvePathValue(candidate, prefixPath);
|
|
32196
|
+
const resolved = resolvePathValue$1(candidate, prefixPath);
|
|
32318
32197
|
const value = toDisplayText(resolved);
|
|
32319
32198
|
if (value) {
|
|
32320
32199
|
return value;
|
|
@@ -32322,29 +32201,6 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32322
32201
|
}
|
|
32323
32202
|
return '';
|
|
32324
32203
|
}
|
|
32325
|
-
formatOptionLabel(label, cfg) {
|
|
32326
|
-
if (!cfg.formatNumericOptionLabels) {
|
|
32327
|
-
return label;
|
|
32328
|
-
}
|
|
32329
|
-
const trimmed = label.trim();
|
|
32330
|
-
if (!trimmed) {
|
|
32331
|
-
return label;
|
|
32332
|
-
}
|
|
32333
|
-
const normalized = trimmed.replace(/,/g, '');
|
|
32334
|
-
if (!/^-?\d+(\.\d+)?$/.test(normalized)) {
|
|
32335
|
-
return label;
|
|
32336
|
-
}
|
|
32337
|
-
const numericValue = Number(normalized);
|
|
32338
|
-
if (!Number.isFinite(numericValue)) {
|
|
32339
|
-
return label;
|
|
32340
|
-
}
|
|
32341
|
-
const fractionPart = normalized.split('.')[1];
|
|
32342
|
-
return new Intl.NumberFormat(undefined, {
|
|
32343
|
-
useGrouping: true,
|
|
32344
|
-
minimumFractionDigits: fractionPart?.length ?? 0,
|
|
32345
|
-
maximumFractionDigits: fractionPart?.length ?? 0
|
|
32346
|
-
}).format(numericValue);
|
|
32347
|
-
}
|
|
32348
32204
|
async getRuntimeOptions(field, engine) {
|
|
32349
32205
|
if (!engine)
|
|
32350
32206
|
return undefined;
|
|
@@ -32503,6 +32359,60 @@ function getHeadingClass(level) {
|
|
|
32503
32359
|
}
|
|
32504
32360
|
}
|
|
32505
32361
|
|
|
32362
|
+
function parsePathSegments$1(path) {
|
|
32363
|
+
const segments = [];
|
|
32364
|
+
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
32365
|
+
let match;
|
|
32366
|
+
while ((match = matcher.exec(path)) !== null) {
|
|
32367
|
+
const [, property, index] = match;
|
|
32368
|
+
if (property) {
|
|
32369
|
+
segments.push(property);
|
|
32370
|
+
continue;
|
|
32371
|
+
}
|
|
32372
|
+
if (index !== undefined) {
|
|
32373
|
+
segments.push(index);
|
|
32374
|
+
}
|
|
32375
|
+
}
|
|
32376
|
+
return segments;
|
|
32377
|
+
}
|
|
32378
|
+
function resolvePathValue(value, path) {
|
|
32379
|
+
if (!path)
|
|
32380
|
+
return value;
|
|
32381
|
+
const normalizedPath = path.trim();
|
|
32382
|
+
if (!normalizedPath)
|
|
32383
|
+
return value;
|
|
32384
|
+
let current = value;
|
|
32385
|
+
for (const segment of parsePathSegments$1(normalizedPath)) {
|
|
32386
|
+
if (current === null || current === undefined) {
|
|
32387
|
+
return undefined;
|
|
32388
|
+
}
|
|
32389
|
+
if (Array.isArray(current)) {
|
|
32390
|
+
const index = Number(segment);
|
|
32391
|
+
if (!Number.isInteger(index)) {
|
|
32392
|
+
return undefined;
|
|
32393
|
+
}
|
|
32394
|
+
current = current[index];
|
|
32395
|
+
continue;
|
|
32396
|
+
}
|
|
32397
|
+
if (typeof current !== 'object') {
|
|
32398
|
+
return undefined;
|
|
32399
|
+
}
|
|
32400
|
+
current = current[segment];
|
|
32401
|
+
}
|
|
32402
|
+
return current;
|
|
32403
|
+
}
|
|
32404
|
+
function valuesMatch(left, right) {
|
|
32405
|
+
if (Object.is(left, right))
|
|
32406
|
+
return true;
|
|
32407
|
+
if (left === undefined || left === null || right === undefined || right === null)
|
|
32408
|
+
return false;
|
|
32409
|
+
const leftIsPrimitive = typeof left === 'string' || typeof left === 'number' || typeof left === 'boolean';
|
|
32410
|
+
const rightIsPrimitive = typeof right === 'string' || typeof right === 'number' || typeof right === 'boolean';
|
|
32411
|
+
if (leftIsPrimitive && rightIsPrimitive) {
|
|
32412
|
+
return String(left) === String(right);
|
|
32413
|
+
}
|
|
32414
|
+
return false;
|
|
32415
|
+
}
|
|
32506
32416
|
class TextFieldWidgetComponent {
|
|
32507
32417
|
_config;
|
|
32508
32418
|
hasReceivedConfig = false;
|
|
@@ -32552,7 +32462,7 @@ class TextFieldWidgetComponent {
|
|
|
32552
32462
|
return this.config?.type === 'color';
|
|
32553
32463
|
}
|
|
32554
32464
|
usesFormattedNumberInput() {
|
|
32555
|
-
return this.config?.type === 'number' && this.config
|
|
32465
|
+
return this.config?.type === 'number' && usesFieldThousandSeparator(this.config);
|
|
32556
32466
|
}
|
|
32557
32467
|
hasDisplayPrefix() {
|
|
32558
32468
|
return !this.isTextarea() && !this.isColorField() && this.displayPrefix.trim().length > 0;
|
|
@@ -32609,7 +32519,7 @@ class TextFieldWidgetComponent {
|
|
|
32609
32519
|
const datasourceId = this.config?.dataConfig?.datasourceId;
|
|
32610
32520
|
if (!datasourceId || update.datasourceId !== datasourceId)
|
|
32611
32521
|
return;
|
|
32612
|
-
void this.refreshValueFromDataSource();
|
|
32522
|
+
void this.refreshValueFromDataSource(true);
|
|
32613
32523
|
});
|
|
32614
32524
|
}
|
|
32615
32525
|
this.engine.valueChanges$
|
|
@@ -32617,7 +32527,7 @@ class TextFieldWidgetComponent {
|
|
|
32617
32527
|
.subscribe(values => {
|
|
32618
32528
|
this.syncEnabledState();
|
|
32619
32529
|
if (this.haveDependencyValuesChanged(values)) {
|
|
32620
|
-
void this.refreshValueFromDataSource();
|
|
32530
|
+
void this.refreshValueFromDataSource(true);
|
|
32621
32531
|
}
|
|
32622
32532
|
});
|
|
32623
32533
|
// Listen for submit attempts to show validation errors
|
|
@@ -32721,7 +32631,7 @@ class TextFieldWidgetComponent {
|
|
|
32721
32631
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
32722
32632
|
}
|
|
32723
32633
|
get enabled() {
|
|
32724
|
-
if (this.config
|
|
32634
|
+
if (isFieldDisabled(this.config))
|
|
32725
32635
|
return false;
|
|
32726
32636
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
32727
32637
|
}
|
|
@@ -32747,14 +32657,23 @@ class TextFieldWidgetComponent {
|
|
|
32747
32657
|
this.control.disable({ emitEvent: false });
|
|
32748
32658
|
}
|
|
32749
32659
|
}
|
|
32750
|
-
async refreshValueFromDataSource() {
|
|
32660
|
+
async refreshValueFromDataSource(clearWhenMissing = false) {
|
|
32751
32661
|
if (!this.dataProvider || !this.config.dataConfig)
|
|
32752
32662
|
return;
|
|
32753
32663
|
try {
|
|
32664
|
+
if (clearWhenMissing && !(await this.hasSelectedRowMatch())) {
|
|
32665
|
+
this.clearResolvedValue();
|
|
32666
|
+
return;
|
|
32667
|
+
}
|
|
32754
32668
|
const val = await this.dataProvider.getValue(this.config, this.engine);
|
|
32755
32669
|
this.displayPrefix = await this.dataProvider.getValueDisplayPrefix(this.config, this.engine);
|
|
32756
|
-
if (val === undefined || val === null)
|
|
32670
|
+
if (val === undefined || val === null) {
|
|
32671
|
+
if (!clearWhenMissing) {
|
|
32672
|
+
return;
|
|
32673
|
+
}
|
|
32674
|
+
this.clearResolvedValue();
|
|
32757
32675
|
return;
|
|
32676
|
+
}
|
|
32758
32677
|
this.control.setValue(val, { emitEvent: false });
|
|
32759
32678
|
this.syncFormattedNumberValue();
|
|
32760
32679
|
if (this.engine) {
|
|
@@ -32765,12 +32684,48 @@ class TextFieldWidgetComponent {
|
|
|
32765
32684
|
// Ignore failed datasource refreshes; field remains editable.
|
|
32766
32685
|
}
|
|
32767
32686
|
}
|
|
32687
|
+
clearResolvedValue() {
|
|
32688
|
+
this.displayPrefix = '';
|
|
32689
|
+
this.control.setValue(null, { emitEvent: false });
|
|
32690
|
+
this.syncFormattedNumberValue();
|
|
32691
|
+
if (this.engine) {
|
|
32692
|
+
this.engine.setValue(this.config.name, null);
|
|
32693
|
+
}
|
|
32694
|
+
}
|
|
32695
|
+
async hasSelectedRowMatch() {
|
|
32696
|
+
const cfg = this.config.dataConfig;
|
|
32697
|
+
if (!cfg
|
|
32698
|
+
|| cfg.rowSelectionMode !== 'selected'
|
|
32699
|
+
|| !cfg.selectionFieldId
|
|
32700
|
+
|| !cfg.selectionMatchPath
|
|
32701
|
+
|| !this.engine) {
|
|
32702
|
+
return true;
|
|
32703
|
+
}
|
|
32704
|
+
const selectorField = this.engine.getSchema().fields.find(field => field.id === cfg.selectionFieldId);
|
|
32705
|
+
if (!selectorField) {
|
|
32706
|
+
return false;
|
|
32707
|
+
}
|
|
32708
|
+
const selectorValue = this.engine.getValue(selectorField.name);
|
|
32709
|
+
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32710
|
+
return false;
|
|
32711
|
+
}
|
|
32712
|
+
const rows = await this.dataProvider.getList(this.config, this.engine);
|
|
32713
|
+
return rows.some(row => valuesMatch(resolvePathValue(row, cfg.selectionMatchPath), selectorValue));
|
|
32714
|
+
}
|
|
32768
32715
|
getDataConfigSignature(config) {
|
|
32769
32716
|
if (!config)
|
|
32770
32717
|
return '';
|
|
32771
32718
|
const dataConfig = config.dataConfig;
|
|
32772
32719
|
if (!dataConfig) {
|
|
32773
|
-
return
|
|
32720
|
+
return [
|
|
32721
|
+
config.id,
|
|
32722
|
+
config.name,
|
|
32723
|
+
config.type,
|
|
32724
|
+
String(config.html5?.readonly ?? ''),
|
|
32725
|
+
String(config.html5?.disabled ?? ''),
|
|
32726
|
+
String(config.useThousandSeparator ?? ''),
|
|
32727
|
+
'no-data-config'
|
|
32728
|
+
].join('::');
|
|
32774
32729
|
}
|
|
32775
32730
|
const sourceKey = dataConfig.type === 'source' || dataConfig.type === 'global' || dataConfig.type === 'api'
|
|
32776
32731
|
? String(dataConfig.datasourceId ?? '')
|
|
@@ -32778,16 +32733,18 @@ class TextFieldWidgetComponent {
|
|
|
32778
32733
|
return [
|
|
32779
32734
|
config.id,
|
|
32780
32735
|
config.name,
|
|
32736
|
+
String(config.html5?.readonly ?? ''),
|
|
32737
|
+
String(config.html5?.disabled ?? ''),
|
|
32781
32738
|
dataConfig.type ?? '',
|
|
32782
32739
|
sourceKey,
|
|
32783
32740
|
String(dataConfig.valueKey ?? ''),
|
|
32784
32741
|
String(dataConfig.rowsPath ?? ''),
|
|
32785
|
-
String(dataConfig.formatNumericOptionLabels ?? ''),
|
|
32786
32742
|
String(dataConfig.optionLabelPrefixPath ?? ''),
|
|
32787
32743
|
String(dataConfig.optionLabelPrefixFieldId ?? ''),
|
|
32788
32744
|
String(dataConfig.rowSelectionMode ?? ''),
|
|
32789
32745
|
String(dataConfig.selectionFieldId ?? ''),
|
|
32790
32746
|
String(dataConfig.selectionMatchPath ?? ''),
|
|
32747
|
+
String(config.useThousandSeparator ?? ''),
|
|
32791
32748
|
(dataConfig.filters ?? []).map(filter => `${filter.column}:${filter.valueFrom ?? ''}:${filter.fieldId ?? ''}`).join('|')
|
|
32792
32749
|
].join('::');
|
|
32793
32750
|
}
|
|
@@ -32922,7 +32879,7 @@ class TextFieldWidgetComponent {
|
|
|
32922
32879
|
(blur)="onBlur()"
|
|
32923
32880
|
(mouseenter)="onMouseEnter()"
|
|
32924
32881
|
(mouseleave)="onMouseLeave()"
|
|
32925
|
-
[readonly]="config.readonly"
|
|
32882
|
+
[readonly]="config.html5?.readonly"
|
|
32926
32883
|
[attr.aria-required]="required"
|
|
32927
32884
|
[attr.aria-invalid]="!!error"
|
|
32928
32885
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -32943,7 +32900,7 @@ class TextFieldWidgetComponent {
|
|
|
32943
32900
|
(blur)="onBlur()"
|
|
32944
32901
|
(mouseenter)="onMouseEnter()"
|
|
32945
32902
|
(mouseleave)="onMouseLeave()"
|
|
32946
|
-
[readonly]="config.readonly"
|
|
32903
|
+
[readonly]="config.html5?.readonly"
|
|
32947
32904
|
[attr.aria-required]="required"
|
|
32948
32905
|
[attr.aria-invalid]="!!error"
|
|
32949
32906
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -32955,7 +32912,7 @@ class TextFieldWidgetComponent {
|
|
|
32955
32912
|
[cpAlphaChannel]="'disabled'"
|
|
32956
32913
|
[cpOutputFormat]="'hex'"
|
|
32957
32914
|
[cpFallbackColor]="'#000000'"
|
|
32958
|
-
[cpDisabled]="config.readonly || !enabled"
|
|
32915
|
+
[cpDisabled]="config.html5?.readonly || !enabled"
|
|
32959
32916
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
32960
32917
|
} @else if (usesFormattedNumberInput()) {
|
|
32961
32918
|
@if (hasDisplayPrefix()) {
|
|
@@ -32977,7 +32934,7 @@ class TextFieldWidgetComponent {
|
|
|
32977
32934
|
(blur)="onBlur()"
|
|
32978
32935
|
(mouseenter)="onMouseEnter()"
|
|
32979
32936
|
(mouseleave)="onMouseLeave()"
|
|
32980
|
-
[readonly]="config.readonly"
|
|
32937
|
+
[readonly]="config.html5?.readonly"
|
|
32981
32938
|
[disabled]="control.disabled"
|
|
32982
32939
|
[attr.aria-required]="required"
|
|
32983
32940
|
[attr.aria-invalid]="!!error"
|
|
@@ -33007,7 +32964,7 @@ class TextFieldWidgetComponent {
|
|
|
33007
32964
|
(blur)="onBlur()"
|
|
33008
32965
|
(mouseenter)="onMouseEnter()"
|
|
33009
32966
|
(mouseleave)="onMouseLeave()"
|
|
33010
|
-
[readonly]="config.readonly"
|
|
32967
|
+
[readonly]="config.html5?.readonly"
|
|
33011
32968
|
[attr.aria-required]="required"
|
|
33012
32969
|
[attr.aria-invalid]="!!error"
|
|
33013
32970
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33065,7 +33022,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33065
33022
|
(blur)="onBlur()"
|
|
33066
33023
|
(mouseenter)="onMouseEnter()"
|
|
33067
33024
|
(mouseleave)="onMouseLeave()"
|
|
33068
|
-
[readonly]="config.readonly"
|
|
33025
|
+
[readonly]="config.html5?.readonly"
|
|
33069
33026
|
[attr.aria-required]="required"
|
|
33070
33027
|
[attr.aria-invalid]="!!error"
|
|
33071
33028
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33086,7 +33043,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33086
33043
|
(blur)="onBlur()"
|
|
33087
33044
|
(mouseenter)="onMouseEnter()"
|
|
33088
33045
|
(mouseleave)="onMouseLeave()"
|
|
33089
|
-
[readonly]="config.readonly"
|
|
33046
|
+
[readonly]="config.html5?.readonly"
|
|
33090
33047
|
[attr.aria-required]="required"
|
|
33091
33048
|
[attr.aria-invalid]="!!error"
|
|
33092
33049
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33098,7 +33055,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33098
33055
|
[cpAlphaChannel]="'disabled'"
|
|
33099
33056
|
[cpOutputFormat]="'hex'"
|
|
33100
33057
|
[cpFallbackColor]="'#000000'"
|
|
33101
|
-
[cpDisabled]="config.readonly || !enabled"
|
|
33058
|
+
[cpDisabled]="config.html5?.readonly || !enabled"
|
|
33102
33059
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
33103
33060
|
} @else if (usesFormattedNumberInput()) {
|
|
33104
33061
|
@if (hasDisplayPrefix()) {
|
|
@@ -33120,7 +33077,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33120
33077
|
(blur)="onBlur()"
|
|
33121
33078
|
(mouseenter)="onMouseEnter()"
|
|
33122
33079
|
(mouseleave)="onMouseLeave()"
|
|
33123
|
-
[readonly]="config.readonly"
|
|
33080
|
+
[readonly]="config.html5?.readonly"
|
|
33124
33081
|
[disabled]="control.disabled"
|
|
33125
33082
|
[attr.aria-required]="required"
|
|
33126
33083
|
[attr.aria-invalid]="!!error"
|
|
@@ -33150,7 +33107,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33150
33107
|
(blur)="onBlur()"
|
|
33151
33108
|
(mouseenter)="onMouseEnter()"
|
|
33152
33109
|
(mouseleave)="onMouseLeave()"
|
|
33153
|
-
[readonly]="config.readonly"
|
|
33110
|
+
[readonly]="config.html5?.readonly"
|
|
33154
33111
|
[attr.aria-required]="required"
|
|
33155
33112
|
[attr.aria-invalid]="!!error"
|
|
33156
33113
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33263,12 +33220,12 @@ class FileUploadWidgetComponent {
|
|
|
33263
33220
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
33264
33221
|
}
|
|
33265
33222
|
get enabled() {
|
|
33266
|
-
if (this.config
|
|
33223
|
+
if (isFieldDisabled(this.config))
|
|
33267
33224
|
return false;
|
|
33268
33225
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
33269
33226
|
}
|
|
33270
33227
|
get isDisabled() {
|
|
33271
|
-
return !this.enabled ||
|
|
33228
|
+
return !this.enabled || isFieldReadonly(this.config);
|
|
33272
33229
|
}
|
|
33273
33230
|
get required() {
|
|
33274
33231
|
return this.engine ? this.engine.isFieldRequired(this.config.id) : !!this.config?.html5?.required;
|
|
@@ -33759,7 +33716,7 @@ class SelectWidgetComponent {
|
|
|
33759
33716
|
this.runtimeOptionsLoaded = false;
|
|
33760
33717
|
this.currentSearchTerm = '';
|
|
33761
33718
|
this.setOptionsFromRaw([]);
|
|
33762
|
-
void this.loadOptions(this.currentSearchTerm);
|
|
33719
|
+
void this.loadOptions(this.currentSearchTerm, false, true);
|
|
33763
33720
|
});
|
|
33764
33721
|
}
|
|
33765
33722
|
}
|
|
@@ -33902,7 +33859,7 @@ class SelectWidgetComponent {
|
|
|
33902
33859
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
33903
33860
|
}
|
|
33904
33861
|
get enabled() {
|
|
33905
|
-
if (this.config
|
|
33862
|
+
if (isFieldDisabled(this.config))
|
|
33906
33863
|
return false;
|
|
33907
33864
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
33908
33865
|
}
|
|
@@ -33959,7 +33916,7 @@ class SelectWidgetComponent {
|
|
|
33959
33916
|
event.preventDefault();
|
|
33960
33917
|
}
|
|
33961
33918
|
onPillClick() {
|
|
33962
|
-
if (this.config
|
|
33919
|
+
if (isFieldReadonly(this.config)) {
|
|
33963
33920
|
return;
|
|
33964
33921
|
}
|
|
33965
33922
|
this.onClick();
|
|
@@ -34026,7 +33983,7 @@ class SelectWidgetComponent {
|
|
|
34026
33983
|
assign('--fd-select-icon-color', controlStyles['iconColor'] ?? controlStyles['color']);
|
|
34027
33984
|
return vars;
|
|
34028
33985
|
}
|
|
34029
|
-
async loadOptions(term = '', isSearch = false) {
|
|
33986
|
+
async loadOptions(term = '', isSearch = false, clearStaleSelection = false) {
|
|
34030
33987
|
if (!this.config)
|
|
34031
33988
|
return;
|
|
34032
33989
|
const reqId = ++this.requestId;
|
|
@@ -34044,8 +34001,17 @@ class SelectWidgetComponent {
|
|
|
34044
34001
|
opts = await this.dataProvider.getOptions(this.config, this.engine);
|
|
34045
34002
|
}
|
|
34046
34003
|
if (this.requestId === reqId) {
|
|
34047
|
-
this.
|
|
34048
|
-
|
|
34004
|
+
const selectedValue = this.resolveSelectedValueForFallback();
|
|
34005
|
+
const shouldClearStaleSelection = clearStaleSelection
|
|
34006
|
+
&& this.hasMeaningfulValue(selectedValue)
|
|
34007
|
+
&& !this.hasOptionValue(opts, this.toComparableOptionValue(selectedValue));
|
|
34008
|
+
this.setOptionsFromRaw(shouldClearStaleSelection ? opts : this.withSelectedValueFallbackOptions(opts));
|
|
34009
|
+
if (shouldClearStaleSelection) {
|
|
34010
|
+
this.control.setValue(null);
|
|
34011
|
+
}
|
|
34012
|
+
else {
|
|
34013
|
+
this.syncStoredFieldLabel(this.control.value);
|
|
34014
|
+
}
|
|
34049
34015
|
this.loading = false;
|
|
34050
34016
|
this.loadError = null;
|
|
34051
34017
|
this.cdr.markForCheck();
|
|
@@ -34152,6 +34118,9 @@ class SelectWidgetComponent {
|
|
|
34152
34118
|
config.id,
|
|
34153
34119
|
config.name,
|
|
34154
34120
|
config.type,
|
|
34121
|
+
String(config.html5?.readonly ?? ''),
|
|
34122
|
+
String(config.html5?.disabled ?? ''),
|
|
34123
|
+
String(config.useThousandSeparator ?? ''),
|
|
34155
34124
|
'no-data-config',
|
|
34156
34125
|
fieldStaticOptions
|
|
34157
34126
|
].join('::');
|
|
@@ -34164,11 +34133,13 @@ class SelectWidgetComponent {
|
|
|
34164
34133
|
config.id,
|
|
34165
34134
|
config.name,
|
|
34166
34135
|
config.type,
|
|
34136
|
+
String(config.html5?.readonly ?? ''),
|
|
34137
|
+
String(config.html5?.disabled ?? ''),
|
|
34167
34138
|
dataConfig.type ?? '',
|
|
34168
34139
|
String(dataConfig.datasourceId ?? ''),
|
|
34169
34140
|
String(dataConfig.labelKey ?? ''),
|
|
34170
34141
|
String(dataConfig.valueKey ?? ''),
|
|
34171
|
-
String(
|
|
34142
|
+
String(config.useThousandSeparator ?? ''),
|
|
34172
34143
|
String(dataConfig.optionLabelPrefixFieldId ?? ''),
|
|
34173
34144
|
String(dataConfig.searchEnabled ?? ''),
|
|
34174
34145
|
String(dataConfig.optionsLimit ?? ''),
|
|
@@ -34221,15 +34192,18 @@ class SelectWidgetComponent {
|
|
|
34221
34192
|
applyDisplayFormatting() {
|
|
34222
34193
|
this.options = this.rawOptions.map(option => ({
|
|
34223
34194
|
...option,
|
|
34224
|
-
label: this.formatOptionLabel(option
|
|
34195
|
+
label: this.formatOptionLabel(option)
|
|
34225
34196
|
}));
|
|
34226
34197
|
}
|
|
34227
|
-
formatOptionLabel(
|
|
34228
|
-
const
|
|
34198
|
+
formatOptionLabel(option) {
|
|
34199
|
+
const label = option.label;
|
|
34200
|
+
const formattedLabel = usesFieldThousandSeparator(this.config)
|
|
34229
34201
|
? this.formatNumericLabel(label)
|
|
34230
34202
|
: label;
|
|
34231
|
-
const
|
|
34232
|
-
|
|
34203
|
+
const prefixParts = [option.displayPrefix, this.resolveOptionLabelPrefix()]
|
|
34204
|
+
.map(value => value?.trim())
|
|
34205
|
+
.filter((value) => !!value);
|
|
34206
|
+
return prefixParts.length > 0 ? `${prefixParts.join(' ')} ${formattedLabel}` : formattedLabel;
|
|
34233
34207
|
}
|
|
34234
34208
|
resolveOptionLabelPrefix() {
|
|
34235
34209
|
const prefixFieldId = this.config.dataConfig?.optionLabelPrefixFieldId;
|
|
@@ -34312,6 +34286,12 @@ class SelectWidgetComponent {
|
|
|
34312
34286
|
hasOptionValue(options, value) {
|
|
34313
34287
|
return options.some(option => Object.is(option.value, value) || String(option.value) === String(value));
|
|
34314
34288
|
}
|
|
34289
|
+
toComparableOptionValue(value) {
|
|
34290
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
34291
|
+
return value;
|
|
34292
|
+
}
|
|
34293
|
+
return String(value ?? '');
|
|
34294
|
+
}
|
|
34315
34295
|
resolveSelectedValueForFallback() {
|
|
34316
34296
|
const controlValue = this.control.value;
|
|
34317
34297
|
if (this.hasMeaningfulValue(controlValue)) {
|
|
@@ -34356,7 +34336,7 @@ class SelectWidgetComponent {
|
|
|
34356
34336
|
if (this.config.dataConfig?.optionLabelPrefixFieldId) {
|
|
34357
34337
|
return this.resolveOptionLabelPrefix().length === 0;
|
|
34358
34338
|
}
|
|
34359
|
-
return this.config
|
|
34339
|
+
return !usesFieldThousandSeparator(this.config);
|
|
34360
34340
|
}
|
|
34361
34341
|
setStoredFieldLabel(label) {
|
|
34362
34342
|
if (!this.engine || typeof this.engine.setFieldLabel !== 'function') {
|
|
@@ -34394,8 +34374,8 @@ class SelectWidgetComponent {
|
|
|
34394
34374
|
[loadingText]="'Loading options...'"
|
|
34395
34375
|
[notFoundText]="loadError || 'No options found'"
|
|
34396
34376
|
[searchable]="isSearchable()"
|
|
34397
|
-
[clearable]="!required && !config.readonly && !hasPillLabel()"
|
|
34398
|
-
[readonly]="config.readonly"
|
|
34377
|
+
[clearable]="!required && !config.html5?.readonly && !hasPillLabel()"
|
|
34378
|
+
[readonly]="config.html5?.readonly"
|
|
34399
34379
|
[labelForId]="fieldId"
|
|
34400
34380
|
[inputAttrs]="getInputAttributes()"
|
|
34401
34381
|
[typeahead]="searchTerms$"
|
|
@@ -34421,7 +34401,7 @@ class SelectWidgetComponent {
|
|
|
34421
34401
|
class="fd-select-pill"
|
|
34422
34402
|
[ngStyle]="getPillStyles()"
|
|
34423
34403
|
data-fd-select-pill
|
|
34424
|
-
[disabled]="config.readonly"
|
|
34404
|
+
[disabled]="config.html5?.readonly"
|
|
34425
34405
|
(mousedown)="onPillMouseDown($event)"
|
|
34426
34406
|
(click)="onPillClick()">
|
|
34427
34407
|
<span class="fd-select-pill__label">{{ pillLabel() }}</span>
|
|
@@ -34474,8 +34454,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
34474
34454
|
[loadingText]="'Loading options...'"
|
|
34475
34455
|
[notFoundText]="loadError || 'No options found'"
|
|
34476
34456
|
[searchable]="isSearchable()"
|
|
34477
|
-
[clearable]="!required && !config.readonly && !hasPillLabel()"
|
|
34478
|
-
[readonly]="config.readonly"
|
|
34457
|
+
[clearable]="!required && !config.html5?.readonly && !hasPillLabel()"
|
|
34458
|
+
[readonly]="config.html5?.readonly"
|
|
34479
34459
|
[labelForId]="fieldId"
|
|
34480
34460
|
[inputAttrs]="getInputAttributes()"
|
|
34481
34461
|
[typeahead]="searchTerms$"
|
|
@@ -34501,7 +34481,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
34501
34481
|
class="fd-select-pill"
|
|
34502
34482
|
[ngStyle]="getPillStyles()"
|
|
34503
34483
|
data-fd-select-pill
|
|
34504
|
-
[disabled]="config.readonly"
|
|
34484
|
+
[disabled]="config.html5?.readonly"
|
|
34505
34485
|
(mousedown)="onPillMouseDown($event)"
|
|
34506
34486
|
(click)="onPillClick()">
|
|
34507
34487
|
<span class="fd-select-pill__label">{{ pillLabel() }}</span>
|
|
@@ -34596,7 +34576,7 @@ class SearchWidgetComponent {
|
|
|
34596
34576
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
34597
34577
|
}
|
|
34598
34578
|
get enabled() {
|
|
34599
|
-
if (this.config
|
|
34579
|
+
if (isFieldDisabled(this.config))
|
|
34600
34580
|
return false;
|
|
34601
34581
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
34602
34582
|
}
|
|
@@ -34659,7 +34639,7 @@ class SearchWidgetComponent {
|
|
|
34659
34639
|
const datasourceId = this.config?.dataConfig?.datasourceId;
|
|
34660
34640
|
if (!datasourceId || update.datasourceId !== datasourceId)
|
|
34661
34641
|
return;
|
|
34662
|
-
void this.refreshForCurrentQuery();
|
|
34642
|
+
void this.refreshForCurrentQuery(true);
|
|
34663
34643
|
});
|
|
34664
34644
|
}
|
|
34665
34645
|
this.engine.valueChanges$
|
|
@@ -34803,7 +34783,7 @@ class SearchWidgetComponent {
|
|
|
34803
34783
|
this.queryControl.disable({ emitEvent: false });
|
|
34804
34784
|
}
|
|
34805
34785
|
}
|
|
34806
|
-
async refreshForCurrentQuery() {
|
|
34786
|
+
async refreshForCurrentQuery(clearStaleSelection = false) {
|
|
34807
34787
|
const query = this.queryControl.value ?? '';
|
|
34808
34788
|
if (!this.shouldQuery(query)) {
|
|
34809
34789
|
this.options = [];
|
|
@@ -34813,7 +34793,7 @@ class SearchWidgetComponent {
|
|
|
34813
34793
|
this.cdr.markForCheck();
|
|
34814
34794
|
return;
|
|
34815
34795
|
}
|
|
34816
|
-
await this.loadOptions(query);
|
|
34796
|
+
await this.loadOptions(query, clearStaleSelection);
|
|
34817
34797
|
}
|
|
34818
34798
|
async handleQueryChange(query) {
|
|
34819
34799
|
if (this.selectingOption) {
|
|
@@ -34833,7 +34813,7 @@ class SearchWidgetComponent {
|
|
|
34833
34813
|
}
|
|
34834
34814
|
await this.loadOptions(normalizedQuery);
|
|
34835
34815
|
}
|
|
34836
|
-
async loadOptions(term) {
|
|
34816
|
+
async loadOptions(term, clearStaleSelection = false) {
|
|
34837
34817
|
const requestId = ++this.requestId;
|
|
34838
34818
|
this.loading = true;
|
|
34839
34819
|
this.loadError = null;
|
|
@@ -34847,6 +34827,15 @@ class SearchWidgetComponent {
|
|
|
34847
34827
|
return;
|
|
34848
34828
|
}
|
|
34849
34829
|
this.options = this.normalizeOptions(options);
|
|
34830
|
+
if (clearStaleSelection && this.isSelectedOptionState() && !this.hasOptionValue(this.options, this.control.value)) {
|
|
34831
|
+
this.queryControl.setValue('', { emitEvent: false });
|
|
34832
|
+
this.control.setValue(null);
|
|
34833
|
+
this.loading = false;
|
|
34834
|
+
this.loadError = null;
|
|
34835
|
+
this.activeOptionIndex = -1;
|
|
34836
|
+
this.cdr.markForCheck();
|
|
34837
|
+
return;
|
|
34838
|
+
}
|
|
34850
34839
|
this.activeOptionIndex = this.options.length > 0 ? 0 : -1;
|
|
34851
34840
|
this.loading = false;
|
|
34852
34841
|
this.loadError = null;
|
|
@@ -34878,6 +34867,31 @@ class SearchWidgetComponent {
|
|
|
34878
34867
|
const minChars = this.getMinChars();
|
|
34879
34868
|
return (query ?? '').trim().length >= minChars;
|
|
34880
34869
|
}
|
|
34870
|
+
isSelectedOptionState() {
|
|
34871
|
+
if (!this.hasMeaningfulValue(this.control.value)) {
|
|
34872
|
+
return false;
|
|
34873
|
+
}
|
|
34874
|
+
const storedLabel = this.getStoredFieldLabel();
|
|
34875
|
+
if (typeof storedLabel === 'string' && storedLabel.length > 0) {
|
|
34876
|
+
return true;
|
|
34877
|
+
}
|
|
34878
|
+
return String(this.control.value ?? '') !== String(this.queryControl.value ?? '');
|
|
34879
|
+
}
|
|
34880
|
+
hasOptionValue(options, value) {
|
|
34881
|
+
if (!this.hasMeaningfulValue(value)) {
|
|
34882
|
+
return false;
|
|
34883
|
+
}
|
|
34884
|
+
return options.some(option => Object.is(option.value, value) || String(option.value) === String(value));
|
|
34885
|
+
}
|
|
34886
|
+
hasMeaningfulValue(value) {
|
|
34887
|
+
if (value === undefined || value === null)
|
|
34888
|
+
return false;
|
|
34889
|
+
if (typeof value === 'string')
|
|
34890
|
+
return value.length > 0;
|
|
34891
|
+
if (Array.isArray(value))
|
|
34892
|
+
return value.length > 0;
|
|
34893
|
+
return true;
|
|
34894
|
+
}
|
|
34881
34895
|
getMinChars() {
|
|
34882
34896
|
return this.toSafeNonNegativeInt(this.config?.['searchMinChars'], 1);
|
|
34883
34897
|
}
|
|
@@ -34945,7 +34959,7 @@ class SearchWidgetComponent {
|
|
|
34945
34959
|
type="search"
|
|
34946
34960
|
[placeholder]="config.placeholder || 'Search...'"
|
|
34947
34961
|
[formControl]="queryControl"
|
|
34948
|
-
[readonly]="config.readonly"
|
|
34962
|
+
[readonly]="config.html5?.readonly"
|
|
34949
34963
|
[attr.aria-required]="required"
|
|
34950
34964
|
[attr.aria-invalid]="!!error"
|
|
34951
34965
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -35024,7 +35038,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
35024
35038
|
type="search"
|
|
35025
35039
|
[placeholder]="config.placeholder || 'Search...'"
|
|
35026
35040
|
[formControl]="queryControl"
|
|
35027
|
-
[readonly]="config.readonly"
|
|
35041
|
+
[readonly]="config.html5?.readonly"
|
|
35028
35042
|
[attr.aria-required]="required"
|
|
35029
35043
|
[attr.aria-invalid]="!!error"
|
|
35030
35044
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -35311,7 +35325,7 @@ class TreeSelectWidgetComponent {
|
|
|
35311
35325
|
expandRecursive(filtered);
|
|
35312
35326
|
}
|
|
35313
35327
|
toggleDropdown(e) {
|
|
35314
|
-
if (this.config
|
|
35328
|
+
if (isFieldDisabled(this.config) || isFieldReadonly(this.config))
|
|
35315
35329
|
return;
|
|
35316
35330
|
this.engine?.emitUiEvent({ fieldId: this.config.id, fieldName: this.config.name, type: 'click' });
|
|
35317
35331
|
if (this.isOpen) {
|
|
@@ -35423,8 +35437,8 @@ class TreeSelectWidgetComponent {
|
|
|
35423
35437
|
<!-- Dropdown Trigger -->
|
|
35424
35438
|
<div class="relative group" (click)="toggleDropdown($event)">
|
|
35425
35439
|
<div class="flex items-center justify-between w-full rounded-md border text-sm px-3 py-2 cursor-pointer transition-colors"
|
|
35426
|
-
[class.bg-gray-50]="config.disabled"
|
|
35427
|
-
[class.cursor-not-allowed]="config.disabled"
|
|
35440
|
+
[class.bg-gray-50]="config.html5?.disabled"
|
|
35441
|
+
[class.cursor-not-allowed]="config.html5?.disabled"
|
|
35428
35442
|
[class.border-gray-300]="!isInvalid && !isOpen"
|
|
35429
35443
|
[class.border-blue-500]="isOpen"
|
|
35430
35444
|
[class.ring-2]="isOpen"
|
|
@@ -35527,8 +35541,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
35527
35541
|
<!-- Dropdown Trigger -->
|
|
35528
35542
|
<div class="relative group" (click)="toggleDropdown($event)">
|
|
35529
35543
|
<div class="flex items-center justify-between w-full rounded-md border text-sm px-3 py-2 cursor-pointer transition-colors"
|
|
35530
|
-
[class.bg-gray-50]="config.disabled"
|
|
35531
|
-
[class.cursor-not-allowed]="config.disabled"
|
|
35544
|
+
[class.bg-gray-50]="config.html5?.disabled"
|
|
35545
|
+
[class.cursor-not-allowed]="config.html5?.disabled"
|
|
35532
35546
|
[class.border-gray-300]="!isInvalid && !isOpen"
|
|
35533
35547
|
[class.border-blue-500]="isOpen"
|
|
35534
35548
|
[class.ring-2]="isOpen"
|
|
@@ -35778,7 +35792,7 @@ class RadioWidgetComponent {
|
|
|
35778
35792
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
35779
35793
|
}
|
|
35780
35794
|
get enabled() {
|
|
35781
|
-
if (this.config
|
|
35795
|
+
if (isFieldDisabled(this.config))
|
|
35782
35796
|
return false;
|
|
35783
35797
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
35784
35798
|
}
|
|
@@ -36094,7 +36108,7 @@ class CheckboxGroupWidgetComponent {
|
|
|
36094
36108
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36095
36109
|
}
|
|
36096
36110
|
get enabled() {
|
|
36097
|
-
if (this.config
|
|
36111
|
+
if (isFieldDisabled(this.config))
|
|
36098
36112
|
return false;
|
|
36099
36113
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36100
36114
|
}
|
|
@@ -36330,7 +36344,7 @@ class CheckboxWidgetComponent {
|
|
|
36330
36344
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36331
36345
|
}
|
|
36332
36346
|
get enabled() {
|
|
36333
|
-
if (this.config
|
|
36347
|
+
if (isFieldDisabled(this.config))
|
|
36334
36348
|
return false;
|
|
36335
36349
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36336
36350
|
}
|
|
@@ -36564,7 +36578,7 @@ class RepeatableGroupWidgetComponent {
|
|
|
36564
36578
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36565
36579
|
}
|
|
36566
36580
|
get enabled() {
|
|
36567
|
-
if (this.config
|
|
36581
|
+
if (isFieldDisabled(this.config))
|
|
36568
36582
|
return false;
|
|
36569
36583
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36570
36584
|
}
|
|
@@ -37899,8 +37913,8 @@ const COMMON_GROUP_FIELDS = [
|
|
|
37899
37913
|
{ key: 'groupKey', type: 'text', label: 'Group Key', placeholder: 'documents', helpText: 'Group fields into one object on submit/preview (uses the field key inside the group).' }
|
|
37900
37914
|
];
|
|
37901
37915
|
const COMMON_INTERACTIVITY_FIELDS = [
|
|
37902
|
-
{ key: 'readonly', type: 'checkbox', label: 'Read Only' },
|
|
37903
|
-
{ key: 'disabled', type: 'checkbox', label: 'Disabled' }
|
|
37916
|
+
{ key: 'html5.readonly', type: 'checkbox', label: 'Read Only' },
|
|
37917
|
+
{ key: 'html5.disabled', type: 'checkbox', label: 'Disabled' }
|
|
37904
37918
|
];
|
|
37905
37919
|
const COMMON_BASIC_FIELDS = [
|
|
37906
37920
|
{ key: 'name', type: 'text', label: 'Field Key (Name)' },
|
|
@@ -37960,16 +37974,10 @@ const BASE_REQUIRED_FIELD = {
|
|
|
37960
37974
|
label: 'Required',
|
|
37961
37975
|
helpText: 'Base required state; Rules can override this dynamically.'
|
|
37962
37976
|
};
|
|
37963
|
-
const CUSTOM_VALIDATION_RULES_FIELD = {
|
|
37964
|
-
key: 'validation',
|
|
37965
|
-
type: 'validators-editor',
|
|
37966
|
-
label: 'Custom Validation Rules',
|
|
37967
|
-
helpText: 'Use these for field-level validation checks. Use the Rules tab for conditional behaviour.'
|
|
37968
|
-
};
|
|
37969
37977
|
function createValidationSection(...fields) {
|
|
37970
37978
|
return {
|
|
37971
37979
|
label: 'Validation',
|
|
37972
|
-
fields
|
|
37980
|
+
fields
|
|
37973
37981
|
};
|
|
37974
37982
|
}
|
|
37975
37983
|
const TEXT_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD, { key: 'html5.minLength', type: 'number', label: 'Min Length' }, { key: 'html5.maxLength', type: 'number', label: 'Max Length' }, { key: 'html5.pattern', type: 'text', label: 'Pattern (regex)' });
|
|
@@ -37979,6 +37987,28 @@ const TIME_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD, { k
|
|
|
37979
37987
|
const DATETIME_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD, { key: 'html5.min', type: 'text', label: 'Earliest (YYYY-MM-DDTHH:MM)' }, { key: 'html5.max', type: 'text', label: 'Latest (YYYY-MM-DDTHH:MM)' });
|
|
37980
37988
|
const SELECT_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD);
|
|
37981
37989
|
const FILE_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD);
|
|
37990
|
+
const NUMBER_DISPLAY_SECTION = {
|
|
37991
|
+
label: 'Display',
|
|
37992
|
+
fields: [
|
|
37993
|
+
{
|
|
37994
|
+
key: 'useThousandSeparator',
|
|
37995
|
+
type: 'checkbox',
|
|
37996
|
+
label: 'Show thousand separators',
|
|
37997
|
+
helpText: 'Formats grouped digits in the visible field value without changing the stored number.'
|
|
37998
|
+
}
|
|
37999
|
+
]
|
|
38000
|
+
};
|
|
38001
|
+
const SELECT_DISPLAY_SECTION = {
|
|
38002
|
+
label: 'Display',
|
|
38003
|
+
fields: [
|
|
38004
|
+
{
|
|
38005
|
+
key: 'useThousandSeparator',
|
|
38006
|
+
type: 'checkbox',
|
|
38007
|
+
label: 'Show thousand separators for numeric labels',
|
|
38008
|
+
helpText: 'Formats numeric option labels without changing the stored option value.'
|
|
38009
|
+
}
|
|
38010
|
+
]
|
|
38011
|
+
};
|
|
37982
38012
|
const BUTTON_VARIANT_OPTIONS = [
|
|
37983
38013
|
{ label: 'Primary (Blue)', value: 'primary' },
|
|
37984
38014
|
{ label: 'Secondary (Outline)', value: 'secondary' }
|
|
@@ -38187,6 +38217,7 @@ const FIELD_WIDGETS = [
|
|
|
38187
38217
|
]
|
|
38188
38218
|
},
|
|
38189
38219
|
NUMBER_VALIDATION_SECTION,
|
|
38220
|
+
NUMBER_DISPLAY_SECTION,
|
|
38190
38221
|
{ label: 'Appearance', fields: COMMON_APPEARANCE_FIELDS },
|
|
38191
38222
|
...COMMON_STYLE_SECTIONS
|
|
38192
38223
|
]
|
|
@@ -38648,6 +38679,7 @@ const FIELD_WIDGETS = [
|
|
|
38648
38679
|
},
|
|
38649
38680
|
// Options are now handled in Data Tab
|
|
38650
38681
|
SELECT_VALIDATION_SECTION,
|
|
38682
|
+
SELECT_DISPLAY_SECTION,
|
|
38651
38683
|
{ label: 'Appearance', fields: COMMON_APPEARANCE_FIELDS },
|
|
38652
38684
|
...COMMON_STYLE_SECTIONS
|
|
38653
38685
|
]
|
|
@@ -41463,5 +41495,5 @@ function provideHttpDataSourceClient(config) {
|
|
|
41463
41495
|
* Generated bundle index. Do not edit.
|
|
41464
41496
|
*/
|
|
41465
41497
|
|
|
41466
|
-
export { APPEARANCE_FIELDS, AiToolRegistryService, CONTENT_TEXT_CLASS, CONTENT_TEXT_MUTED_CLASS, CORE_DESIGNER_PLUGINS, CURRENT_SCHEMA_VERSION, DATA_PROVIDER, DATA_SOURCE_CLIENT, DEFAULT_TEMPLATE_LIBRARY, DEFAULT_WEBSITE_SECTIONS, DEFAULT_WIDGET_PACKS, DESIGNER_PLUGINS, DESIGNER_SECTIONS, DataCatalog, DataPanelComponent, DataProvider, DefaultDataProvider, DefaultDataSourceClient, DefaultFileUploadClient, DesignerContext, DesignerStateService, DynamicPropertiesComponent, EFFECTS_FIELDS, EMAIL_SAFE_STYLE_SECTIONS, EMAIL_WIDGETS, EmailRendererComponent, EventsPanelComponent, EventsWorkspaceComponent, FIELD_CHOICE_LABEL_CLASS, FIELD_CHOICE_SURFACE_CLASS, FIELD_CONTAINER_CLASS, FIELD_ERROR_CLASS, FIELD_HELP_CLASS, FIELD_LABEL_CLASS, FIELD_OPTION_CLASS, FIELD_REQUIRED_CLASS, FIELD_RESULTS_PANEL_CLASS, FIELD_WIDGETS, FILE_UPLOAD_CARD_CLASS, FILE_UPLOAD_CLIENT, FORM_DESIGNER_AI_TOOL_PLUGIN, FULL_WEB_STYLE_SECTIONS, FieldPaletteComponent, FormDesignerAiFeatureStateService, FormDesignerShellComponent, FormEngine, FormJourneyStateService, FormJourneyViewerComponent, FormViewerComponent, GlobalDataManagerComponent, HTTP_DATA_SOURCE_CLIENT_CONFIG, HttpDataSourceClient, InMemoryDataCatalogService, InspectorAdvancedSectionComponent, InspectorBackgroundsSectionComponent, InspectorBordersSectionComponent, InspectorEffectsSectionComponent, InspectorLayoutSectionComponent, InspectorPositionSectionComponent, InspectorSizeSectionComponent, InspectorSpacingSectionComponent, InspectorSpinInputComponent, InspectorTypographySectionComponent, JsonFormDesignerComponent, JsonFormRendererComponent, LAYOUT_FIELDS, LayoutCanvasComponent, LayoutNodeComponent, OUTLINED_FIELD_BORDER_WIDTH, OUTLINED_FIELD_IDLE_BORDER_COLOR, OUTLINED_FIELD_INTERACTIVE_BORDER_COLOR, OUTLINED_FIELD_INVALID_BORDER_COLOR, PAGE_WIDGETS, PropertiesPanelComponent, RulesPanelComponent, RuntimeFieldDataAccessRegistryService, SELECT_THEME_HOOKS, SELECT_THEME_TOKENS, SPACING_BOX_MODEL_FIELD, SPACING_MARGIN_FIELDS, SPACING_PADDING_FIELDS, STANDARD_FORM_STYLE_SECTIONS, STYLE_APPEARANCE_SECTION, STYLE_EFFECTS_SECTION, STYLE_LAYOUT_SECTION, STYLE_SECTIONS, STYLE_SPACING_SECTION, STYLE_TRANSFORM_SECTION, STYLE_TYPOGRAPHY_SECTION, TABLE_CELL_CLASS, TABLE_EMPTY_CLASS, TABLE_GRID_CLASS, TABLE_HEAD_CELL_CLASS, TABLE_HEAD_CLASS, TABLE_ICON_BUTTON_CLASS, TABLE_ROOT_CLASS, TABLE_ROW_CLASS, TABLE_TOOLBAR_CLASS, TRANSFORM_FIELDS, TYPOGRAPHY_FIELDS, ThemeService, UiAccordionComponent, UiBoxModelComponent, UiColorSwatchComponent, UiDimensionComponent, UiEdgeBoxComponent, UiFieldWrapperComponent, UiInputComponent, UiRangeNumberComponent, UiSelectIconComponent, UiTabComponent, UiTabsComponent, WIDGET_DEFINITIONS, WIDGET_ID_SEPARATOR, WebsiteBrickStudioComponent, WebsiteDesignerShellComponent, WebsitePreviewShellComponent, WebsiteProjectService, WidgetDefinitionResolverService, WidgetInspectorComponent, appendSectionToSchema, buildWidgetId, checkSchemaForApiOnlySources, createDefaultWebsiteBrick, createDefaultWebsiteBricks, createDefaultWebsiteTheme, createEmptySchema, createFormEngine, createFormJourneyPage, createFormJourneyProject, createPluginContext, createWebsiteBrick, createWebsitePage, createWebsiteProject, defineWidget, flattenPluginWidgets, getButtonClass, getChoiceControlClass, getEffectiveDataConfig, getFileInputClass, getFileUploadShellClass, getHeadingClass, getOutlinedFieldInlineStyle, getTextControlClass, getWidgetsForFlavor, hasWrapperSurfaceStyles, inferSchema, isFormJourneyProject, isWidgetVisibleInPalette, mergeAndNormalize, normalizeRuntimeOptions, normalizeStyle$1 as normalizeStyle, normalizeToJourney, parseCsv, parseJsonArray, parseSchema, provideDesignerPlugins, provideFormDesignerAngaiFeature, provideHttpDataSourceClient, serializeSchema, slugifyId, splitControlSurfaceStyles, stripEmbeddedSourceData, unwrapSinglePageJourney };
|
|
41498
|
+
export { APPEARANCE_FIELDS, AiToolRegistryService, CONTENT_TEXT_CLASS, CONTENT_TEXT_MUTED_CLASS, CORE_DESIGNER_PLUGINS, CURRENT_SCHEMA_VERSION, DATA_PROVIDER, DATA_SOURCE_CLIENT, DEFAULT_TEMPLATE_LIBRARY, DEFAULT_WEBSITE_SECTIONS, DEFAULT_WIDGET_PACKS, DESIGNER_PLUGINS, DESIGNER_SECTIONS, DataCatalog, DataPanelComponent, DataProvider, DefaultDataProvider, DefaultDataSourceClient, DefaultFileUploadClient, DesignerContext, DesignerStateService, DynamicPropertiesComponent, EFFECTS_FIELDS, EMAIL_SAFE_STYLE_SECTIONS, EMAIL_WIDGETS, EmailRendererComponent, EventsPanelComponent, EventsWorkspaceComponent, FIELD_CHOICE_LABEL_CLASS, FIELD_CHOICE_SURFACE_CLASS, FIELD_CONTAINER_CLASS, FIELD_ERROR_CLASS, FIELD_HELP_CLASS, FIELD_LABEL_CLASS, FIELD_OPTION_CLASS, FIELD_REQUIRED_CLASS, FIELD_RESULTS_PANEL_CLASS, FIELD_WIDGETS, FILE_UPLOAD_CARD_CLASS, FILE_UPLOAD_CLIENT, FORM_DESIGNER_AI_TOOL_PLUGIN, FULL_WEB_STYLE_SECTIONS, FieldPaletteComponent, FormDesignerAiFeatureStateService, FormDesignerShellComponent, FormEngine, FormJourneyStateService, FormJourneyViewerComponent, FormViewerComponent, GlobalDataManagerComponent, HTTP_DATA_SOURCE_CLIENT_CONFIG, HttpDataSourceClient, InMemoryDataCatalogService, InspectorAdvancedSectionComponent, InspectorBackgroundsSectionComponent, InspectorBordersSectionComponent, InspectorEffectsSectionComponent, InspectorLayoutSectionComponent, InspectorPositionSectionComponent, InspectorSizeSectionComponent, InspectorSpacingSectionComponent, InspectorSpinInputComponent, InspectorTypographySectionComponent, JsonFormDesignerComponent, JsonFormRendererComponent, LAYOUT_FIELDS, LayoutCanvasComponent, LayoutNodeComponent, OUTLINED_FIELD_BORDER_WIDTH, OUTLINED_FIELD_IDLE_BORDER_COLOR, OUTLINED_FIELD_INTERACTIVE_BORDER_COLOR, OUTLINED_FIELD_INVALID_BORDER_COLOR, PAGE_WIDGETS, PropertiesPanelComponent, RulesPanelComponent, RuntimeFieldDataAccessRegistryService, SELECT_THEME_HOOKS, SELECT_THEME_TOKENS, SPACING_BOX_MODEL_FIELD, SPACING_MARGIN_FIELDS, SPACING_PADDING_FIELDS, STANDARD_FORM_STYLE_SECTIONS, STYLE_APPEARANCE_SECTION, STYLE_EFFECTS_SECTION, STYLE_LAYOUT_SECTION, STYLE_SECTIONS, STYLE_SPACING_SECTION, STYLE_TRANSFORM_SECTION, STYLE_TYPOGRAPHY_SECTION, TABLE_CELL_CLASS, TABLE_EMPTY_CLASS, TABLE_GRID_CLASS, TABLE_HEAD_CELL_CLASS, TABLE_HEAD_CLASS, TABLE_ICON_BUTTON_CLASS, TABLE_ROOT_CLASS, TABLE_ROW_CLASS, TABLE_TOOLBAR_CLASS, TRANSFORM_FIELDS, TYPOGRAPHY_FIELDS, ThemeService, UiAccordionComponent, UiBoxModelComponent, UiColorSwatchComponent, UiDimensionComponent, UiEdgeBoxComponent, UiFieldWrapperComponent, UiInputComponent, UiRangeNumberComponent, UiSelectIconComponent, UiTabComponent, UiTabsComponent, WIDGET_DEFINITIONS, WIDGET_ID_SEPARATOR, WebsiteBrickStudioComponent, WebsiteDesignerShellComponent, WebsitePreviewShellComponent, WebsiteProjectService, WidgetDefinitionResolverService, WidgetInspectorComponent, appendSectionToSchema, buildWidgetId, checkSchemaForApiOnlySources, createDefaultWebsiteBrick, createDefaultWebsiteBricks, createDefaultWebsiteTheme, createEmptySchema, createFormEngine, createFormJourneyPage, createFormJourneyProject, createPluginContext, createWebsiteBrick, createWebsitePage, createWebsiteProject, defineWidget, flattenPluginWidgets, getButtonClass, getChoiceControlClass, getEffectiveDataConfig, getFileInputClass, getFileUploadShellClass, getHeadingClass, getOutlinedFieldInlineStyle, getTextControlClass, getWidgetsForFlavor, hasWrapperSurfaceStyles, inferSchema, isFieldDisabled, isFieldReadonly, isFormJourneyProject, isWidgetVisibleInPalette, mergeAndNormalize, normalizeRuntimeOptions, normalizeStyle$1 as normalizeStyle, normalizeToJourney, parseCsv, parseJsonArray, parseSchema, provideDesignerPlugins, provideFormDesignerAngaiFeature, provideHttpDataSourceClient, serializeSchema, slugifyId, splitControlSurfaceStyles, stripEmbeddedSourceData, unwrapSinglePageJourney, usesFieldThousandSeparator };
|
|
41467
41499
|
//# sourceMappingURL=uch-web-ngx-form-designer.mjs.map
|