@yourself.create/ngx-form-designer 0.0.11 → 0.0.13

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.
@@ -329,6 +329,8 @@ class RuleEvaluationService {
329
329
  return value !== null && value !== undefined && value !== '';
330
330
  case 'truthy':
331
331
  return !!value;
332
+ case 'notTruthy':
333
+ return !value;
332
334
  default: return false;
333
335
  }
334
336
  }
@@ -433,6 +435,7 @@ class FormEngine {
433
435
  }
434
436
  updateSchema(schema) {
435
437
  this.schema = schema;
438
+ let valuesChanged = false;
436
439
  // Re-initialize any new fields
437
440
  this.schema.fields.forEach(field => {
438
441
  if (this.values[field.name] === undefined) {
@@ -442,10 +445,13 @@ class FormEngine {
442
445
  else {
443
446
  this.values[field.name] = null;
444
447
  }
448
+ valuesChanged = true;
445
449
  }
446
450
  });
447
- // Emit new state to ensure UI syncs if defaults added
448
- this.valueSubject.next({ ...this.values });
451
+ // Emit only when schema updates also change the value map.
452
+ if (valuesChanged) {
453
+ this.valueSubject.next({ ...this.values });
454
+ }
449
455
  // Re-validate all
450
456
  this.validate();
451
457
  }
@@ -1375,11 +1381,10 @@ class DesignerStateService {
1375
1381
  const originalField = clipboardFields.get(oldRefId);
1376
1382
  if (originalField) {
1377
1383
  const newFieldId = v4();
1378
- const newField = {
1379
- ...originalField,
1384
+ const newField = this.cloneFieldForDuplication(originalField, {
1380
1385
  id: newFieldId,
1381
1386
  name: `${originalField.name}_${Date.now()}_${Math.floor(Math.random() * 1000)}`
1382
- };
1387
+ });
1383
1388
  targetSchema.fields.push(newField);
1384
1389
  newNode.refId = newFieldId;
1385
1390
  }
@@ -2304,12 +2309,11 @@ class DesignerStateService {
2304
2309
  const originalField = scopeFields.find(f => f.id === cloned.refId);
2305
2310
  if (originalField) {
2306
2311
  const newFieldId = v4();
2307
- const newField = {
2308
- ...this.cloneValue(originalField),
2312
+ const newField = this.cloneFieldForDuplication(originalField, {
2309
2313
  id: newFieldId,
2310
2314
  name: `${originalField.name}_copy_${Date.now()}`,
2311
2315
  label: `${originalField.label || 'Field'} (Copy)`
2312
- };
2316
+ });
2313
2317
  scopeFields.push(newField);
2314
2318
  cloned.refId = newFieldId;
2315
2319
  }
@@ -2379,11 +2383,10 @@ class DesignerStateService {
2379
2383
  if (!location)
2380
2384
  return;
2381
2385
  const newFieldId = v4();
2382
- const newField = {
2383
- ...this.cloneValue(location.field),
2386
+ const newField = this.cloneFieldForDuplication(location.field, {
2384
2387
  id: newFieldId,
2385
2388
  name: `${location.field.name}_copy_${Date.now()}`
2386
- };
2389
+ });
2387
2390
  location.schema.fields.push(newField);
2388
2391
  const widgetNode = this.findWidgetByRefId(location.schema.layout, fieldId);
2389
2392
  if (!widgetNode) {
@@ -2910,6 +2913,42 @@ class DesignerStateService {
2910
2913
  cloneValue(value) {
2911
2914
  return structuredClone(value);
2912
2915
  }
2916
+ cloneFieldForDuplication(field, overrides) {
2917
+ const clonedField = this.cloneValue(field);
2918
+ const bindingIdMap = new Map();
2919
+ const events = clonedField.events?.map(binding => {
2920
+ const nextBindingId = v4();
2921
+ bindingIdMap.set(binding.id, nextBindingId);
2922
+ return {
2923
+ ...binding,
2924
+ id: nextBindingId,
2925
+ actions: binding.actions.map(action => {
2926
+ if (action.type !== 'api') {
2927
+ return action;
2928
+ }
2929
+ return {
2930
+ ...action,
2931
+ datasourceId: action.datasourceId ? this.createEventDatasourceId() : action.datasourceId
2932
+ };
2933
+ })
2934
+ };
2935
+ });
2936
+ const dataConfig = clonedField.dataConfig?.eventId && bindingIdMap.has(clonedField.dataConfig.eventId)
2937
+ ? {
2938
+ ...clonedField.dataConfig,
2939
+ eventId: bindingIdMap.get(clonedField.dataConfig.eventId)
2940
+ }
2941
+ : clonedField.dataConfig;
2942
+ return {
2943
+ ...clonedField,
2944
+ ...overrides,
2945
+ events,
2946
+ dataConfig
2947
+ };
2948
+ }
2949
+ createEventDatasourceId() {
2950
+ return `evt_ds_${v4().replace(/-/g, '')}`;
2951
+ }
2913
2952
  clampIndex(index, length) {
2914
2953
  if (index < 0)
2915
2954
  return 0;
@@ -4467,6 +4506,9 @@ class FormEventRunner {
4467
4506
  if (!field || !field.events)
4468
4507
  return;
4469
4508
  const bindings = field.events.filter(b => b.on === evt.type && b.enabled !== false);
4509
+ if (evt.type === 'change' && this.isEmptyEventValue(evt.value)) {
4510
+ await this.clearInactiveApiBindingDatasources(field, bindings, evt);
4511
+ }
4470
4512
  for (const binding of bindings) {
4471
4513
  for (const action of binding.actions) {
4472
4514
  const stop = await this.executeAction(action, binding.id, evt, schema.fields);
@@ -4480,6 +4522,46 @@ class FormEventRunner {
4480
4522
  this.processingDepth--;
4481
4523
  }
4482
4524
  }
4525
+ async clearInactiveApiBindingDatasources(field, activeBindings, evt) {
4526
+ if (!this.dataSourceWriter || !field.events?.length) {
4527
+ return;
4528
+ }
4529
+ const activeBindingIds = new Set(activeBindings.map(binding => binding.id));
4530
+ const clearedDatasourceIds = new Set();
4531
+ for (const binding of field.events) {
4532
+ if (binding.enabled === false || activeBindingIds.has(binding.id)) {
4533
+ continue;
4534
+ }
4535
+ for (const action of binding.actions) {
4536
+ if (action.type !== 'api') {
4537
+ continue;
4538
+ }
4539
+ const datasourceId = this.resolveDatasourceId(action, evt);
4540
+ if (!datasourceId || clearedDatasourceIds.has(datasourceId)) {
4541
+ continue;
4542
+ }
4543
+ clearedDatasourceIds.add(datasourceId);
4544
+ try {
4545
+ await this.dataSourceWriter({
4546
+ datasourceId,
4547
+ rows: [],
4548
+ action,
4549
+ event: evt,
4550
+ response: []
4551
+ });
4552
+ this.engine.emitDataSourceUpdate(datasourceId);
4553
+ }
4554
+ catch (error) {
4555
+ this.logger.warn('Failed to clear API action datasource after the source field was emptied.', {
4556
+ event: evt,
4557
+ action,
4558
+ datasourceId,
4559
+ error
4560
+ });
4561
+ }
4562
+ }
4563
+ }
4564
+ }
4483
4565
  async executeAction(action, eventId, evt, fields) {
4484
4566
  if (action.type === 'log') {
4485
4567
  this.logger.log(action.message || 'Event fired', { event: evt });
@@ -4651,6 +4733,8 @@ class FormEventRunner {
4651
4733
  return !this.isEmptyValue(left);
4652
4734
  case 'truthy':
4653
4735
  return !!left;
4736
+ case 'notTruthy':
4737
+ return !left;
4654
4738
  default:
4655
4739
  return false;
4656
4740
  }
@@ -4733,6 +4817,18 @@ class FormEventRunner {
4733
4817
  }
4734
4818
  return [{ value }];
4735
4819
  }
4820
+ isEmptyEventValue(value) {
4821
+ if (value === undefined || value === null) {
4822
+ return true;
4823
+ }
4824
+ if (typeof value === 'string') {
4825
+ return value.trim().length === 0;
4826
+ }
4827
+ if (Array.isArray(value)) {
4828
+ return value.length === 0;
4829
+ }
4830
+ return false;
4831
+ }
4736
4832
  }
4737
4833
 
4738
4834
  const FILE_UPLOAD_CLIENT = new InjectionToken('FILE_UPLOAD_CLIENT');
@@ -5178,10 +5274,12 @@ class JsonFormRendererComponent {
5178
5274
  eventApiExecutor;
5179
5275
  navigateToPage;
5180
5276
  uploadOnSubmit = true;
5277
+ severityEvaluationMode = 'rule-failed';
5181
5278
  fieldDataAccessMap;
5182
5279
  fieldDataAccessApi;
5183
5280
  formContentId;
5184
5281
  formContentVersion;
5282
+ refreshKey;
5185
5283
  valueChange = new EventEmitter();
5186
5284
  groupedValueChange = new EventEmitter();
5187
5285
  combinedValueChange = new EventEmitter();
@@ -5214,6 +5312,10 @@ class JsonFormRendererComponent {
5214
5312
  if (changes['mode'] && !changes['mode'].firstChange) {
5215
5313
  this.configureRunner();
5216
5314
  }
5315
+ if (changes['refreshKey'] && !changes['refreshKey'].firstChange) {
5316
+ this.createEngine();
5317
+ return;
5318
+ }
5217
5319
  if (changes['fieldDataAccessMap']
5218
5320
  || changes['fieldDataAccessApi']
5219
5321
  || changes['formContentId']
@@ -5478,7 +5580,7 @@ class JsonFormRendererComponent {
5478
5580
  errors: fieldErrors,
5479
5581
  validators: this.describeFieldValidators(field, visible, required, fieldErrors)
5480
5582
  };
5481
- states[field.name].isSeverityError = states[field.name].validators.some(validator => validator.severity === 'error' && validator.valid === false);
5583
+ states[field.name].isSeverityError = states[field.name].validators.some(validator => validator.severity === 'error' && validator.isSeverityTriggered === true);
5482
5584
  }
5483
5585
  return states;
5484
5586
  }
@@ -5556,11 +5658,13 @@ class JsonFormRendererComponent {
5556
5658
  }
5557
5659
  for (const outcome of ruleOutcomes) {
5558
5660
  const message = this.getRuleValidationMessage(outcome.rule);
5661
+ const isSeverityTriggered = this.isRuleSeverityTriggered(outcome);
5559
5662
  validators.push({
5560
5663
  name: outcome.rule.name?.trim() || this.describeRuleName(outcome.rule),
5561
5664
  source: 'rule',
5562
5665
  active: true,
5563
5666
  valid: outcome.conditionMet || outcome.nextAction !== undefined,
5667
+ ...(isSeverityTriggered ? { isSeverityTriggered: true } : {}),
5564
5668
  value: {
5565
5669
  action: outcome.rule.action,
5566
5670
  elseAction: outcome.rule.elseAction
@@ -5585,6 +5689,15 @@ class JsonFormRendererComponent {
5585
5689
  }
5586
5690
  return false;
5587
5691
  }
5692
+ isRuleSeverityTriggered(outcome) {
5693
+ if (outcome.rule.severity !== 'error') {
5694
+ return false;
5695
+ }
5696
+ if (this.severityEvaluationMode === 'rule-matched') {
5697
+ return outcome.conditionMet && outcome.rule.elseAction === undefined;
5698
+ }
5699
+ return !outcome.conditionMet && outcome.nextAction === undefined;
5700
+ }
5588
5701
  getRuleOutcomes(field) {
5589
5702
  if (!field.rules?.length) {
5590
5703
  return [];
@@ -5944,7 +6057,7 @@ class JsonFormRendererComponent {
5944
6057
  || typeof record['type'] === 'string';
5945
6058
  }
5946
6059
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: JsonFormRendererComponent, deps: [{ token: DesignerStateService }], target: i0.ɵɵFactoryTarget.Component });
5947
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: JsonFormRendererComponent, isStandalone: true, selector: "app-json-form-renderer", inputs: { schema: "schema", initialValues: "initialValues", initialFieldLabels: "initialFieldLabels", mode: "mode", device: "device", showLayoutGuides: "showLayoutGuides", breakpoint: "breakpoint", eventLogger: "eventLogger", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", navigateToPage: "navigateToPage", uploadOnSubmit: "uploadOnSubmit", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion" }, outputs: { valueChange: "valueChange", groupedValueChange: "groupedValueChange", combinedValueChange: "combinedValueChange", validationChange: "validationChange", uploadedFilesChange: "uploadedFilesChange", formSubmit: "formSubmit" }, usesOnChanges: true, ngImport: i0, template: `
6060
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: JsonFormRendererComponent, isStandalone: true, selector: "app-json-form-renderer", inputs: { schema: "schema", initialValues: "initialValues", initialFieldLabels: "initialFieldLabels", mode: "mode", device: "device", showLayoutGuides: "showLayoutGuides", breakpoint: "breakpoint", eventLogger: "eventLogger", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", navigateToPage: "navigateToPage", uploadOnSubmit: "uploadOnSubmit", severityEvaluationMode: "severityEvaluationMode", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion", refreshKey: "refreshKey" }, outputs: { valueChange: "valueChange", groupedValueChange: "groupedValueChange", combinedValueChange: "combinedValueChange", validationChange: "validationChange", uploadedFilesChange: "uploadedFilesChange", formSubmit: "formSubmit" }, usesOnChanges: true, ngImport: i0, template: `
5948
6061
  <div class="form-renderer-container"
5949
6062
  data-fd="renderer"
5950
6063
  [class.is-mobile]="device === 'mobile'"
@@ -6017,6 +6130,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6017
6130
  type: Input
6018
6131
  }], uploadOnSubmit: [{
6019
6132
  type: Input
6133
+ }], severityEvaluationMode: [{
6134
+ type: Input
6020
6135
  }], fieldDataAccessMap: [{
6021
6136
  type: Input
6022
6137
  }], fieldDataAccessApi: [{
@@ -6025,6 +6140,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6025
6140
  type: Input
6026
6141
  }], formContentVersion: [{
6027
6142
  type: Input
6143
+ }], refreshKey: [{
6144
+ type: Input
6028
6145
  }], valueChange: [{
6029
6146
  type: Output
6030
6147
  }], groupedValueChange: [{
@@ -6217,6 +6334,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6217
6334
  class FormJourneyViewerComponent {
6218
6335
  journey;
6219
6336
  viewOnly = false;
6337
+ severityEvaluationMode = 'rule-failed';
6220
6338
  eventApis = [];
6221
6339
  eventApiExecutor;
6222
6340
  initialValues;
@@ -6225,6 +6343,7 @@ class FormJourneyViewerComponent {
6225
6343
  fieldDataAccessApi;
6226
6344
  formContentId;
6227
6345
  formContentVersion;
6346
+ refreshKey;
6228
6347
  formDataChange = new EventEmitter();
6229
6348
  formDataByPageChange = new EventEmitter();
6230
6349
  formValidationChange = new EventEmitter();
@@ -6242,9 +6361,7 @@ class FormJourneyViewerComponent {
6242
6361
  return index >= 0 ? index : 0;
6243
6362
  });
6244
6363
  ngOnInit() {
6245
- this.activePageId.set(this.journey.startPageId || this.journey.pages[0]?.id || '');
6246
- this.values.set(this.normalizeInitialValues(this.initialValues));
6247
- this.fieldLabels.set(this.normalizeInitialFieldLabels(this.initialFieldLabels));
6364
+ this.resetViewerState();
6248
6365
  }
6249
6366
  ngOnChanges(changes) {
6250
6367
  if (changes['initialValues']) {
@@ -6253,6 +6370,10 @@ class FormJourneyViewerComponent {
6253
6370
  if (changes['initialFieldLabels']) {
6254
6371
  this.fieldLabels.set(this.normalizeInitialFieldLabels(this.initialFieldLabels));
6255
6372
  }
6373
+ if (changes['refreshKey'] && !changes['refreshKey'].firstChange) {
6374
+ this.resetViewerState();
6375
+ return;
6376
+ }
6256
6377
  const current = this.activePageId();
6257
6378
  if (current && this.journey.pages.some(page => page.id === current))
6258
6379
  return;
@@ -6301,6 +6422,11 @@ class FormJourneyViewerComponent {
6301
6422
  return {};
6302
6423
  return structuredClone(value);
6303
6424
  }
6425
+ resetViewerState() {
6426
+ this.activePageId.set(this.journey.startPageId || this.journey.pages[0]?.id || '');
6427
+ this.values.set(this.normalizeInitialValues(this.initialValues));
6428
+ this.fieldLabels.set(this.normalizeInitialFieldLabels(this.initialFieldLabels));
6429
+ }
6304
6430
  toValueScope(values) {
6305
6431
  const scope = {};
6306
6432
  for (const fieldValue of Object.values(values)) {
@@ -6359,7 +6485,7 @@ class FormJourneyViewerComponent {
6359
6485
  return flattened;
6360
6486
  }
6361
6487
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormJourneyViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6362
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormJourneyViewerComponent, isStandalone: true, selector: "app-form-journey-viewer", inputs: { journey: "journey", viewOnly: "viewOnly", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", initialValues: "initialValues", initialFieldLabels: "initialFieldLabels", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion" }, outputs: { formDataChange: "formDataChange", formDataByPageChange: "formDataByPageChange", formValidationChange: "formValidationChange", uploadedFilesChange: "uploadedFilesChange", submit: "submit", activePageIdChange: "activePageIdChange" }, viewQueries: [{ propertyName: "renderer", first: true, predicate: JsonFormRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
6488
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormJourneyViewerComponent, isStandalone: true, selector: "app-form-journey-viewer", inputs: { journey: "journey", viewOnly: "viewOnly", severityEvaluationMode: "severityEvaluationMode", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", initialValues: "initialValues", initialFieldLabels: "initialFieldLabels", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion", refreshKey: "refreshKey" }, outputs: { formDataChange: "formDataChange", formDataByPageChange: "formDataByPageChange", formValidationChange: "formValidationChange", uploadedFilesChange: "uploadedFilesChange", submit: "submit", activePageIdChange: "activePageIdChange" }, viewQueries: [{ propertyName: "renderer", first: true, predicate: JsonFormRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
6363
6489
  <div class="form-journey-viewer flex h-full w-full flex-col" data-fd="form-journey-viewer">
6364
6490
  <div class="border-b border-gray-200 bg-white px-4 py-2 text-xs text-gray-600" data-fd="journey-progress">
6365
6491
  {{ activePageIndex() + 1 }} / {{ journey.pages.length }}
@@ -6373,12 +6499,14 @@ class FormJourneyViewerComponent {
6373
6499
  [initialValues]="values()"
6374
6500
  [initialFieldLabels]="fieldLabels()"
6375
6501
  [mode]="viewOnly ? 'preview' : 'live'"
6502
+ [severityEvaluationMode]="severityEvaluationMode"
6376
6503
  [eventApis]="eventApis"
6377
6504
  [eventApiExecutor]="eventApiExecutor"
6378
6505
  [fieldDataAccessMap]="fieldDataAccessMap"
6379
6506
  [fieldDataAccessApi]="fieldDataAccessApi"
6380
6507
  [formContentId]="formContentId"
6381
6508
  [formContentVersion]="formContentVersion"
6509
+ [refreshKey]="refreshKey"
6382
6510
  [navigateToPage]="navigateToPage"
6383
6511
  (valueChange)="onValueChange($event)"
6384
6512
  (validationChange)="onValidationChange($event)"
@@ -6387,7 +6515,7 @@ class FormJourneyViewerComponent {
6387
6515
  </app-json-form-renderer>
6388
6516
  </div>
6389
6517
  </div>
6390
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
6518
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
6391
6519
  }
6392
6520
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormJourneyViewerComponent, decorators: [{
6393
6521
  type: Component,
@@ -6409,12 +6537,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6409
6537
  [initialValues]="values()"
6410
6538
  [initialFieldLabels]="fieldLabels()"
6411
6539
  [mode]="viewOnly ? 'preview' : 'live'"
6540
+ [severityEvaluationMode]="severityEvaluationMode"
6412
6541
  [eventApis]="eventApis"
6413
6542
  [eventApiExecutor]="eventApiExecutor"
6414
6543
  [fieldDataAccessMap]="fieldDataAccessMap"
6415
6544
  [fieldDataAccessApi]="fieldDataAccessApi"
6416
6545
  [formContentId]="formContentId"
6417
6546
  [formContentVersion]="formContentVersion"
6547
+ [refreshKey]="refreshKey"
6418
6548
  [navigateToPage]="navigateToPage"
6419
6549
  (valueChange)="onValueChange($event)"
6420
6550
  (validationChange)="onValidationChange($event)"
@@ -6430,6 +6560,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6430
6560
  args: [{ required: true }]
6431
6561
  }], viewOnly: [{
6432
6562
  type: Input
6563
+ }], severityEvaluationMode: [{
6564
+ type: Input
6433
6565
  }], eventApis: [{
6434
6566
  type: Input
6435
6567
  }], eventApiExecutor: [{
@@ -6446,6 +6578,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6446
6578
  type: Input
6447
6579
  }], formContentVersion: [{
6448
6580
  type: Input
6581
+ }], refreshKey: [{
6582
+ type: Input
6449
6583
  }], formDataChange: [{
6450
6584
  type: Output
6451
6585
  }], formDataByPageChange: [{
@@ -6486,12 +6620,14 @@ class FormViewerComponent {
6486
6620
  emitOnChange: true
6487
6621
  };
6488
6622
  viewOnly = false;
6623
+ severityEvaluationMode = 'rule-failed';
6489
6624
  eventApis = [];
6490
6625
  eventApiExecutor;
6491
6626
  fieldDataAccessMap;
6492
6627
  fieldDataAccessApi;
6493
6628
  formContentId;
6494
6629
  formContentVersion;
6630
+ refreshKey;
6495
6631
  formDataChange = new EventEmitter();
6496
6632
  formDataByPageChange = new EventEmitter();
6497
6633
  formValidationChange = new EventEmitter();
@@ -6767,7 +6903,7 @@ class FormViewerComponent {
6767
6903
  return !!value && typeof value === 'object';
6768
6904
  }
6769
6905
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormViewerComponent, isStandalone: true, selector: "app-form-viewer", inputs: { schema: "schema", journey: "journey", data: "data", dataUsesFieldNameKeys: "dataUsesFieldNameKeys", options: "options", viewOnly: "viewOnly", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion" }, outputs: { formDataChange: "formDataChange", formDataByPageChange: "formDataByPageChange", formValidationChange: "formValidationChange", uploadedFilesChange: "uploadedFilesChange", submit: "submit", activePageIdChange: "activePageIdChange" }, viewQueries: [{ propertyName: "renderer", first: true, predicate: JsonFormRendererComponent, descendants: true }, { propertyName: "journeyViewer", first: true, predicate: FormJourneyViewerComponent, descendants: true }], ngImport: i0, template: `
6906
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: FormViewerComponent, isStandalone: true, selector: "app-form-viewer", inputs: { schema: "schema", journey: "journey", data: "data", dataUsesFieldNameKeys: "dataUsesFieldNameKeys", options: "options", viewOnly: "viewOnly", severityEvaluationMode: "severityEvaluationMode", eventApis: "eventApis", eventApiExecutor: "eventApiExecutor", fieldDataAccessMap: "fieldDataAccessMap", fieldDataAccessApi: "fieldDataAccessApi", formContentId: "formContentId", formContentVersion: "formContentVersion", refreshKey: "refreshKey" }, outputs: { formDataChange: "formDataChange", formDataByPageChange: "formDataByPageChange", formValidationChange: "formValidationChange", uploadedFilesChange: "uploadedFilesChange", submit: "submit", activePageIdChange: "activePageIdChange" }, viewQueries: [{ propertyName: "renderer", first: true, predicate: JsonFormRendererComponent, descendants: true }, { propertyName: "journeyViewer", first: true, predicate: FormJourneyViewerComponent, descendants: true }], ngImport: i0, template: `
6771
6907
  <div class="form-viewer-container flex flex-col h-full"
6772
6908
  data-fd="form-viewer"
6773
6909
  [attr.data-fd-mode]="viewOnly ? 'preview' : 'live'">
@@ -6777,6 +6913,7 @@ class FormViewerComponent {
6777
6913
  data-fd="form-viewer-journey"
6778
6914
  [journey]="journey!"
6779
6915
  [viewOnly]="viewOnly"
6916
+ [severityEvaluationMode]="severityEvaluationMode"
6780
6917
  [eventApis]="eventApis"
6781
6918
  [eventApiExecutor]="eventApiExecutor"
6782
6919
  [initialValues]="normalizedInitialValues"
@@ -6785,6 +6922,7 @@ class FormViewerComponent {
6785
6922
  [fieldDataAccessApi]="fieldDataAccessApi"
6786
6923
  [formContentId]="formContentId"
6787
6924
  [formContentVersion]="formContentVersion"
6925
+ [refreshKey]="refreshKey"
6788
6926
  (formDataChange)="onValueChange($event)"
6789
6927
  (formDataByPageChange)="onJourneyValueByPageChange($event)"
6790
6928
  (formValidationChange)="onValidationChange($event)"
@@ -6800,6 +6938,7 @@ class FormViewerComponent {
6800
6938
  [initialValues]="normalizedInitialValues"
6801
6939
  [initialFieldLabels]="normalizedInitialFieldLabels"
6802
6940
  [mode]="viewOnly ? 'preview' : 'live'"
6941
+ [severityEvaluationMode]="severityEvaluationMode"
6803
6942
  [breakpoint]="breakpoint()"
6804
6943
  [uploadOnSubmit]="true"
6805
6944
  [eventApis]="eventApis"
@@ -6808,6 +6947,7 @@ class FormViewerComponent {
6808
6947
  [fieldDataAccessApi]="fieldDataAccessApi"
6809
6948
  [formContentId]="formContentId"
6810
6949
  [formContentVersion]="formContentVersion"
6950
+ [refreshKey]="refreshKey"
6811
6951
  (valueChange)="onValueChange($event)"
6812
6952
  (validationChange)="onValidationChange($event)"
6813
6953
  (uploadedFilesChange)="onUploadedFilesChange($event)"
@@ -6828,7 +6968,7 @@ class FormViewerComponent {
6828
6968
  </button>
6829
6969
  </div>
6830
6970
  </div>
6831
- `, isInline: true, styles: [":host{display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "component", type: FormJourneyViewerComponent, selector: "app-form-journey-viewer", inputs: ["journey", "viewOnly", "eventApis", "eventApiExecutor", "initialValues", "initialFieldLabels", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["formDataChange", "formDataByPageChange", "formValidationChange", "uploadedFilesChange", "submit", "activePageIdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6971
+ `, isInline: true, styles: [":host{display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "component", type: FormJourneyViewerComponent, selector: "app-form-journey-viewer", inputs: ["journey", "viewOnly", "severityEvaluationMode", "eventApis", "eventApiExecutor", "initialValues", "initialFieldLabels", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["formDataChange", "formDataByPageChange", "formValidationChange", "uploadedFilesChange", "submit", "activePageIdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6832
6972
  }
6833
6973
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormViewerComponent, decorators: [{
6834
6974
  type: Component,
@@ -6842,6 +6982,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6842
6982
  data-fd="form-viewer-journey"
6843
6983
  [journey]="journey!"
6844
6984
  [viewOnly]="viewOnly"
6985
+ [severityEvaluationMode]="severityEvaluationMode"
6845
6986
  [eventApis]="eventApis"
6846
6987
  [eventApiExecutor]="eventApiExecutor"
6847
6988
  [initialValues]="normalizedInitialValues"
@@ -6850,6 +6991,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6850
6991
  [fieldDataAccessApi]="fieldDataAccessApi"
6851
6992
  [formContentId]="formContentId"
6852
6993
  [formContentVersion]="formContentVersion"
6994
+ [refreshKey]="refreshKey"
6853
6995
  (formDataChange)="onValueChange($event)"
6854
6996
  (formDataByPageChange)="onJourneyValueByPageChange($event)"
6855
6997
  (formValidationChange)="onValidationChange($event)"
@@ -6865,6 +7007,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6865
7007
  [initialValues]="normalizedInitialValues"
6866
7008
  [initialFieldLabels]="normalizedInitialFieldLabels"
6867
7009
  [mode]="viewOnly ? 'preview' : 'live'"
7010
+ [severityEvaluationMode]="severityEvaluationMode"
6868
7011
  [breakpoint]="breakpoint()"
6869
7012
  [uploadOnSubmit]="true"
6870
7013
  [eventApis]="eventApis"
@@ -6873,6 +7016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6873
7016
  [fieldDataAccessApi]="fieldDataAccessApi"
6874
7017
  [formContentId]="formContentId"
6875
7018
  [formContentVersion]="formContentVersion"
7019
+ [refreshKey]="refreshKey"
6876
7020
  (valueChange)="onValueChange($event)"
6877
7021
  (validationChange)="onValidationChange($event)"
6878
7022
  (uploadedFilesChange)="onUploadedFilesChange($event)"
@@ -6906,6 +7050,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6906
7050
  type: Input
6907
7051
  }], viewOnly: [{
6908
7052
  type: Input
7053
+ }], severityEvaluationMode: [{
7054
+ type: Input
6909
7055
  }], eventApis: [{
6910
7056
  type: Input
6911
7057
  }], eventApiExecutor: [{
@@ -6918,6 +7064,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
6918
7064
  type: Input
6919
7065
  }], formContentVersion: [{
6920
7066
  type: Input
7067
+ }], refreshKey: [{
7068
+ type: Input
6921
7069
  }], formDataChange: [{
6922
7070
  type: Output
6923
7071
  }], formDataByPageChange: [{
@@ -8999,7 +9147,7 @@ class LayoutCanvasComponent {
8999
9147
 
9000
9148
  <!-- Hidden file input for import -->
9001
9149
  <input type="file" #fileInput accept=".json" (change)="onFileSelected($event)" style="display: none;">
9002
- `, isInline: true, styles: [".canvas-grid{background-image:radial-gradient(rgba(148,163,184,.35) 1px,transparent 1px);background-size:18px 18px}.custom-scrollbar::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:transparent;border-radius:10px}.custom-scrollbar:hover::-webkit-scrollbar-thumb{background:#00000026}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:transparent transparent}.custom-scrollbar:hover{scrollbar-color:rgba(0,0,0,.15) transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: MonacoEditorComponent, selector: "app-monaco-editor", inputs: ["value", "language", "theme", "readOnly", "minimap", "options"], outputs: ["valueChange"] }] });
9150
+ `, isInline: true, styles: [".canvas-grid{background-image:radial-gradient(rgba(148,163,184,.35) 1px,transparent 1px);background-size:18px 18px}.custom-scrollbar::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:transparent;border-radius:10px}.custom-scrollbar:hover::-webkit-scrollbar-thumb{background:#00000026}.custom-scrollbar{scrollbar-width:thin;scrollbar-color:transparent transparent}.custom-scrollbar:hover{scrollbar-color:rgba(0,0,0,.15) transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: MonacoEditorComponent, selector: "app-monaco-editor", inputs: ["value", "language", "theme", "readOnly", "minimap", "options"], outputs: ["valueChange"] }] });
9003
9151
  }
9004
9152
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutCanvasComponent, decorators: [{
9005
9153
  type: Component,
@@ -17147,7 +17295,8 @@ class QueryBuilderComponent {
17147
17295
  { label: 'Contains', value: 'contains' },
17148
17296
  { label: 'Is Empty', value: 'empty' },
17149
17297
  { label: 'Not Empty', value: 'notEmpty' },
17150
- { label: 'Is Truthy', value: 'truthy' }
17298
+ { label: 'Is Truthy', value: 'truthy' },
17299
+ { label: 'Is Not Truthy', value: 'notTruthy' }
17151
17300
  ];
17152
17301
  fieldOptions() {
17153
17302
  return [
@@ -17229,7 +17378,7 @@ class QueryBuilderComponent {
17229
17378
  this.emitChange();
17230
17379
  }
17231
17380
  requiresValue(operator) {
17232
- return !['empty', 'notEmpty', 'truthy'].includes(operator);
17381
+ return !['empty', 'notEmpty', 'truthy', 'notTruthy'].includes(operator);
17233
17382
  }
17234
17383
  conditionValueSource(condition) {
17235
17384
  return condition.valueSource === 'field' ? 'field' : 'literal';
@@ -19608,7 +19757,7 @@ class FormPreviewComponent {
19608
19757
  </div>
19609
19758
  </div>
19610
19759
  </div>
19611
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
19760
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
19612
19761
  }
19613
19762
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormPreviewComponent, decorators: [{
19614
19763
  type: Component,
@@ -23616,7 +23765,8 @@ class EventsWorkspaceComponent {
23616
23765
  { label: 'Ends With', value: 'endsWith' },
23617
23766
  { label: 'Is Empty', value: 'empty' },
23618
23767
  { label: 'Is Not Empty', value: 'notEmpty' },
23619
- { label: 'Is Truthy', value: 'truthy' }
23768
+ { label: 'Is Truthy', value: 'truthy' },
23769
+ { label: 'Is Not Truthy', value: 'notTruthy' }
23620
23770
  ];
23621
23771
  currentSchema = computed(() => this.draftSchema() ?? this.schema());
23622
23772
  fields = computed(() => this.flattenFields(this.currentSchema()));
@@ -24094,7 +24244,7 @@ class EventsWorkspaceComponent {
24094
24244
  this.updateNavigateConditionGroup(bindingIndex, actionIndex, this.toNavigateLogicGroup(next));
24095
24245
  }
24096
24246
  navigateOperatorNeedsValue(operator) {
24097
- return !['empty', 'notEmpty', 'truthy'].includes(operator);
24247
+ return !['empty', 'notEmpty', 'truthy', 'notTruthy'].includes(operator);
24098
24248
  }
24099
24249
  navigateConditionFields() {
24100
24250
  return this.fields().map(field => ({
@@ -26263,7 +26413,7 @@ class FormDesignerShellComponent {
26263
26413
  </div>
26264
26414
  </section>
26265
26415
  </div>
26266
- `, isInline: true, styles: ["@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}.animate-slide-in-right{animation:slideInRight .3s cubic-bezier(.16,1,.3,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "component", type: JsonFormDesignerComponent, selector: "app-json-form-designer", inputs: ["flavor", "mode", "eventApis", "eventApiExecutor", "pages", "activePageId", "canRemovePage"], outputs: ["pageAdd", "pageSelect", "pageRemove", "pageRename", "pageRouteChange"] }, { kind: "component", type: EventsWorkspaceComponent, selector: "app-events-workspace", inputs: ["schema", "readOnly", "eventApis", "eventApiBrowser", "pages"], outputs: ["schemaChange", "eventsSave"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "component", type: EmailRendererComponent, selector: "app-email-renderer", inputs: ["schema", "engine"] }, { kind: "component", type: GlobalDataManagerComponent, selector: "app-global-data-manager", outputs: ["close"] }, { kind: "component", type: AiChatDrawerComponent, selector: "app-ai-chat-drawer", outputs: ["close", "expand"] }, { kind: "component", type: AiWorkspaceComponent, selector: "app-ai-workspace", outputs: ["close"] }] });
26416
+ `, isInline: true, styles: ["@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}.animate-slide-in-right{animation:slideInRight .3s cubic-bezier(.16,1,.3,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "component", type: JsonFormDesignerComponent, selector: "app-json-form-designer", inputs: ["flavor", "mode", "eventApis", "eventApiExecutor", "pages", "activePageId", "canRemovePage"], outputs: ["pageAdd", "pageSelect", "pageRemove", "pageRename", "pageRouteChange"] }, { kind: "component", type: EventsWorkspaceComponent, selector: "app-events-workspace", inputs: ["schema", "readOnly", "eventApis", "eventApiBrowser", "pages"], outputs: ["schemaChange", "eventsSave"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }, { kind: "component", type: EmailRendererComponent, selector: "app-email-renderer", inputs: ["schema", "engine"] }, { kind: "component", type: GlobalDataManagerComponent, selector: "app-global-data-manager", outputs: ["close"] }, { kind: "component", type: AiChatDrawerComponent, selector: "app-ai-chat-drawer", outputs: ["close", "expand"] }, { kind: "component", type: AiWorkspaceComponent, selector: "app-ai-workspace", outputs: ["close"] }] });
26267
26417
  }
26268
26418
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: FormDesignerShellComponent, decorators: [{
26269
26419
  type: Component,
@@ -31517,7 +31667,7 @@ class WebsitePreviewShellComponent {
31517
31667
  }
31518
31668
  </main>
31519
31669
  </div>
31520
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
31670
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: JsonFormRendererComponent, selector: "app-json-form-renderer", inputs: ["schema", "initialValues", "initialFieldLabels", "mode", "device", "showLayoutGuides", "breakpoint", "eventLogger", "eventApis", "eventApiExecutor", "navigateToPage", "uploadOnSubmit", "severityEvaluationMode", "fieldDataAccessMap", "fieldDataAccessApi", "formContentId", "formContentVersion", "refreshKey"], outputs: ["valueChange", "groupedValueChange", "combinedValueChange", "validationChange", "uploadedFilesChange", "formSubmit"] }] });
31521
31671
  }
31522
31672
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: WebsitePreviewShellComponent, decorators: [{
31523
31673
  type: Component,
@@ -32651,6 +32801,10 @@ class TextFieldWidgetComponent {
32651
32801
  this.clearResolvedValue();
32652
32802
  return;
32653
32803
  }
32804
+ if (clearWhenMissing && !(await this.hasResolvedRows())) {
32805
+ this.clearResolvedValue();
32806
+ return;
32807
+ }
32654
32808
  const val = await this.dataProvider.getValue(this.config, this.engine);
32655
32809
  this.displayPrefix = await this.dataProvider.getValueDisplayPrefix(this.config, this.engine);
32656
32810
  if (val === undefined || val === null) {
@@ -32670,6 +32824,10 @@ class TextFieldWidgetComponent {
32670
32824
  // Ignore failed datasource refreshes; field remains editable.
32671
32825
  }
32672
32826
  }
32827
+ async hasResolvedRows() {
32828
+ const rows = await this.dataProvider.getList(this.config, this.engine);
32829
+ return rows.length > 0;
32830
+ }
32673
32831
  clearResolvedValue() {
32674
32832
  this.displayPrefix = '';
32675
32833
  this.control.setValue(null, { emitEvent: false });
@@ -36973,6 +37131,9 @@ class InlineQuillEditorComponent {
36973
37131
  this.applyEditorAppearance();
36974
37132
  }
36975
37133
  if (changes['html'] && !changes['html'].firstChange) {
37134
+ if (!this.readOnly) {
37135
+ return;
37136
+ }
36976
37137
  this.setHtml(this.html ?? '');
36977
37138
  }
36978
37139
  }
@@ -37066,6 +37227,9 @@ class InlineQuillEditorComponent {
37066
37227
  onEditorMouseDown(event) {
37067
37228
  this.stopInteractionEvent(event);
37068
37229
  }
37230
+ onEditorClick(event) {
37231
+ this.stopInteractionEvent(event);
37232
+ }
37069
37233
  onEditorPointerDown(event) {
37070
37234
  this.stopInteractionEvent(event);
37071
37235
  }
@@ -37086,6 +37250,7 @@ class InlineQuillEditorComponent {
37086
37250
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: InlineQuillEditorComponent, isStandalone: true, selector: "app-inline-quill-editor", inputs: { html: "html", placeholder: "placeholder", readOnly: "readOnly", autoFocus: "autoFocus", containerClass: "containerClass", editorClass: "editorClass", editorStyle: "editorStyle" }, outputs: { htmlChange: "htmlChange", editorBlur: "editorBlur", editorFocus: "editorFocus" }, viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
37087
37251
  <div class="inline-quill"
37088
37252
  [ngClass]="containerClass"
37253
+ (click)="onEditorClick($event)"
37089
37254
  (mousedown)="onEditorMouseDown($event)"
37090
37255
  (pointerdown)="onEditorPointerDown($event)"
37091
37256
  (touchstart)="onEditorTouchStart($event)"
@@ -37099,6 +37264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
37099
37264
  args: [{ selector: 'app-inline-quill-editor', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
37100
37265
  <div class="inline-quill"
37101
37266
  [ngClass]="containerClass"
37267
+ (click)="onEditorClick($event)"
37102
37268
  (mousedown)="onEditorMouseDown($event)"
37103
37269
  (pointerdown)="onEditorPointerDown($event)"
37104
37270
  (touchstart)="onEditorTouchStart($event)"