@yourself.create/ngx-form-designer 0.0.8 → 0.0.10
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 +396 -378
- 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 +2 -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-designer/widget-inspector.component.d.ts +1 -1
- 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;
|
|
@@ -568,30 +577,6 @@ class FormEngine {
|
|
|
568
577
|
}
|
|
569
578
|
}
|
|
570
579
|
}
|
|
571
|
-
// Custom Validation Rules
|
|
572
|
-
if (field.validation) {
|
|
573
|
-
field.validation.forEach(rule => {
|
|
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
|
-
}
|
|
595
580
|
}
|
|
596
581
|
if (fieldErrors.length > 0) {
|
|
597
582
|
this.errors[fieldName] = fieldErrors;
|
|
@@ -638,13 +623,31 @@ class FormEngine {
|
|
|
638
623
|
if (hasPositiveRules && startValue === true) {
|
|
639
624
|
currentState = false; // Implicitly hide/disable
|
|
640
625
|
}
|
|
641
|
-
field.
|
|
642
|
-
const conditionMet = this.ruleEvaluator.evaluateRule(rule, this.values, this.schema.fields);
|
|
643
|
-
const nextAction = conditionMet ? rule.action : rule.elseAction;
|
|
626
|
+
this.getEnterpriseRuleOutcomes(field).forEach(({ nextAction }) => {
|
|
644
627
|
currentState = this.applyRuleAction(currentState, nextAction, positiveAction, negativeAction);
|
|
645
628
|
});
|
|
646
629
|
return currentState;
|
|
647
630
|
}
|
|
631
|
+
getEnterpriseRuleOutcomes(field) {
|
|
632
|
+
if (!field.rules || field.rules.length === 0) {
|
|
633
|
+
return [];
|
|
634
|
+
}
|
|
635
|
+
return field.rules.map((rule) => {
|
|
636
|
+
const conditionMet = this.ruleEvaluator.evaluateRule(rule, this.values, this.schema.fields);
|
|
637
|
+
return {
|
|
638
|
+
rule,
|
|
639
|
+
conditionMet,
|
|
640
|
+
nextAction: conditionMet ? rule.action : rule.elseAction
|
|
641
|
+
};
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
getRuleValidationMessage(rule) {
|
|
645
|
+
const name = rule.name?.trim();
|
|
646
|
+
if (name) {
|
|
647
|
+
return name;
|
|
648
|
+
}
|
|
649
|
+
return `Rule "${rule.action}" failed.`;
|
|
650
|
+
}
|
|
648
651
|
applyRuleAction(currentState, action, positiveAction, negativeAction) {
|
|
649
652
|
if (action === positiveAction) {
|
|
650
653
|
return true;
|
|
@@ -4496,6 +4499,7 @@ class FormEventRunner {
|
|
|
4496
4499
|
const target = fields.find(f => f.id === action.targetFieldId);
|
|
4497
4500
|
if (!target)
|
|
4498
4501
|
return;
|
|
4502
|
+
const previousValue = this.engine.getValue(target.name);
|
|
4499
4503
|
let val;
|
|
4500
4504
|
if (action.valueFrom === 'literal') {
|
|
4501
4505
|
val = action.valueLiteral;
|
|
@@ -4510,6 +4514,14 @@ class FormEventRunner {
|
|
|
4510
4514
|
}
|
|
4511
4515
|
}
|
|
4512
4516
|
this.engine.setValue(target.name, val);
|
|
4517
|
+
if (!Object.is(previousValue, val)) {
|
|
4518
|
+
this.engine.emitUiEvent({
|
|
4519
|
+
fieldId: target.id,
|
|
4520
|
+
fieldName: target.name,
|
|
4521
|
+
type: 'change',
|
|
4522
|
+
value: val
|
|
4523
|
+
});
|
|
4524
|
+
}
|
|
4513
4525
|
}
|
|
4514
4526
|
async handleApiAction(action, eventId, evt, fields) {
|
|
4515
4527
|
if (!this.apiExecutor) {
|
|
@@ -5181,6 +5193,7 @@ class JsonFormRendererComponent {
|
|
|
5181
5193
|
uploadClient = inject(FILE_UPLOAD_CLIENT, { optional: true }) ?? inject(DefaultFileUploadClient);
|
|
5182
5194
|
runtimeFieldDataAccessRegistry = inject(RuntimeFieldDataAccessRegistryService);
|
|
5183
5195
|
dataCatalog = inject(DataCatalog, { optional: true });
|
|
5196
|
+
ruleEvaluationService = inject(RuleEvaluationService);
|
|
5184
5197
|
constructor(designerState) {
|
|
5185
5198
|
this.designerState = designerState;
|
|
5186
5199
|
}
|
|
@@ -5435,10 +5448,12 @@ class JsonFormRendererComponent {
|
|
|
5435
5448
|
const errors = revalidate
|
|
5436
5449
|
? (this.engine?.validate() ?? {})
|
|
5437
5450
|
: (this.engine?.getErrors() ?? {});
|
|
5451
|
+
const fields = this.buildFieldValidationState(errors);
|
|
5438
5452
|
return {
|
|
5439
5453
|
errors: { ...errors },
|
|
5440
5454
|
isValid: Object.keys(errors).length === 0,
|
|
5441
|
-
|
|
5455
|
+
isSeverityError: Object.values(fields).some(field => field.isSeverityError),
|
|
5456
|
+
fields
|
|
5442
5457
|
};
|
|
5443
5458
|
}
|
|
5444
5459
|
buildFieldValidationState(errors) {
|
|
@@ -5459,71 +5474,99 @@ class JsonFormRendererComponent {
|
|
|
5459
5474
|
visible,
|
|
5460
5475
|
required,
|
|
5461
5476
|
valid: fieldErrors.length === 0,
|
|
5477
|
+
isSeverityError: false,
|
|
5462
5478
|
errors: fieldErrors,
|
|
5463
|
-
validators: this.describeFieldValidators(field, visible, required)
|
|
5479
|
+
validators: this.describeFieldValidators(field, visible, required, fieldErrors)
|
|
5464
5480
|
};
|
|
5481
|
+
states[field.name].isSeverityError = states[field.name].validators.some(validator => validator.severity === 'error' && validator.valid === false);
|
|
5465
5482
|
}
|
|
5466
5483
|
return states;
|
|
5467
5484
|
}
|
|
5468
|
-
describeFieldValidators(field, visible, required) {
|
|
5485
|
+
describeFieldValidators(field, visible, required, fieldErrors) {
|
|
5469
5486
|
const validators = [];
|
|
5470
5487
|
const value = this.engine?.getValue(field.name);
|
|
5471
5488
|
const hasValue = !this.isValidationEmpty(value);
|
|
5489
|
+
const ruleOutcomes = this.getRuleOutcomes(field);
|
|
5490
|
+
const requiredSeverity = ruleOutcomes.some(outcome => outcome.rule.severity === 'error' && outcome.nextAction === 'required');
|
|
5472
5491
|
if (this.hasRequiredValidation(field) || required) {
|
|
5492
|
+
const message = 'This field is required.';
|
|
5473
5493
|
validators.push({
|
|
5474
5494
|
name: 'required',
|
|
5475
5495
|
source: 'required',
|
|
5476
5496
|
active: visible && required,
|
|
5477
|
-
|
|
5497
|
+
valid: !fieldErrors.includes(message),
|
|
5498
|
+
message,
|
|
5499
|
+
...(requiredSeverity ? { severity: 'error' } : {})
|
|
5478
5500
|
});
|
|
5479
5501
|
}
|
|
5480
5502
|
if (field.html5?.minLength !== undefined) {
|
|
5503
|
+
const message = `Minimum length is ${field.html5.minLength}.`;
|
|
5481
5504
|
validators.push({
|
|
5482
5505
|
name: 'minLength',
|
|
5483
5506
|
source: 'html5',
|
|
5484
5507
|
active: visible && hasValue,
|
|
5485
|
-
|
|
5508
|
+
valid: !fieldErrors.includes(message),
|
|
5509
|
+
value: field.html5.minLength,
|
|
5510
|
+
message
|
|
5486
5511
|
});
|
|
5487
5512
|
}
|
|
5488
5513
|
if (field.html5?.maxLength !== undefined) {
|
|
5514
|
+
const message = `Maximum length is ${field.html5.maxLength}.`;
|
|
5489
5515
|
validators.push({
|
|
5490
5516
|
name: 'maxLength',
|
|
5491
5517
|
source: 'html5',
|
|
5492
5518
|
active: visible && hasValue,
|
|
5493
|
-
|
|
5519
|
+
valid: !fieldErrors.includes(message),
|
|
5520
|
+
value: field.html5.maxLength,
|
|
5521
|
+
message
|
|
5494
5522
|
});
|
|
5495
5523
|
}
|
|
5496
5524
|
if (field.html5?.min !== undefined) {
|
|
5525
|
+
const message = `Minimum value is ${field.html5.min}.`;
|
|
5497
5526
|
validators.push({
|
|
5498
5527
|
name: 'min',
|
|
5499
5528
|
source: 'html5',
|
|
5500
5529
|
active: visible && hasValue,
|
|
5501
|
-
|
|
5530
|
+
valid: !fieldErrors.includes(message),
|
|
5531
|
+
value: field.html5.min,
|
|
5532
|
+
message
|
|
5502
5533
|
});
|
|
5503
5534
|
}
|
|
5504
5535
|
if (field.html5?.max !== undefined) {
|
|
5536
|
+
const message = `Maximum value is ${field.html5.max}.`;
|
|
5505
5537
|
validators.push({
|
|
5506
5538
|
name: 'max',
|
|
5507
5539
|
source: 'html5',
|
|
5508
5540
|
active: visible && hasValue,
|
|
5509
|
-
|
|
5541
|
+
valid: !fieldErrors.includes(message),
|
|
5542
|
+
value: field.html5.max,
|
|
5543
|
+
message
|
|
5510
5544
|
});
|
|
5511
5545
|
}
|
|
5512
5546
|
if (field.html5?.pattern) {
|
|
5547
|
+
const message = 'Invalid format.';
|
|
5513
5548
|
validators.push({
|
|
5514
5549
|
name: 'pattern',
|
|
5515
5550
|
source: 'html5',
|
|
5516
5551
|
active: visible && hasValue,
|
|
5517
|
-
|
|
5552
|
+
valid: !fieldErrors.includes(message),
|
|
5553
|
+
value: field.html5.pattern,
|
|
5554
|
+
message
|
|
5518
5555
|
});
|
|
5519
5556
|
}
|
|
5520
|
-
for (const
|
|
5557
|
+
for (const outcome of ruleOutcomes) {
|
|
5558
|
+
const message = this.getRuleValidationMessage(outcome.rule);
|
|
5521
5559
|
validators.push({
|
|
5522
|
-
name: rule.
|
|
5523
|
-
source: '
|
|
5524
|
-
active:
|
|
5525
|
-
|
|
5526
|
-
|
|
5560
|
+
name: outcome.rule.name?.trim() || this.describeRuleName(outcome.rule),
|
|
5561
|
+
source: 'rule',
|
|
5562
|
+
active: true,
|
|
5563
|
+
valid: outcome.conditionMet || outcome.nextAction !== undefined,
|
|
5564
|
+
value: {
|
|
5565
|
+
action: outcome.rule.action,
|
|
5566
|
+
elseAction: outcome.rule.elseAction
|
|
5567
|
+
},
|
|
5568
|
+
message,
|
|
5569
|
+
...(outcome.rule.severity ? { severity: outcome.rule.severity } : {})
|
|
5527
5570
|
});
|
|
5528
5571
|
}
|
|
5529
5572
|
return validators;
|
|
@@ -5542,16 +5585,30 @@ class JsonFormRendererComponent {
|
|
|
5542
5585
|
}
|
|
5543
5586
|
return false;
|
|
5544
5587
|
}
|
|
5545
|
-
|
|
5546
|
-
if (!
|
|
5547
|
-
return
|
|
5548
|
-
try {
|
|
5549
|
-
const checkFn = new Function('form', `return ${rule.when}`);
|
|
5550
|
-
return checkFn(this.engine?.getValues() ?? {});
|
|
5588
|
+
getRuleOutcomes(field) {
|
|
5589
|
+
if (!field.rules?.length) {
|
|
5590
|
+
return [];
|
|
5551
5591
|
}
|
|
5552
|
-
|
|
5553
|
-
|
|
5592
|
+
const schema = this.engine?.getSchema() ?? this.schema;
|
|
5593
|
+
const formValues = this.engine?.getValues() ?? {};
|
|
5594
|
+
return field.rules.map(rule => {
|
|
5595
|
+
const conditionMet = this.ruleEvaluationService.evaluateRule(rule, formValues, schema?.fields ?? []);
|
|
5596
|
+
return {
|
|
5597
|
+
rule,
|
|
5598
|
+
conditionMet,
|
|
5599
|
+
nextAction: conditionMet ? rule.action : rule.elseAction
|
|
5600
|
+
};
|
|
5601
|
+
});
|
|
5602
|
+
}
|
|
5603
|
+
describeRuleName(rule) {
|
|
5604
|
+
return rule.action.charAt(0).toUpperCase() + rule.action.slice(1);
|
|
5605
|
+
}
|
|
5606
|
+
getRuleValidationMessage(rule) {
|
|
5607
|
+
const name = rule.name?.trim();
|
|
5608
|
+
if (name) {
|
|
5609
|
+
return name;
|
|
5554
5610
|
}
|
|
5611
|
+
return `Rule "${rule.action}" failed.`;
|
|
5555
5612
|
}
|
|
5556
5613
|
isValidationEmpty(value) {
|
|
5557
5614
|
return value === null
|
|
@@ -10271,13 +10328,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
10271
10328
|
class DynamicPropertiesComponent {
|
|
10272
10329
|
onPropertyChange;
|
|
10273
10330
|
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
10331
|
get properties() {
|
|
10282
10332
|
if (!this.config)
|
|
10283
10333
|
return [];
|
|
@@ -10609,68 +10659,6 @@ class DynamicPropertiesComponent {
|
|
|
10609
10659
|
this.setValue(path, options);
|
|
10610
10660
|
}
|
|
10611
10661
|
}
|
|
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
10662
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DynamicPropertiesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10675
10663
|
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
10664
|
<div class="dynamic-properties flex flex-col font-sans text-sm">
|
|
@@ -10813,51 +10801,6 @@ class DynamicPropertiesComponent {
|
|
|
10813
10801
|
</div>
|
|
10814
10802
|
</ui-field-wrapper>
|
|
10815
10803
|
|
|
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
10804
|
<!-- Field Reference -->
|
|
10862
10805
|
<ui-field-wrapper *ngIf="field.type === 'field-reference'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
10863
10806
|
<select [ngModel]="getValue(field.key) || ''"
|
|
@@ -11106,51 +11049,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
11106
11049
|
</div>
|
|
11107
11050
|
</ui-field-wrapper>
|
|
11108
11051
|
|
|
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
11052
|
<!-- Field Reference -->
|
|
11155
11053
|
<ui-field-wrapper *ngIf="field.type === 'field-reference'" [label]="field.label || ''" [helpText]="field.helpText || ''">
|
|
11156
11054
|
<select [ngModel]="getValue(field.key) || ''"
|
|
@@ -15261,7 +15159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
15261
15159
|
type: Output
|
|
15262
15160
|
}] } });
|
|
15263
15161
|
|
|
15264
|
-
function parsePathSegments$
|
|
15162
|
+
function parsePathSegments$3(path) {
|
|
15265
15163
|
const segments = [];
|
|
15266
15164
|
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
15267
15165
|
let match;
|
|
@@ -15277,14 +15175,14 @@ function parsePathSegments$2(path) {
|
|
|
15277
15175
|
}
|
|
15278
15176
|
return segments;
|
|
15279
15177
|
}
|
|
15280
|
-
function resolvePathValue$
|
|
15178
|
+
function resolvePathValue$2(value, path) {
|
|
15281
15179
|
if (!path)
|
|
15282
15180
|
return value;
|
|
15283
15181
|
const normalized = path.trim();
|
|
15284
15182
|
if (!normalized)
|
|
15285
15183
|
return value;
|
|
15286
15184
|
let current = value;
|
|
15287
|
-
for (const segment of parsePathSegments$
|
|
15185
|
+
for (const segment of parsePathSegments$3(normalized)) {
|
|
15288
15186
|
if (current === null || current === undefined)
|
|
15289
15187
|
return undefined;
|
|
15290
15188
|
if (Array.isArray(current)) {
|
|
@@ -15301,7 +15199,7 @@ function resolvePathValue$1(value, path) {
|
|
|
15301
15199
|
return current;
|
|
15302
15200
|
}
|
|
15303
15201
|
function assignPathValue(target, path, value) {
|
|
15304
|
-
const segments = parsePathSegments$
|
|
15202
|
+
const segments = parsePathSegments$3(path);
|
|
15305
15203
|
if (!segments.length) {
|
|
15306
15204
|
return;
|
|
15307
15205
|
}
|
|
@@ -15437,7 +15335,6 @@ class DataPanelComponent {
|
|
|
15437
15335
|
selectionFieldId;
|
|
15438
15336
|
selectionMatchPath;
|
|
15439
15337
|
childRowsPath;
|
|
15440
|
-
formatNumericOptionLabels = false;
|
|
15441
15338
|
optionLabelPrefixPath;
|
|
15442
15339
|
rootPathOptions = [];
|
|
15443
15340
|
rowPathOptions = [];
|
|
@@ -15679,7 +15576,6 @@ class DataPanelComponent {
|
|
|
15679
15576
|
this.selectionFieldId = undefined;
|
|
15680
15577
|
this.selectionMatchPath = undefined;
|
|
15681
15578
|
this.childRowsPath = undefined;
|
|
15682
|
-
this.formatNumericOptionLabels = false;
|
|
15683
15579
|
this.optionLabelPrefixPath = undefined;
|
|
15684
15580
|
this.rootPathOptions = [];
|
|
15685
15581
|
this.rowPathOptions = [];
|
|
@@ -15721,7 +15617,6 @@ class DataPanelComponent {
|
|
|
15721
15617
|
this.selectionFieldId = d.selectionFieldId;
|
|
15722
15618
|
this.selectionMatchPath = d.selectionMatchPath;
|
|
15723
15619
|
this.childRowsPath = d.childRowsPath;
|
|
15724
|
-
this.formatNumericOptionLabels = d.formatNumericOptionLabels === true;
|
|
15725
15620
|
this.optionLabelPrefixPath = d.optionLabelPrefixPath;
|
|
15726
15621
|
// Search
|
|
15727
15622
|
this.searchEnabled = !!d.searchEnabled;
|
|
@@ -15774,10 +15669,7 @@ class DataPanelComponent {
|
|
|
15774
15669
|
labelKey: this.sourceType === 'source' ? this.labelKey : undefined,
|
|
15775
15670
|
valueKey: this.sourceType === 'source' ? this.valueKey : undefined,
|
|
15776
15671
|
rowsPath: this.sourceType === 'source' ? this.normalizedRowsPath() : undefined,
|
|
15777
|
-
|
|
15778
|
-
? this.formatNumericOptionLabels
|
|
15779
|
-
: undefined,
|
|
15780
|
-
optionLabelPrefixPath: this.shouldPersistOptionLabelFormatting()
|
|
15672
|
+
optionLabelPrefixPath: this.shouldPersistOptionLabelPrefix()
|
|
15781
15673
|
? this.optionLabelPrefixPath
|
|
15782
15674
|
: undefined,
|
|
15783
15675
|
rowSelectionMode: this.sourceType === 'source' && this.bindingShape === 'scalar' && this.rowSelectionMode === 'selected'
|
|
@@ -15896,9 +15788,6 @@ class DataPanelComponent {
|
|
|
15896
15788
|
&& this.bindingShape === 'scalar'
|
|
15897
15789
|
&& (this.widgetType === 'text' || this.widgetType === 'number');
|
|
15898
15790
|
}
|
|
15899
|
-
supportsNumericDisplayFormatting() {
|
|
15900
|
-
return this.widgetType === 'select' || this.widgetType === 'number';
|
|
15901
|
-
}
|
|
15902
15791
|
displayFormattingTitle() {
|
|
15903
15792
|
return this.widgetType === 'select' ? 'Amount Display' : 'Field Display';
|
|
15904
15793
|
}
|
|
@@ -15907,15 +15796,10 @@ class DataPanelComponent {
|
|
|
15907
15796
|
return 'Format the visible dropdown label without changing the stored option value.';
|
|
15908
15797
|
}
|
|
15909
15798
|
if (this.widgetType === 'number') {
|
|
15910
|
-
return 'Show a fixed prefix
|
|
15799
|
+
return 'Show a fixed prefix in the visible field value without changing the stored number.';
|
|
15911
15800
|
}
|
|
15912
15801
|
return 'Show a fixed prefix beside the editable value without changing the stored field value.';
|
|
15913
15802
|
}
|
|
15914
|
-
numericDisplayFormattingLabel() {
|
|
15915
|
-
return this.widgetType === 'select'
|
|
15916
|
-
? 'Show thousand separators for numeric labels'
|
|
15917
|
-
: 'Show thousand separators for numeric values';
|
|
15918
|
-
}
|
|
15919
15803
|
showStaticOptionsEditor() {
|
|
15920
15804
|
return this.sourceType === 'static' && this.widgetType !== 'table' && this.usesOptionMapping();
|
|
15921
15805
|
}
|
|
@@ -15944,12 +15828,12 @@ class DataPanelComponent {
|
|
|
15944
15828
|
}
|
|
15945
15829
|
getPreviewLabel(row) {
|
|
15946
15830
|
const key = this.labelKey || 'label';
|
|
15947
|
-
const value = resolvePathValue$
|
|
15831
|
+
const value = resolvePathValue$2(row, key);
|
|
15948
15832
|
return value === undefined || value === null || value === '' ? '(no label)' : String(value);
|
|
15949
15833
|
}
|
|
15950
15834
|
getPreviewValue(row) {
|
|
15951
15835
|
const key = this.valueKey || 'value';
|
|
15952
|
-
const value = resolvePathValue$
|
|
15836
|
+
const value = resolvePathValue$2(row, key);
|
|
15953
15837
|
return value === undefined || value === null ? '' : String(value);
|
|
15954
15838
|
}
|
|
15955
15839
|
availableRootPaths() {
|
|
@@ -15966,7 +15850,7 @@ class DataPanelComponent {
|
|
|
15966
15850
|
const sample = this.extractPreviewRows(this.previewRows, this.effectiveRowsPath())[0];
|
|
15967
15851
|
return sample ? collectArrayPaths(sample) : [];
|
|
15968
15852
|
}
|
|
15969
|
-
|
|
15853
|
+
shouldPersistOptionLabelPrefix() {
|
|
15970
15854
|
if (this.widgetType === 'select' && this.usesOptionMapping()) {
|
|
15971
15855
|
return true;
|
|
15972
15856
|
}
|
|
@@ -15982,7 +15866,7 @@ class DataPanelComponent {
|
|
|
15982
15866
|
return normalized ? normalized : 'defaultValue';
|
|
15983
15867
|
}
|
|
15984
15868
|
readScalarTargetValue() {
|
|
15985
|
-
const resolved = resolvePathValue$
|
|
15869
|
+
const resolved = resolvePathValue$2(this.config, this.scalarTargetPath());
|
|
15986
15870
|
if (resolved !== undefined) {
|
|
15987
15871
|
return resolved;
|
|
15988
15872
|
}
|
|
@@ -16005,7 +15889,7 @@ class DataPanelComponent {
|
|
|
16005
15889
|
}
|
|
16006
15890
|
const flattened = [];
|
|
16007
15891
|
for (const row of rows) {
|
|
16008
|
-
const resolved = resolvePathValue$
|
|
15892
|
+
const resolved = resolvePathValue$2(row, normalizedPath);
|
|
16009
15893
|
if (Array.isArray(resolved)) {
|
|
16010
15894
|
flattened.push(...resolved);
|
|
16011
15895
|
continue;
|
|
@@ -16297,15 +16181,6 @@ class DataPanelComponent {
|
|
|
16297
16181
|
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16298
16182
|
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16299
16183
|
|
|
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
16184
|
<div class="mt-3 flex flex-col gap-1">
|
|
16310
16185
|
<label class="text-xs font-medium text-gray-500">Prefix Key</label>
|
|
16311
16186
|
<input
|
|
@@ -16916,15 +16791,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
16916
16791
|
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500">{{ displayFormattingTitle() }}</div>
|
|
16917
16792
|
<div class="mt-1 text-[11px] text-gray-500">{{ displayFormattingDescription() }}</div>
|
|
16918
16793
|
|
|
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
16794
|
<div class="mt-3 flex flex-col gap-1">
|
|
16929
16795
|
<label class="text-xs font-medium text-gray-500">Prefix Key</label>
|
|
16930
16796
|
<input
|
|
@@ -17866,7 +17732,7 @@ class RulesPanelComponent {
|
|
|
17866
17732
|
<div class="flex flex-col gap-2">
|
|
17867
17733
|
<div class="flex items-center gap-2 bg-amber-50 p-2 rounded-md border border-amber-100">
|
|
17868
17734
|
<span class="text-xs font-semibold text-amber-700 uppercase">Severity</span>
|
|
17869
|
-
<span class="text-xs text-amber-800 italic">
|
|
17735
|
+
<span class="text-xs text-amber-800 italic">Error severity is emitted in runtime validation; warn stays informational.</span>
|
|
17870
17736
|
</div>
|
|
17871
17737
|
|
|
17872
17738
|
<div class="flex items-center gap-2">
|
|
@@ -17988,7 +17854,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
17988
17854
|
<div class="flex flex-col gap-2">
|
|
17989
17855
|
<div class="flex items-center gap-2 bg-amber-50 p-2 rounded-md border border-amber-100">
|
|
17990
17856
|
<span class="text-xs font-semibold text-amber-700 uppercase">Severity</span>
|
|
17991
|
-
<span class="text-xs text-amber-800 italic">
|
|
17857
|
+
<span class="text-xs text-amber-800 italic">Error severity is emitted in runtime validation; warn stays informational.</span>
|
|
17992
17858
|
</div>
|
|
17993
17859
|
|
|
17994
17860
|
<div class="flex items-center gap-2">
|
|
@@ -20255,13 +20121,13 @@ async function updateFieldSettings(state, args, widgetDefs = []) {
|
|
|
20255
20121
|
updates[key] = value;
|
|
20256
20122
|
}
|
|
20257
20123
|
}
|
|
20124
|
+
const html5Patch = {};
|
|
20258
20125
|
if (typeof a['disabled'] === 'boolean') {
|
|
20259
|
-
|
|
20126
|
+
html5Patch['disabled'] = a['disabled'];
|
|
20260
20127
|
}
|
|
20261
20128
|
if (typeof a['readonly'] === 'boolean') {
|
|
20262
|
-
|
|
20129
|
+
html5Patch['readonly'] = a['readonly'];
|
|
20263
20130
|
}
|
|
20264
|
-
const html5Patch = {};
|
|
20265
20131
|
const html5Keys = ['required', 'min', 'max', 'step', 'minLength', 'maxLength', 'pattern'];
|
|
20266
20132
|
for (const key of html5Keys) {
|
|
20267
20133
|
if (typeof a[key] !== 'undefined') {
|
|
@@ -22071,7 +21937,7 @@ const DATA_SOURCES_TEMPLATE = {
|
|
|
22071
21937
|
"type": "text",
|
|
22072
21938
|
"label": "Selected country code",
|
|
22073
21939
|
"placeholder": "Auto-filled",
|
|
22074
|
-
"readonly": true,
|
|
21940
|
+
"html5": { "readonly": true },
|
|
22075
21941
|
"helpText": "Updated by an event binding on the Country field."
|
|
22076
21942
|
},
|
|
22077
21943
|
{
|
|
@@ -22477,8 +22343,8 @@ const TRANSACTION_KYC_REVIEW_TEMPLATE = {
|
|
|
22477
22343
|
"name": "clientDisplay",
|
|
22478
22344
|
"type": "text",
|
|
22479
22345
|
"label": "Client",
|
|
22480
|
-
"readonly": true,
|
|
22481
22346
|
"html5": {
|
|
22347
|
+
"readonly": true,
|
|
22482
22348
|
"required": false
|
|
22483
22349
|
},
|
|
22484
22350
|
"rules": [
|
|
@@ -22524,7 +22390,7 @@ const TRANSACTION_KYC_REVIEW_TEMPLATE = {
|
|
|
22524
22390
|
"type": "text",
|
|
22525
22391
|
"label": "Balance",
|
|
22526
22392
|
"defaultValue": "USD 24,580.00",
|
|
22527
|
-
"readonly": true,
|
|
22393
|
+
"html5": { "readonly": true },
|
|
22528
22394
|
"rules": [
|
|
22529
22395
|
{
|
|
22530
22396
|
"id": "rule_balance_visible",
|
|
@@ -23292,7 +23158,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_TWO = {
|
|
|
23292
23158
|
"name": "summaryCountryCode",
|
|
23293
23159
|
"type": "text",
|
|
23294
23160
|
"label": "Country Code",
|
|
23295
|
-
"readonly": true,
|
|
23161
|
+
"html5": { "readonly": true },
|
|
23296
23162
|
"dataConfig": {
|
|
23297
23163
|
"type": "source",
|
|
23298
23164
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -23497,7 +23363,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_THREE = {
|
|
|
23497
23363
|
"name": "summaryCurrency",
|
|
23498
23364
|
"type": "text",
|
|
23499
23365
|
"label": "Currency",
|
|
23500
|
-
"readonly": true,
|
|
23366
|
+
"html5": { "readonly": true },
|
|
23501
23367
|
"dataConfig": {
|
|
23502
23368
|
"type": "source",
|
|
23503
23369
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -23510,7 +23376,7 @@ const JOURNEY_BRANCHING_TEMPLATE_STEP_THREE = {
|
|
|
23510
23376
|
"name": "summaryTimezone",
|
|
23511
23377
|
"type": "text",
|
|
23512
23378
|
"label": "Timezone",
|
|
23513
|
-
"readonly": true,
|
|
23379
|
+
"html5": { "readonly": true },
|
|
23514
23380
|
"dataConfig": {
|
|
23515
23381
|
"type": "source",
|
|
23516
23382
|
"datasourceId": "journey_branch_ds_country_profile",
|
|
@@ -31742,7 +31608,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
31742
31608
|
}]
|
|
31743
31609
|
}] });
|
|
31744
31610
|
|
|
31745
|
-
function parsePathSegments$
|
|
31611
|
+
function parsePathSegments$2(path) {
|
|
31746
31612
|
const segments = [];
|
|
31747
31613
|
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
31748
31614
|
let match;
|
|
@@ -31758,14 +31624,14 @@ function parsePathSegments$1(path) {
|
|
|
31758
31624
|
}
|
|
31759
31625
|
return segments;
|
|
31760
31626
|
}
|
|
31761
|
-
function resolvePathValue(value, path) {
|
|
31627
|
+
function resolvePathValue$1(value, path) {
|
|
31762
31628
|
if (!path)
|
|
31763
31629
|
return value;
|
|
31764
31630
|
const normalizedPath = path.trim();
|
|
31765
31631
|
if (!normalizedPath)
|
|
31766
31632
|
return value;
|
|
31767
31633
|
let current = value;
|
|
31768
|
-
for (const segment of parsePathSegments$
|
|
31634
|
+
for (const segment of parsePathSegments$2(normalizedPath)) {
|
|
31769
31635
|
if (current === null || current === undefined) {
|
|
31770
31636
|
return undefined;
|
|
31771
31637
|
}
|
|
@@ -31789,7 +31655,7 @@ function hasPathSyntax(path) {
|
|
|
31789
31655
|
return false;
|
|
31790
31656
|
return path.includes('.') || path.includes('[');
|
|
31791
31657
|
}
|
|
31792
|
-
function valuesMatch(left, right) {
|
|
31658
|
+
function valuesMatch$1(left, right) {
|
|
31793
31659
|
if (Object.is(left, right))
|
|
31794
31660
|
return true;
|
|
31795
31661
|
if (left === undefined || left === null || right === undefined || right === null)
|
|
@@ -31845,8 +31711,8 @@ class DataProvider {
|
|
|
31845
31711
|
if (query.sort && query.sort.length > 0) {
|
|
31846
31712
|
rows = [...rows].sort((a, b) => {
|
|
31847
31713
|
for (const s of query.sort) {
|
|
31848
|
-
const valA = resolvePathValue(a, s.column);
|
|
31849
|
-
const valB = resolvePathValue(b, s.column);
|
|
31714
|
+
const valA = resolvePathValue$1(a, s.column);
|
|
31715
|
+
const valB = resolvePathValue$1(b, s.column);
|
|
31850
31716
|
if (valA === valB)
|
|
31851
31717
|
continue;
|
|
31852
31718
|
const result = compareSortableValues(valA, valB);
|
|
@@ -32006,12 +31872,12 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32006
31872
|
}
|
|
32007
31873
|
const row = context.row;
|
|
32008
31874
|
const resolvedPath = cfg.valueKey;
|
|
32009
|
-
const resolvedValue = resolvePathValue(row, resolvedPath);
|
|
31875
|
+
const resolvedValue = resolvePathValue$1(row, resolvedPath);
|
|
32010
31876
|
if (resolvedPath && resolvedValue !== undefined) {
|
|
32011
31877
|
return resolvedValue;
|
|
32012
31878
|
}
|
|
32013
|
-
if (resolvePathValue(row, 'value') !== undefined) {
|
|
32014
|
-
return resolvePathValue(row, 'value');
|
|
31879
|
+
if (resolvePathValue$1(row, 'value') !== undefined) {
|
|
31880
|
+
return resolvePathValue$1(row, 'value');
|
|
32015
31881
|
}
|
|
32016
31882
|
return row;
|
|
32017
31883
|
}
|
|
@@ -32028,7 +31894,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32028
31894
|
for (const candidate of [context.row, context.parentRow, context.sourceRow]) {
|
|
32029
31895
|
if (!candidate)
|
|
32030
31896
|
continue;
|
|
32031
|
-
const resolved = resolvePathValue(candidate, prefixPath);
|
|
31897
|
+
const resolved = resolvePathValue$1(candidate, prefixPath);
|
|
32032
31898
|
const value = toDisplayText(resolved);
|
|
32033
31899
|
if (value) {
|
|
32034
31900
|
return value;
|
|
@@ -32131,7 +31997,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32131
31997
|
}
|
|
32132
31998
|
const flattened = [];
|
|
32133
31999
|
for (const row of rows) {
|
|
32134
|
-
const resolved = resolvePathValue(row, normalizedPath);
|
|
32000
|
+
const resolved = resolvePathValue$1(row, normalizedPath);
|
|
32135
32001
|
if (Array.isArray(resolved)) {
|
|
32136
32002
|
for (const entry of resolved) {
|
|
32137
32003
|
flattened.push({
|
|
@@ -32159,7 +32025,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32159
32025
|
}
|
|
32160
32026
|
const flattened = [];
|
|
32161
32027
|
for (const row of rows) {
|
|
32162
|
-
const resolved = resolvePathValue(row, normalizedPath);
|
|
32028
|
+
const resolved = resolvePathValue$1(row, normalizedPath);
|
|
32163
32029
|
if (Array.isArray(resolved)) {
|
|
32164
32030
|
for (const entry of resolved) {
|
|
32165
32031
|
flattened.push(this.toRowRecord(entry));
|
|
@@ -32187,7 +32053,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32187
32053
|
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32188
32054
|
return undefined;
|
|
32189
32055
|
}
|
|
32190
|
-
return rows.find(row => valuesMatch(resolvePathValue(row, cfg.selectionMatchPath), selectorValue));
|
|
32056
|
+
return rows.find(row => valuesMatch$1(resolvePathValue$1(row, cfg.selectionMatchPath), selectorValue));
|
|
32191
32057
|
}
|
|
32192
32058
|
selectOptionContext(contexts, cfg, engine) {
|
|
32193
32059
|
if (contexts.length === 0)
|
|
@@ -32204,7 +32070,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32204
32070
|
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32205
32071
|
return undefined;
|
|
32206
32072
|
}
|
|
32207
|
-
return contexts.find(context => valuesMatch(resolvePathValue(context.row, cfg.selectionMatchPath), selectorValue));
|
|
32073
|
+
return contexts.find(context => valuesMatch$1(resolvePathValue$1(context.row, cfg.selectionMatchPath), selectorValue));
|
|
32208
32074
|
}
|
|
32209
32075
|
applyRowFilters(rows, filters, engine) {
|
|
32210
32076
|
if (!filters || filters.length === 0)
|
|
@@ -32221,7 +32087,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32221
32087
|
const expected = this.resolveFilterValue(filter, engine);
|
|
32222
32088
|
if (expected === undefined)
|
|
32223
32089
|
return true;
|
|
32224
|
-
const actual = resolvePathValue(row, filter.column);
|
|
32090
|
+
const actual = resolvePathValue$1(row, filter.column);
|
|
32225
32091
|
const val = expected;
|
|
32226
32092
|
switch (filter.op) {
|
|
32227
32093
|
case 'eq': return actual === val;
|
|
@@ -32293,17 +32159,16 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32293
32159
|
}
|
|
32294
32160
|
mapRowToOption(row, labelKey, valueKey) {
|
|
32295
32161
|
return {
|
|
32296
|
-
label: String(resolvePathValue(row, labelKey) ?? ''),
|
|
32297
|
-
value: this.toOptionValue(resolvePathValue(row, valueKey))
|
|
32162
|
+
label: String(resolvePathValue$1(row, labelKey) ?? ''),
|
|
32163
|
+
value: this.toOptionValue(resolvePathValue$1(row, valueKey))
|
|
32298
32164
|
};
|
|
32299
32165
|
}
|
|
32300
32166
|
mapContextToOption(context, labelKey, valueKey, cfg) {
|
|
32301
|
-
const rawLabel = String(resolvePathValue(context.row, labelKey) ?? '');
|
|
32302
32167
|
const prefix = this.resolveOptionLabelPrefix(context, cfg);
|
|
32303
|
-
const label = this.formatOptionLabel(rawLabel, cfg);
|
|
32304
32168
|
return {
|
|
32305
|
-
label:
|
|
32306
|
-
|
|
32169
|
+
label: String(resolvePathValue$1(context.row, labelKey) ?? ''),
|
|
32170
|
+
displayPrefix: prefix || undefined,
|
|
32171
|
+
value: this.toOptionValue(resolvePathValue$1(context.row, valueKey))
|
|
32307
32172
|
};
|
|
32308
32173
|
}
|
|
32309
32174
|
resolveOptionLabelPrefix(context, cfg) {
|
|
@@ -32314,7 +32179,7 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32314
32179
|
for (const candidate of [context.row, context.parentRow, context.sourceRow]) {
|
|
32315
32180
|
if (!candidate)
|
|
32316
32181
|
continue;
|
|
32317
|
-
const resolved = resolvePathValue(candidate, prefixPath);
|
|
32182
|
+
const resolved = resolvePathValue$1(candidate, prefixPath);
|
|
32318
32183
|
const value = toDisplayText(resolved);
|
|
32319
32184
|
if (value) {
|
|
32320
32185
|
return value;
|
|
@@ -32322,29 +32187,6 @@ class DefaultDataProvider extends DataProvider {
|
|
|
32322
32187
|
}
|
|
32323
32188
|
return '';
|
|
32324
32189
|
}
|
|
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
32190
|
async getRuntimeOptions(field, engine) {
|
|
32349
32191
|
if (!engine)
|
|
32350
32192
|
return undefined;
|
|
@@ -32503,6 +32345,60 @@ function getHeadingClass(level) {
|
|
|
32503
32345
|
}
|
|
32504
32346
|
}
|
|
32505
32347
|
|
|
32348
|
+
function parsePathSegments$1(path) {
|
|
32349
|
+
const segments = [];
|
|
32350
|
+
const matcher = /([^[.\]]+)|\[(\d+)\]/g;
|
|
32351
|
+
let match;
|
|
32352
|
+
while ((match = matcher.exec(path)) !== null) {
|
|
32353
|
+
const [, property, index] = match;
|
|
32354
|
+
if (property) {
|
|
32355
|
+
segments.push(property);
|
|
32356
|
+
continue;
|
|
32357
|
+
}
|
|
32358
|
+
if (index !== undefined) {
|
|
32359
|
+
segments.push(index);
|
|
32360
|
+
}
|
|
32361
|
+
}
|
|
32362
|
+
return segments;
|
|
32363
|
+
}
|
|
32364
|
+
function resolvePathValue(value, path) {
|
|
32365
|
+
if (!path)
|
|
32366
|
+
return value;
|
|
32367
|
+
const normalizedPath = path.trim();
|
|
32368
|
+
if (!normalizedPath)
|
|
32369
|
+
return value;
|
|
32370
|
+
let current = value;
|
|
32371
|
+
for (const segment of parsePathSegments$1(normalizedPath)) {
|
|
32372
|
+
if (current === null || current === undefined) {
|
|
32373
|
+
return undefined;
|
|
32374
|
+
}
|
|
32375
|
+
if (Array.isArray(current)) {
|
|
32376
|
+
const index = Number(segment);
|
|
32377
|
+
if (!Number.isInteger(index)) {
|
|
32378
|
+
return undefined;
|
|
32379
|
+
}
|
|
32380
|
+
current = current[index];
|
|
32381
|
+
continue;
|
|
32382
|
+
}
|
|
32383
|
+
if (typeof current !== 'object') {
|
|
32384
|
+
return undefined;
|
|
32385
|
+
}
|
|
32386
|
+
current = current[segment];
|
|
32387
|
+
}
|
|
32388
|
+
return current;
|
|
32389
|
+
}
|
|
32390
|
+
function valuesMatch(left, right) {
|
|
32391
|
+
if (Object.is(left, right))
|
|
32392
|
+
return true;
|
|
32393
|
+
if (left === undefined || left === null || right === undefined || right === null)
|
|
32394
|
+
return false;
|
|
32395
|
+
const leftIsPrimitive = typeof left === 'string' || typeof left === 'number' || typeof left === 'boolean';
|
|
32396
|
+
const rightIsPrimitive = typeof right === 'string' || typeof right === 'number' || typeof right === 'boolean';
|
|
32397
|
+
if (leftIsPrimitive && rightIsPrimitive) {
|
|
32398
|
+
return String(left) === String(right);
|
|
32399
|
+
}
|
|
32400
|
+
return false;
|
|
32401
|
+
}
|
|
32506
32402
|
class TextFieldWidgetComponent {
|
|
32507
32403
|
_config;
|
|
32508
32404
|
hasReceivedConfig = false;
|
|
@@ -32552,7 +32448,7 @@ class TextFieldWidgetComponent {
|
|
|
32552
32448
|
return this.config?.type === 'color';
|
|
32553
32449
|
}
|
|
32554
32450
|
usesFormattedNumberInput() {
|
|
32555
|
-
return this.config?.type === 'number' && this.config
|
|
32451
|
+
return this.config?.type === 'number' && usesFieldThousandSeparator(this.config);
|
|
32556
32452
|
}
|
|
32557
32453
|
hasDisplayPrefix() {
|
|
32558
32454
|
return !this.isTextarea() && !this.isColorField() && this.displayPrefix.trim().length > 0;
|
|
@@ -32609,7 +32505,7 @@ class TextFieldWidgetComponent {
|
|
|
32609
32505
|
const datasourceId = this.config?.dataConfig?.datasourceId;
|
|
32610
32506
|
if (!datasourceId || update.datasourceId !== datasourceId)
|
|
32611
32507
|
return;
|
|
32612
|
-
void this.refreshValueFromDataSource();
|
|
32508
|
+
void this.refreshValueFromDataSource(true);
|
|
32613
32509
|
});
|
|
32614
32510
|
}
|
|
32615
32511
|
this.engine.valueChanges$
|
|
@@ -32617,7 +32513,7 @@ class TextFieldWidgetComponent {
|
|
|
32617
32513
|
.subscribe(values => {
|
|
32618
32514
|
this.syncEnabledState();
|
|
32619
32515
|
if (this.haveDependencyValuesChanged(values)) {
|
|
32620
|
-
void this.refreshValueFromDataSource();
|
|
32516
|
+
void this.refreshValueFromDataSource(true);
|
|
32621
32517
|
}
|
|
32622
32518
|
});
|
|
32623
32519
|
// Listen for submit attempts to show validation errors
|
|
@@ -32711,7 +32607,7 @@ class TextFieldWidgetComponent {
|
|
|
32711
32607
|
return styles;
|
|
32712
32608
|
}
|
|
32713
32609
|
return mergeAndNormalize(styles, {
|
|
32714
|
-
paddingLeft: `calc(
|
|
32610
|
+
paddingLeft: `calc(25px + ${Math.max(this.displayPrefix.length, 1)}ch) !important`
|
|
32715
32611
|
});
|
|
32716
32612
|
}
|
|
32717
32613
|
hasWrapperFrame() {
|
|
@@ -32721,7 +32617,7 @@ class TextFieldWidgetComponent {
|
|
|
32721
32617
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
32722
32618
|
}
|
|
32723
32619
|
get enabled() {
|
|
32724
|
-
if (this.config
|
|
32620
|
+
if (isFieldDisabled(this.config))
|
|
32725
32621
|
return false;
|
|
32726
32622
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
32727
32623
|
}
|
|
@@ -32747,14 +32643,23 @@ class TextFieldWidgetComponent {
|
|
|
32747
32643
|
this.control.disable({ emitEvent: false });
|
|
32748
32644
|
}
|
|
32749
32645
|
}
|
|
32750
|
-
async refreshValueFromDataSource() {
|
|
32646
|
+
async refreshValueFromDataSource(clearWhenMissing = false) {
|
|
32751
32647
|
if (!this.dataProvider || !this.config.dataConfig)
|
|
32752
32648
|
return;
|
|
32753
32649
|
try {
|
|
32650
|
+
if (clearWhenMissing && !(await this.hasSelectedRowMatch())) {
|
|
32651
|
+
this.clearResolvedValue();
|
|
32652
|
+
return;
|
|
32653
|
+
}
|
|
32754
32654
|
const val = await this.dataProvider.getValue(this.config, this.engine);
|
|
32755
32655
|
this.displayPrefix = await this.dataProvider.getValueDisplayPrefix(this.config, this.engine);
|
|
32756
|
-
if (val === undefined || val === null)
|
|
32656
|
+
if (val === undefined || val === null) {
|
|
32657
|
+
if (!clearWhenMissing) {
|
|
32658
|
+
return;
|
|
32659
|
+
}
|
|
32660
|
+
this.clearResolvedValue();
|
|
32757
32661
|
return;
|
|
32662
|
+
}
|
|
32758
32663
|
this.control.setValue(val, { emitEvent: false });
|
|
32759
32664
|
this.syncFormattedNumberValue();
|
|
32760
32665
|
if (this.engine) {
|
|
@@ -32765,12 +32670,48 @@ class TextFieldWidgetComponent {
|
|
|
32765
32670
|
// Ignore failed datasource refreshes; field remains editable.
|
|
32766
32671
|
}
|
|
32767
32672
|
}
|
|
32673
|
+
clearResolvedValue() {
|
|
32674
|
+
this.displayPrefix = '';
|
|
32675
|
+
this.control.setValue(null, { emitEvent: false });
|
|
32676
|
+
this.syncFormattedNumberValue();
|
|
32677
|
+
if (this.engine) {
|
|
32678
|
+
this.engine.setValue(this.config.name, null);
|
|
32679
|
+
}
|
|
32680
|
+
}
|
|
32681
|
+
async hasSelectedRowMatch() {
|
|
32682
|
+
const cfg = this.config.dataConfig;
|
|
32683
|
+
if (!cfg
|
|
32684
|
+
|| cfg.rowSelectionMode !== 'selected'
|
|
32685
|
+
|| !cfg.selectionFieldId
|
|
32686
|
+
|| !cfg.selectionMatchPath
|
|
32687
|
+
|| !this.engine) {
|
|
32688
|
+
return true;
|
|
32689
|
+
}
|
|
32690
|
+
const selectorField = this.engine.getSchema().fields.find(field => field.id === cfg.selectionFieldId);
|
|
32691
|
+
if (!selectorField) {
|
|
32692
|
+
return false;
|
|
32693
|
+
}
|
|
32694
|
+
const selectorValue = this.engine.getValue(selectorField.name);
|
|
32695
|
+
if (selectorValue === undefined || selectorValue === null || selectorValue === '') {
|
|
32696
|
+
return false;
|
|
32697
|
+
}
|
|
32698
|
+
const rows = await this.dataProvider.getList(this.config, this.engine);
|
|
32699
|
+
return rows.some(row => valuesMatch(resolvePathValue(row, cfg.selectionMatchPath), selectorValue));
|
|
32700
|
+
}
|
|
32768
32701
|
getDataConfigSignature(config) {
|
|
32769
32702
|
if (!config)
|
|
32770
32703
|
return '';
|
|
32771
32704
|
const dataConfig = config.dataConfig;
|
|
32772
32705
|
if (!dataConfig) {
|
|
32773
|
-
return
|
|
32706
|
+
return [
|
|
32707
|
+
config.id,
|
|
32708
|
+
config.name,
|
|
32709
|
+
config.type,
|
|
32710
|
+
String(config.html5?.readonly ?? ''),
|
|
32711
|
+
String(config.html5?.disabled ?? ''),
|
|
32712
|
+
String(config.useThousandSeparator ?? ''),
|
|
32713
|
+
'no-data-config'
|
|
32714
|
+
].join('::');
|
|
32774
32715
|
}
|
|
32775
32716
|
const sourceKey = dataConfig.type === 'source' || dataConfig.type === 'global' || dataConfig.type === 'api'
|
|
32776
32717
|
? String(dataConfig.datasourceId ?? '')
|
|
@@ -32778,16 +32719,18 @@ class TextFieldWidgetComponent {
|
|
|
32778
32719
|
return [
|
|
32779
32720
|
config.id,
|
|
32780
32721
|
config.name,
|
|
32722
|
+
String(config.html5?.readonly ?? ''),
|
|
32723
|
+
String(config.html5?.disabled ?? ''),
|
|
32781
32724
|
dataConfig.type ?? '',
|
|
32782
32725
|
sourceKey,
|
|
32783
32726
|
String(dataConfig.valueKey ?? ''),
|
|
32784
32727
|
String(dataConfig.rowsPath ?? ''),
|
|
32785
|
-
String(dataConfig.formatNumericOptionLabels ?? ''),
|
|
32786
32728
|
String(dataConfig.optionLabelPrefixPath ?? ''),
|
|
32787
32729
|
String(dataConfig.optionLabelPrefixFieldId ?? ''),
|
|
32788
32730
|
String(dataConfig.rowSelectionMode ?? ''),
|
|
32789
32731
|
String(dataConfig.selectionFieldId ?? ''),
|
|
32790
32732
|
String(dataConfig.selectionMatchPath ?? ''),
|
|
32733
|
+
String(config.useThousandSeparator ?? ''),
|
|
32791
32734
|
(dataConfig.filters ?? []).map(filter => `${filter.column}:${filter.valueFrom ?? ''}:${filter.fieldId ?? ''}`).join('|')
|
|
32792
32735
|
].join('::');
|
|
32793
32736
|
}
|
|
@@ -32922,7 +32865,7 @@ class TextFieldWidgetComponent {
|
|
|
32922
32865
|
(blur)="onBlur()"
|
|
32923
32866
|
(mouseenter)="onMouseEnter()"
|
|
32924
32867
|
(mouseleave)="onMouseLeave()"
|
|
32925
|
-
[readonly]="config.readonly"
|
|
32868
|
+
[readonly]="config.html5?.readonly"
|
|
32926
32869
|
[attr.aria-required]="required"
|
|
32927
32870
|
[attr.aria-invalid]="!!error"
|
|
32928
32871
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -32943,7 +32886,7 @@ class TextFieldWidgetComponent {
|
|
|
32943
32886
|
(blur)="onBlur()"
|
|
32944
32887
|
(mouseenter)="onMouseEnter()"
|
|
32945
32888
|
(mouseleave)="onMouseLeave()"
|
|
32946
|
-
[readonly]="config.readonly"
|
|
32889
|
+
[readonly]="config.html5?.readonly"
|
|
32947
32890
|
[attr.aria-required]="required"
|
|
32948
32891
|
[attr.aria-invalid]="!!error"
|
|
32949
32892
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -32955,7 +32898,7 @@ class TextFieldWidgetComponent {
|
|
|
32955
32898
|
[cpAlphaChannel]="'disabled'"
|
|
32956
32899
|
[cpOutputFormat]="'hex'"
|
|
32957
32900
|
[cpFallbackColor]="'#000000'"
|
|
32958
|
-
[cpDisabled]="config.readonly || !enabled"
|
|
32901
|
+
[cpDisabled]="config.html5?.readonly || !enabled"
|
|
32959
32902
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
32960
32903
|
} @else if (usesFormattedNumberInput()) {
|
|
32961
32904
|
@if (hasDisplayPrefix()) {
|
|
@@ -32977,7 +32920,7 @@ class TextFieldWidgetComponent {
|
|
|
32977
32920
|
(blur)="onBlur()"
|
|
32978
32921
|
(mouseenter)="onMouseEnter()"
|
|
32979
32922
|
(mouseleave)="onMouseLeave()"
|
|
32980
|
-
[readonly]="config.readonly"
|
|
32923
|
+
[readonly]="config.html5?.readonly"
|
|
32981
32924
|
[disabled]="control.disabled"
|
|
32982
32925
|
[attr.aria-required]="required"
|
|
32983
32926
|
[attr.aria-invalid]="!!error"
|
|
@@ -33007,7 +32950,7 @@ class TextFieldWidgetComponent {
|
|
|
33007
32950
|
(blur)="onBlur()"
|
|
33008
32951
|
(mouseenter)="onMouseEnter()"
|
|
33009
32952
|
(mouseleave)="onMouseLeave()"
|
|
33010
|
-
[readonly]="config.readonly"
|
|
32953
|
+
[readonly]="config.html5?.readonly"
|
|
33011
32954
|
[attr.aria-required]="required"
|
|
33012
32955
|
[attr.aria-invalid]="!!error"
|
|
33013
32956
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33065,7 +33008,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33065
33008
|
(blur)="onBlur()"
|
|
33066
33009
|
(mouseenter)="onMouseEnter()"
|
|
33067
33010
|
(mouseleave)="onMouseLeave()"
|
|
33068
|
-
[readonly]="config.readonly"
|
|
33011
|
+
[readonly]="config.html5?.readonly"
|
|
33069
33012
|
[attr.aria-required]="required"
|
|
33070
33013
|
[attr.aria-invalid]="!!error"
|
|
33071
33014
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33086,7 +33029,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33086
33029
|
(blur)="onBlur()"
|
|
33087
33030
|
(mouseenter)="onMouseEnter()"
|
|
33088
33031
|
(mouseleave)="onMouseLeave()"
|
|
33089
|
-
[readonly]="config.readonly"
|
|
33032
|
+
[readonly]="config.html5?.readonly"
|
|
33090
33033
|
[attr.aria-required]="required"
|
|
33091
33034
|
[attr.aria-invalid]="!!error"
|
|
33092
33035
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33098,7 +33041,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33098
33041
|
[cpAlphaChannel]="'disabled'"
|
|
33099
33042
|
[cpOutputFormat]="'hex'"
|
|
33100
33043
|
[cpFallbackColor]="'#000000'"
|
|
33101
|
-
[cpDisabled]="config.readonly || !enabled"
|
|
33044
|
+
[cpDisabled]="config.html5?.readonly || !enabled"
|
|
33102
33045
|
(colorPickerChange)="onColorPickerChange($event)">
|
|
33103
33046
|
} @else if (usesFormattedNumberInput()) {
|
|
33104
33047
|
@if (hasDisplayPrefix()) {
|
|
@@ -33120,7 +33063,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33120
33063
|
(blur)="onBlur()"
|
|
33121
33064
|
(mouseenter)="onMouseEnter()"
|
|
33122
33065
|
(mouseleave)="onMouseLeave()"
|
|
33123
|
-
[readonly]="config.readonly"
|
|
33066
|
+
[readonly]="config.html5?.readonly"
|
|
33124
33067
|
[disabled]="control.disabled"
|
|
33125
33068
|
[attr.aria-required]="required"
|
|
33126
33069
|
[attr.aria-invalid]="!!error"
|
|
@@ -33150,7 +33093,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
33150
33093
|
(blur)="onBlur()"
|
|
33151
33094
|
(mouseenter)="onMouseEnter()"
|
|
33152
33095
|
(mouseleave)="onMouseLeave()"
|
|
33153
|
-
[readonly]="config.readonly"
|
|
33096
|
+
[readonly]="config.html5?.readonly"
|
|
33154
33097
|
[attr.aria-required]="required"
|
|
33155
33098
|
[attr.aria-invalid]="!!error"
|
|
33156
33099
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -33263,12 +33206,12 @@ class FileUploadWidgetComponent {
|
|
|
33263
33206
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
33264
33207
|
}
|
|
33265
33208
|
get enabled() {
|
|
33266
|
-
if (this.config
|
|
33209
|
+
if (isFieldDisabled(this.config))
|
|
33267
33210
|
return false;
|
|
33268
33211
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
33269
33212
|
}
|
|
33270
33213
|
get isDisabled() {
|
|
33271
|
-
return !this.enabled ||
|
|
33214
|
+
return !this.enabled || isFieldReadonly(this.config);
|
|
33272
33215
|
}
|
|
33273
33216
|
get required() {
|
|
33274
33217
|
return this.engine ? this.engine.isFieldRequired(this.config.id) : !!this.config?.html5?.required;
|
|
@@ -33759,7 +33702,7 @@ class SelectWidgetComponent {
|
|
|
33759
33702
|
this.runtimeOptionsLoaded = false;
|
|
33760
33703
|
this.currentSearchTerm = '';
|
|
33761
33704
|
this.setOptionsFromRaw([]);
|
|
33762
|
-
void this.loadOptions(this.currentSearchTerm);
|
|
33705
|
+
void this.loadOptions(this.currentSearchTerm, false, true);
|
|
33763
33706
|
});
|
|
33764
33707
|
}
|
|
33765
33708
|
}
|
|
@@ -33902,7 +33845,7 @@ class SelectWidgetComponent {
|
|
|
33902
33845
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
33903
33846
|
}
|
|
33904
33847
|
get enabled() {
|
|
33905
|
-
if (this.config
|
|
33848
|
+
if (isFieldDisabled(this.config))
|
|
33906
33849
|
return false;
|
|
33907
33850
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
33908
33851
|
}
|
|
@@ -33959,7 +33902,7 @@ class SelectWidgetComponent {
|
|
|
33959
33902
|
event.preventDefault();
|
|
33960
33903
|
}
|
|
33961
33904
|
onPillClick() {
|
|
33962
|
-
if (this.config
|
|
33905
|
+
if (isFieldReadonly(this.config)) {
|
|
33963
33906
|
return;
|
|
33964
33907
|
}
|
|
33965
33908
|
this.onClick();
|
|
@@ -34026,7 +33969,7 @@ class SelectWidgetComponent {
|
|
|
34026
33969
|
assign('--fd-select-icon-color', controlStyles['iconColor'] ?? controlStyles['color']);
|
|
34027
33970
|
return vars;
|
|
34028
33971
|
}
|
|
34029
|
-
async loadOptions(term = '', isSearch = false) {
|
|
33972
|
+
async loadOptions(term = '', isSearch = false, clearStaleSelection = false) {
|
|
34030
33973
|
if (!this.config)
|
|
34031
33974
|
return;
|
|
34032
33975
|
const reqId = ++this.requestId;
|
|
@@ -34044,8 +33987,17 @@ class SelectWidgetComponent {
|
|
|
34044
33987
|
opts = await this.dataProvider.getOptions(this.config, this.engine);
|
|
34045
33988
|
}
|
|
34046
33989
|
if (this.requestId === reqId) {
|
|
34047
|
-
this.
|
|
34048
|
-
|
|
33990
|
+
const selectedValue = this.resolveSelectedValueForFallback();
|
|
33991
|
+
const shouldClearStaleSelection = clearStaleSelection
|
|
33992
|
+
&& this.hasMeaningfulValue(selectedValue)
|
|
33993
|
+
&& !this.hasOptionValue(opts, this.toComparableOptionValue(selectedValue));
|
|
33994
|
+
this.setOptionsFromRaw(shouldClearStaleSelection ? opts : this.withSelectedValueFallbackOptions(opts));
|
|
33995
|
+
if (shouldClearStaleSelection) {
|
|
33996
|
+
this.control.setValue(null);
|
|
33997
|
+
}
|
|
33998
|
+
else {
|
|
33999
|
+
this.syncStoredFieldLabel(this.control.value);
|
|
34000
|
+
}
|
|
34049
34001
|
this.loading = false;
|
|
34050
34002
|
this.loadError = null;
|
|
34051
34003
|
this.cdr.markForCheck();
|
|
@@ -34152,6 +34104,9 @@ class SelectWidgetComponent {
|
|
|
34152
34104
|
config.id,
|
|
34153
34105
|
config.name,
|
|
34154
34106
|
config.type,
|
|
34107
|
+
String(config.html5?.readonly ?? ''),
|
|
34108
|
+
String(config.html5?.disabled ?? ''),
|
|
34109
|
+
String(config.useThousandSeparator ?? ''),
|
|
34155
34110
|
'no-data-config',
|
|
34156
34111
|
fieldStaticOptions
|
|
34157
34112
|
].join('::');
|
|
@@ -34164,11 +34119,13 @@ class SelectWidgetComponent {
|
|
|
34164
34119
|
config.id,
|
|
34165
34120
|
config.name,
|
|
34166
34121
|
config.type,
|
|
34122
|
+
String(config.html5?.readonly ?? ''),
|
|
34123
|
+
String(config.html5?.disabled ?? ''),
|
|
34167
34124
|
dataConfig.type ?? '',
|
|
34168
34125
|
String(dataConfig.datasourceId ?? ''),
|
|
34169
34126
|
String(dataConfig.labelKey ?? ''),
|
|
34170
34127
|
String(dataConfig.valueKey ?? ''),
|
|
34171
|
-
String(
|
|
34128
|
+
String(config.useThousandSeparator ?? ''),
|
|
34172
34129
|
String(dataConfig.optionLabelPrefixFieldId ?? ''),
|
|
34173
34130
|
String(dataConfig.searchEnabled ?? ''),
|
|
34174
34131
|
String(dataConfig.optionsLimit ?? ''),
|
|
@@ -34221,15 +34178,18 @@ class SelectWidgetComponent {
|
|
|
34221
34178
|
applyDisplayFormatting() {
|
|
34222
34179
|
this.options = this.rawOptions.map(option => ({
|
|
34223
34180
|
...option,
|
|
34224
|
-
label: this.formatOptionLabel(option
|
|
34181
|
+
label: this.formatOptionLabel(option)
|
|
34225
34182
|
}));
|
|
34226
34183
|
}
|
|
34227
|
-
formatOptionLabel(
|
|
34228
|
-
const
|
|
34184
|
+
formatOptionLabel(option) {
|
|
34185
|
+
const label = option.label;
|
|
34186
|
+
const formattedLabel = usesFieldThousandSeparator(this.config)
|
|
34229
34187
|
? this.formatNumericLabel(label)
|
|
34230
34188
|
: label;
|
|
34231
|
-
const
|
|
34232
|
-
|
|
34189
|
+
const prefixParts = [option.displayPrefix, this.resolveOptionLabelPrefix()]
|
|
34190
|
+
.map(value => value?.trim())
|
|
34191
|
+
.filter((value) => !!value);
|
|
34192
|
+
return prefixParts.length > 0 ? `${prefixParts.join(' ')} ${formattedLabel}` : formattedLabel;
|
|
34233
34193
|
}
|
|
34234
34194
|
resolveOptionLabelPrefix() {
|
|
34235
34195
|
const prefixFieldId = this.config.dataConfig?.optionLabelPrefixFieldId;
|
|
@@ -34312,6 +34272,12 @@ class SelectWidgetComponent {
|
|
|
34312
34272
|
hasOptionValue(options, value) {
|
|
34313
34273
|
return options.some(option => Object.is(option.value, value) || String(option.value) === String(value));
|
|
34314
34274
|
}
|
|
34275
|
+
toComparableOptionValue(value) {
|
|
34276
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
34277
|
+
return value;
|
|
34278
|
+
}
|
|
34279
|
+
return String(value ?? '');
|
|
34280
|
+
}
|
|
34315
34281
|
resolveSelectedValueForFallback() {
|
|
34316
34282
|
const controlValue = this.control.value;
|
|
34317
34283
|
if (this.hasMeaningfulValue(controlValue)) {
|
|
@@ -34356,7 +34322,7 @@ class SelectWidgetComponent {
|
|
|
34356
34322
|
if (this.config.dataConfig?.optionLabelPrefixFieldId) {
|
|
34357
34323
|
return this.resolveOptionLabelPrefix().length === 0;
|
|
34358
34324
|
}
|
|
34359
|
-
return this.config
|
|
34325
|
+
return !usesFieldThousandSeparator(this.config);
|
|
34360
34326
|
}
|
|
34361
34327
|
setStoredFieldLabel(label) {
|
|
34362
34328
|
if (!this.engine || typeof this.engine.setFieldLabel !== 'function') {
|
|
@@ -34394,8 +34360,8 @@ class SelectWidgetComponent {
|
|
|
34394
34360
|
[loadingText]="'Loading options...'"
|
|
34395
34361
|
[notFoundText]="loadError || 'No options found'"
|
|
34396
34362
|
[searchable]="isSearchable()"
|
|
34397
|
-
[clearable]="!required && !config.readonly && !hasPillLabel()"
|
|
34398
|
-
[readonly]="config.readonly"
|
|
34363
|
+
[clearable]="!required && !config.html5?.readonly && !hasPillLabel()"
|
|
34364
|
+
[readonly]="config.html5?.readonly"
|
|
34399
34365
|
[labelForId]="fieldId"
|
|
34400
34366
|
[inputAttrs]="getInputAttributes()"
|
|
34401
34367
|
[typeahead]="searchTerms$"
|
|
@@ -34421,7 +34387,7 @@ class SelectWidgetComponent {
|
|
|
34421
34387
|
class="fd-select-pill"
|
|
34422
34388
|
[ngStyle]="getPillStyles()"
|
|
34423
34389
|
data-fd-select-pill
|
|
34424
|
-
[disabled]="config.readonly"
|
|
34390
|
+
[disabled]="config.html5?.readonly"
|
|
34425
34391
|
(mousedown)="onPillMouseDown($event)"
|
|
34426
34392
|
(click)="onPillClick()">
|
|
34427
34393
|
<span class="fd-select-pill__label">{{ pillLabel() }}</span>
|
|
@@ -34474,8 +34440,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
34474
34440
|
[loadingText]="'Loading options...'"
|
|
34475
34441
|
[notFoundText]="loadError || 'No options found'"
|
|
34476
34442
|
[searchable]="isSearchable()"
|
|
34477
|
-
[clearable]="!required && !config.readonly && !hasPillLabel()"
|
|
34478
|
-
[readonly]="config.readonly"
|
|
34443
|
+
[clearable]="!required && !config.html5?.readonly && !hasPillLabel()"
|
|
34444
|
+
[readonly]="config.html5?.readonly"
|
|
34479
34445
|
[labelForId]="fieldId"
|
|
34480
34446
|
[inputAttrs]="getInputAttributes()"
|
|
34481
34447
|
[typeahead]="searchTerms$"
|
|
@@ -34501,7 +34467,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
34501
34467
|
class="fd-select-pill"
|
|
34502
34468
|
[ngStyle]="getPillStyles()"
|
|
34503
34469
|
data-fd-select-pill
|
|
34504
|
-
[disabled]="config.readonly"
|
|
34470
|
+
[disabled]="config.html5?.readonly"
|
|
34505
34471
|
(mousedown)="onPillMouseDown($event)"
|
|
34506
34472
|
(click)="onPillClick()">
|
|
34507
34473
|
<span class="fd-select-pill__label">{{ pillLabel() }}</span>
|
|
@@ -34596,7 +34562,7 @@ class SearchWidgetComponent {
|
|
|
34596
34562
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
34597
34563
|
}
|
|
34598
34564
|
get enabled() {
|
|
34599
|
-
if (this.config
|
|
34565
|
+
if (isFieldDisabled(this.config))
|
|
34600
34566
|
return false;
|
|
34601
34567
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
34602
34568
|
}
|
|
@@ -34659,7 +34625,7 @@ class SearchWidgetComponent {
|
|
|
34659
34625
|
const datasourceId = this.config?.dataConfig?.datasourceId;
|
|
34660
34626
|
if (!datasourceId || update.datasourceId !== datasourceId)
|
|
34661
34627
|
return;
|
|
34662
|
-
void this.refreshForCurrentQuery();
|
|
34628
|
+
void this.refreshForCurrentQuery(true);
|
|
34663
34629
|
});
|
|
34664
34630
|
}
|
|
34665
34631
|
this.engine.valueChanges$
|
|
@@ -34803,7 +34769,7 @@ class SearchWidgetComponent {
|
|
|
34803
34769
|
this.queryControl.disable({ emitEvent: false });
|
|
34804
34770
|
}
|
|
34805
34771
|
}
|
|
34806
|
-
async refreshForCurrentQuery() {
|
|
34772
|
+
async refreshForCurrentQuery(clearStaleSelection = false) {
|
|
34807
34773
|
const query = this.queryControl.value ?? '';
|
|
34808
34774
|
if (!this.shouldQuery(query)) {
|
|
34809
34775
|
this.options = [];
|
|
@@ -34813,7 +34779,7 @@ class SearchWidgetComponent {
|
|
|
34813
34779
|
this.cdr.markForCheck();
|
|
34814
34780
|
return;
|
|
34815
34781
|
}
|
|
34816
|
-
await this.loadOptions(query);
|
|
34782
|
+
await this.loadOptions(query, clearStaleSelection);
|
|
34817
34783
|
}
|
|
34818
34784
|
async handleQueryChange(query) {
|
|
34819
34785
|
if (this.selectingOption) {
|
|
@@ -34833,7 +34799,7 @@ class SearchWidgetComponent {
|
|
|
34833
34799
|
}
|
|
34834
34800
|
await this.loadOptions(normalizedQuery);
|
|
34835
34801
|
}
|
|
34836
|
-
async loadOptions(term) {
|
|
34802
|
+
async loadOptions(term, clearStaleSelection = false) {
|
|
34837
34803
|
const requestId = ++this.requestId;
|
|
34838
34804
|
this.loading = true;
|
|
34839
34805
|
this.loadError = null;
|
|
@@ -34847,6 +34813,15 @@ class SearchWidgetComponent {
|
|
|
34847
34813
|
return;
|
|
34848
34814
|
}
|
|
34849
34815
|
this.options = this.normalizeOptions(options);
|
|
34816
|
+
if (clearStaleSelection && this.isSelectedOptionState() && !this.hasOptionValue(this.options, this.control.value)) {
|
|
34817
|
+
this.queryControl.setValue('', { emitEvent: false });
|
|
34818
|
+
this.control.setValue(null);
|
|
34819
|
+
this.loading = false;
|
|
34820
|
+
this.loadError = null;
|
|
34821
|
+
this.activeOptionIndex = -1;
|
|
34822
|
+
this.cdr.markForCheck();
|
|
34823
|
+
return;
|
|
34824
|
+
}
|
|
34850
34825
|
this.activeOptionIndex = this.options.length > 0 ? 0 : -1;
|
|
34851
34826
|
this.loading = false;
|
|
34852
34827
|
this.loadError = null;
|
|
@@ -34878,6 +34853,31 @@ class SearchWidgetComponent {
|
|
|
34878
34853
|
const minChars = this.getMinChars();
|
|
34879
34854
|
return (query ?? '').trim().length >= minChars;
|
|
34880
34855
|
}
|
|
34856
|
+
isSelectedOptionState() {
|
|
34857
|
+
if (!this.hasMeaningfulValue(this.control.value)) {
|
|
34858
|
+
return false;
|
|
34859
|
+
}
|
|
34860
|
+
const storedLabel = this.getStoredFieldLabel();
|
|
34861
|
+
if (typeof storedLabel === 'string' && storedLabel.length > 0) {
|
|
34862
|
+
return true;
|
|
34863
|
+
}
|
|
34864
|
+
return String(this.control.value ?? '') !== String(this.queryControl.value ?? '');
|
|
34865
|
+
}
|
|
34866
|
+
hasOptionValue(options, value) {
|
|
34867
|
+
if (!this.hasMeaningfulValue(value)) {
|
|
34868
|
+
return false;
|
|
34869
|
+
}
|
|
34870
|
+
return options.some(option => Object.is(option.value, value) || String(option.value) === String(value));
|
|
34871
|
+
}
|
|
34872
|
+
hasMeaningfulValue(value) {
|
|
34873
|
+
if (value === undefined || value === null)
|
|
34874
|
+
return false;
|
|
34875
|
+
if (typeof value === 'string')
|
|
34876
|
+
return value.length > 0;
|
|
34877
|
+
if (Array.isArray(value))
|
|
34878
|
+
return value.length > 0;
|
|
34879
|
+
return true;
|
|
34880
|
+
}
|
|
34881
34881
|
getMinChars() {
|
|
34882
34882
|
return this.toSafeNonNegativeInt(this.config?.['searchMinChars'], 1);
|
|
34883
34883
|
}
|
|
@@ -34945,7 +34945,7 @@ class SearchWidgetComponent {
|
|
|
34945
34945
|
type="search"
|
|
34946
34946
|
[placeholder]="config.placeholder || 'Search...'"
|
|
34947
34947
|
[formControl]="queryControl"
|
|
34948
|
-
[readonly]="config.readonly"
|
|
34948
|
+
[readonly]="config.html5?.readonly"
|
|
34949
34949
|
[attr.aria-required]="required"
|
|
34950
34950
|
[attr.aria-invalid]="!!error"
|
|
34951
34951
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -35024,7 +35024,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
35024
35024
|
type="search"
|
|
35025
35025
|
[placeholder]="config.placeholder || 'Search...'"
|
|
35026
35026
|
[formControl]="queryControl"
|
|
35027
|
-
[readonly]="config.readonly"
|
|
35027
|
+
[readonly]="config.html5?.readonly"
|
|
35028
35028
|
[attr.aria-required]="required"
|
|
35029
35029
|
[attr.aria-invalid]="!!error"
|
|
35030
35030
|
[attr.aria-describedby]="getAriaDescribedBy()"
|
|
@@ -35311,7 +35311,7 @@ class TreeSelectWidgetComponent {
|
|
|
35311
35311
|
expandRecursive(filtered);
|
|
35312
35312
|
}
|
|
35313
35313
|
toggleDropdown(e) {
|
|
35314
|
-
if (this.config
|
|
35314
|
+
if (isFieldDisabled(this.config) || isFieldReadonly(this.config))
|
|
35315
35315
|
return;
|
|
35316
35316
|
this.engine?.emitUiEvent({ fieldId: this.config.id, fieldName: this.config.name, type: 'click' });
|
|
35317
35317
|
if (this.isOpen) {
|
|
@@ -35423,8 +35423,8 @@ class TreeSelectWidgetComponent {
|
|
|
35423
35423
|
<!-- Dropdown Trigger -->
|
|
35424
35424
|
<div class="relative group" (click)="toggleDropdown($event)">
|
|
35425
35425
|
<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"
|
|
35426
|
+
[class.bg-gray-50]="config.html5?.disabled"
|
|
35427
|
+
[class.cursor-not-allowed]="config.html5?.disabled"
|
|
35428
35428
|
[class.border-gray-300]="!isInvalid && !isOpen"
|
|
35429
35429
|
[class.border-blue-500]="isOpen"
|
|
35430
35430
|
[class.ring-2]="isOpen"
|
|
@@ -35527,8 +35527,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
35527
35527
|
<!-- Dropdown Trigger -->
|
|
35528
35528
|
<div class="relative group" (click)="toggleDropdown($event)">
|
|
35529
35529
|
<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"
|
|
35530
|
+
[class.bg-gray-50]="config.html5?.disabled"
|
|
35531
|
+
[class.cursor-not-allowed]="config.html5?.disabled"
|
|
35532
35532
|
[class.border-gray-300]="!isInvalid && !isOpen"
|
|
35533
35533
|
[class.border-blue-500]="isOpen"
|
|
35534
35534
|
[class.ring-2]="isOpen"
|
|
@@ -35778,7 +35778,7 @@ class RadioWidgetComponent {
|
|
|
35778
35778
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
35779
35779
|
}
|
|
35780
35780
|
get enabled() {
|
|
35781
|
-
if (this.config
|
|
35781
|
+
if (isFieldDisabled(this.config))
|
|
35782
35782
|
return false;
|
|
35783
35783
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
35784
35784
|
}
|
|
@@ -36094,7 +36094,7 @@ class CheckboxGroupWidgetComponent {
|
|
|
36094
36094
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36095
36095
|
}
|
|
36096
36096
|
get enabled() {
|
|
36097
|
-
if (this.config
|
|
36097
|
+
if (isFieldDisabled(this.config))
|
|
36098
36098
|
return false;
|
|
36099
36099
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36100
36100
|
}
|
|
@@ -36330,7 +36330,7 @@ class CheckboxWidgetComponent {
|
|
|
36330
36330
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36331
36331
|
}
|
|
36332
36332
|
get enabled() {
|
|
36333
|
-
if (this.config
|
|
36333
|
+
if (isFieldDisabled(this.config))
|
|
36334
36334
|
return false;
|
|
36335
36335
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36336
36336
|
}
|
|
@@ -36564,7 +36564,7 @@ class RepeatableGroupWidgetComponent {
|
|
|
36564
36564
|
return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
|
|
36565
36565
|
}
|
|
36566
36566
|
get enabled() {
|
|
36567
|
-
if (this.config
|
|
36567
|
+
if (isFieldDisabled(this.config))
|
|
36568
36568
|
return false;
|
|
36569
36569
|
return this.engine ? this.engine.isFieldEnabled(this.config.id) : true;
|
|
36570
36570
|
}
|
|
@@ -37023,7 +37023,7 @@ class InlineQuillEditorComponent {
|
|
|
37023
37023
|
setHtml(nextHtml) {
|
|
37024
37024
|
if (!this.quill)
|
|
37025
37025
|
return;
|
|
37026
|
-
if (this.quill.hasFocus())
|
|
37026
|
+
if (this.hasFocus || this.quill.hasFocus())
|
|
37027
37027
|
return;
|
|
37028
37028
|
const normalized = nextHtml ?? '';
|
|
37029
37029
|
if (normalized === this.lastHtml)
|
|
@@ -37899,8 +37899,8 @@ const COMMON_GROUP_FIELDS = [
|
|
|
37899
37899
|
{ 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
37900
|
];
|
|
37901
37901
|
const COMMON_INTERACTIVITY_FIELDS = [
|
|
37902
|
-
{ key: 'readonly', type: 'checkbox', label: 'Read Only' },
|
|
37903
|
-
{ key: 'disabled', type: 'checkbox', label: 'Disabled' }
|
|
37902
|
+
{ key: 'html5.readonly', type: 'checkbox', label: 'Read Only' },
|
|
37903
|
+
{ key: 'html5.disabled', type: 'checkbox', label: 'Disabled' }
|
|
37904
37904
|
];
|
|
37905
37905
|
const COMMON_BASIC_FIELDS = [
|
|
37906
37906
|
{ key: 'name', type: 'text', label: 'Field Key (Name)' },
|
|
@@ -37960,16 +37960,10 @@ const BASE_REQUIRED_FIELD = {
|
|
|
37960
37960
|
label: 'Required',
|
|
37961
37961
|
helpText: 'Base required state; Rules can override this dynamically.'
|
|
37962
37962
|
};
|
|
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
37963
|
function createValidationSection(...fields) {
|
|
37970
37964
|
return {
|
|
37971
37965
|
label: 'Validation',
|
|
37972
|
-
fields
|
|
37966
|
+
fields
|
|
37973
37967
|
};
|
|
37974
37968
|
}
|
|
37975
37969
|
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 +37973,28 @@ const TIME_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD, { k
|
|
|
37979
37973
|
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
37974
|
const SELECT_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD);
|
|
37981
37975
|
const FILE_VALIDATION_SECTION = createValidationSection(BASE_REQUIRED_FIELD);
|
|
37976
|
+
const NUMBER_DISPLAY_SECTION = {
|
|
37977
|
+
label: 'Display',
|
|
37978
|
+
fields: [
|
|
37979
|
+
{
|
|
37980
|
+
key: 'useThousandSeparator',
|
|
37981
|
+
type: 'checkbox',
|
|
37982
|
+
label: 'Show thousand separators',
|
|
37983
|
+
helpText: 'Formats grouped digits in the visible field value without changing the stored number.'
|
|
37984
|
+
}
|
|
37985
|
+
]
|
|
37986
|
+
};
|
|
37987
|
+
const SELECT_DISPLAY_SECTION = {
|
|
37988
|
+
label: 'Display',
|
|
37989
|
+
fields: [
|
|
37990
|
+
{
|
|
37991
|
+
key: 'useThousandSeparator',
|
|
37992
|
+
type: 'checkbox',
|
|
37993
|
+
label: 'Show thousand separators for numeric labels',
|
|
37994
|
+
helpText: 'Formats numeric option labels without changing the stored option value.'
|
|
37995
|
+
}
|
|
37996
|
+
]
|
|
37997
|
+
};
|
|
37982
37998
|
const BUTTON_VARIANT_OPTIONS = [
|
|
37983
37999
|
{ label: 'Primary (Blue)', value: 'primary' },
|
|
37984
38000
|
{ label: 'Secondary (Outline)', value: 'secondary' }
|
|
@@ -38187,6 +38203,7 @@ const FIELD_WIDGETS = [
|
|
|
38187
38203
|
]
|
|
38188
38204
|
},
|
|
38189
38205
|
NUMBER_VALIDATION_SECTION,
|
|
38206
|
+
NUMBER_DISPLAY_SECTION,
|
|
38190
38207
|
{ label: 'Appearance', fields: COMMON_APPEARANCE_FIELDS },
|
|
38191
38208
|
...COMMON_STYLE_SECTIONS
|
|
38192
38209
|
]
|
|
@@ -38648,6 +38665,7 @@ const FIELD_WIDGETS = [
|
|
|
38648
38665
|
},
|
|
38649
38666
|
// Options are now handled in Data Tab
|
|
38650
38667
|
SELECT_VALIDATION_SECTION,
|
|
38668
|
+
SELECT_DISPLAY_SECTION,
|
|
38651
38669
|
{ label: 'Appearance', fields: COMMON_APPEARANCE_FIELDS },
|
|
38652
38670
|
...COMMON_STYLE_SECTIONS
|
|
38653
38671
|
]
|
|
@@ -41463,5 +41481,5 @@ function provideHttpDataSourceClient(config) {
|
|
|
41463
41481
|
* Generated bundle index. Do not edit.
|
|
41464
41482
|
*/
|
|
41465
41483
|
|
|
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 };
|
|
41484
|
+
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
41485
|
//# sourceMappingURL=uch-web-ngx-form-designer.mjs.map
|