@memberjunction/ng-explorer-settings 6.2.0-edge.0 → 6.2.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/lib/account-info/account-info.component.d.ts +1 -1
  2. package/dist/lib/account-info/account-info.component.js +2 -2
  3. package/dist/lib/account-info/account-info.component.js.map +1 -1
  4. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +92 -10
  5. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
  6. package/dist/lib/application-management/application-dialog/application-dialog.component.js +222 -76
  7. package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
  8. package/dist/lib/application-management/application-management.component.d.ts +92 -10
  9. package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
  10. package/dist/lib/application-management/application-management.component.js +229 -65
  11. package/dist/lib/application-management/application-management.component.js.map +1 -1
  12. package/dist/lib/application-settings/application-settings.component.d.ts +4 -4
  13. package/dist/lib/application-settings/application-settings.component.js +10 -10
  14. package/dist/lib/application-settings/application-settings.component.js.map +1 -1
  15. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +88 -10
  16. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
  17. package/dist/lib/entity-permissions/entity-permissions.component.js +219 -63
  18. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
  19. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts +44 -6
  20. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
  21. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +117 -43
  22. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
  23. package/dist/lib/notification-preferences/notification-preferences.component.d.ts +25 -3
  24. package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
  25. package/dist/lib/notification-preferences/notification-preferences.component.js +62 -18
  26. package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
  27. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts +32 -4
  28. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
  29. package/dist/lib/role-management/role-dialog/role-dialog.component.js +84 -30
  30. package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
  31. package/dist/lib/role-management/role-management-agent-context.d.ts +12 -4
  32. package/dist/lib/role-management/role-management-agent-context.d.ts.map +1 -1
  33. package/dist/lib/role-management/role-management-agent-context.js +26 -10
  34. package/dist/lib/role-management/role-management-agent-context.js.map +1 -1
  35. package/dist/lib/role-management/role-management.component.d.ts +95 -11
  36. package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
  37. package/dist/lib/role-management/role-management.component.js +259 -91
  38. package/dist/lib/role-management/role-management.component.js.map +1 -1
  39. package/dist/lib/settings/settings.component.d.ts +87 -11
  40. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  41. package/dist/lib/settings/settings.component.js +211 -65
  42. package/dist/lib/settings/settings.component.js.map +1 -1
  43. package/dist/lib/shared/settings-card.component.d.ts +24 -4
  44. package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
  45. package/dist/lib/shared/settings-card.component.js +46 -6
  46. package/dist/lib/shared/settings-card.component.js.map +1 -1
  47. package/dist/lib/sql-logging/sql-logging.component.d.ts +172 -18
  48. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
  49. package/dist/lib/sql-logging/sql-logging.component.js +320 -108
  50. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
  51. package/dist/lib/user-app-config/user-app-config-content.component.js +3 -3
  52. package/dist/lib/user-app-config/user-app-config-content.component.js.map +1 -1
  53. package/dist/lib/user-app-config/user-app-config-reorder.d.ts +4 -0
  54. package/dist/lib/user-app-config/user-app-config-reorder.d.ts.map +1 -1
  55. package/dist/lib/user-app-config/user-app-config-reorder.js +11 -3
  56. package/dist/lib/user-app-config/user-app-config-reorder.js.map +1 -1
  57. package/dist/lib/user-management/transaction-group-refusals.d.ts +4 -2
  58. package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -1
  59. package/dist/lib/user-management/transaction-group-refusals.js +7 -3
  60. package/dist/lib/user-management/transaction-group-refusals.js.map +1 -1
  61. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts +44 -6
  62. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
  63. package/dist/lib/user-management/user-dialog/user-dialog.component.js +121 -47
  64. package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
  65. package/dist/lib/user-management/user-management-agent-context.d.ts +10 -0
  66. package/dist/lib/user-management/user-management-agent-context.d.ts.map +1 -1
  67. package/dist/lib/user-management/user-management-agent-context.js +26 -6
  68. package/dist/lib/user-management/user-management-agent-context.js.map +1 -1
  69. package/dist/lib/user-management/user-management.component.d.ts +174 -16
  70. package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
  71. package/dist/lib/user-management/user-management.component.js +480 -171
  72. package/dist/lib/user-management/user-management.component.js.map +1 -1
  73. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +97 -15
  74. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
  75. package/dist/lib/user-profile-settings/user-profile-settings.component.js +280 -116
  76. package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
  77. package/package.json +20 -20
@@ -377,33 +377,113 @@ function ApplicationDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
377
377
  i0.ɵɵconditional(ctx_r1.isLoading ? 43 : 44);
378
378
  } }
379
379
  export class ApplicationDialogComponent extends BaseAngularComponent {
380
- data = null;
381
- visible = false;
382
- result = new EventEmitter();
380
+ Data = null;
381
+ /** @deprecated Use {@link Data}. */
382
+ set data(value) {
383
+ this.Data = value;
384
+ }
385
+ /** @deprecated Use {@link Data}. */
386
+ get data() {
387
+ return this.Data;
388
+ }
389
+ Visible = false;
390
+ /** @deprecated Use {@link Visible}. */
391
+ set visible(value) {
392
+ this.Visible = value;
393
+ }
394
+ /** @deprecated Use {@link Visible}. */
395
+ get visible() {
396
+ return this.Visible;
397
+ }
398
+ Result = new EventEmitter();
399
+ /**
400
+ * @deprecated Use {@link Result}.
401
+ *
402
+ * The same emitter under the old binding name, so a template still binding
403
+ * (result) keeps working. Must stay AFTER Result: class fields
404
+ * initialise in order, and the other way round this captures undefined.
405
+ */
406
+ result = this.Result;
383
407
  fb = inject(FormBuilder);
384
408
  cdr = inject(ChangeDetectorRef);
385
409
  ngZone = inject(NgZone);
386
410
  get metadata() { return this.ProviderToUse; }
387
- applicationForm;
411
+ ApplicationForm;
412
+ /** @deprecated Use {@link ApplicationForm}. */
413
+ get applicationForm() {
414
+ return this.ApplicationForm;
415
+ }
416
+ /** @deprecated Use {@link ApplicationForm}. */
417
+ set applicationForm(value) {
418
+ this.ApplicationForm = value;
419
+ }
388
420
  isLoading = false;
389
421
  error = null;
390
422
  // Entity management
391
- applicationEntities = [];
392
- availableEntities = [];
393
- allEntities = [];
423
+ ApplicationEntities = [];
424
+ /** @deprecated Use {@link ApplicationEntities}. */
425
+ get applicationEntities() {
426
+ return this.ApplicationEntities;
427
+ }
428
+ /** @deprecated Use {@link ApplicationEntities}. */
429
+ set applicationEntities(value) {
430
+ this.ApplicationEntities = value;
431
+ }
432
+ AvailableEntities = [];
433
+ /** @deprecated Use {@link AvailableEntities}. */
434
+ get availableEntities() {
435
+ return this.AvailableEntities;
436
+ }
437
+ /** @deprecated Use {@link AvailableEntities}. */
438
+ set availableEntities(value) {
439
+ this.AvailableEntities = value;
440
+ }
441
+ AllEntities = [];
442
+ /** @deprecated Use {@link AllEntities}. */
443
+ get allEntities() {
444
+ return this.AllEntities;
445
+ }
446
+ /** @deprecated Use {@link AllEntities}. */
447
+ set allEntities(value) {
448
+ this.AllEntities = value;
449
+ }
394
450
  // Search filter for available entities
395
- entitySearchTerm = '';
451
+ EntitySearchTerm = '';
452
+ /** @deprecated Use {@link EntitySearchTerm}. */
453
+ get entitySearchTerm() {
454
+ return this.EntitySearchTerm;
455
+ }
456
+ /** @deprecated Use {@link EntitySearchTerm}. */
457
+ set entitySearchTerm(value) {
458
+ this.EntitySearchTerm = value;
459
+ }
396
460
  // Section expansion state
397
- sectionExpanded = {
461
+ SectionExpanded = {
398
462
  basicInfo: true,
399
463
  entities: true,
400
464
  systemInfo: false
401
465
  };
466
+ /** @deprecated Use {@link SectionExpanded}. */
467
+ get sectionExpanded() {
468
+ return this.SectionExpanded;
469
+ }
470
+ /** @deprecated Use {@link SectionExpanded}. */
471
+ set sectionExpanded(value) {
472
+ this.SectionExpanded = value;
473
+ }
402
474
  // Fullscreen state
403
- isFullscreen = false;
475
+ IsFullscreen = false;
476
+ /** @deprecated Use {@link IsFullscreen}. */
477
+ get isFullscreen() {
478
+ return this.IsFullscreen;
479
+ }
480
+ /** @deprecated Use {@link IsFullscreen}. */
481
+ set isFullscreen(value) {
482
+ this.IsFullscreen = value;
483
+ }
404
484
  constructor() {
405
485
  super();
406
- this.applicationForm = this.fb.group({
486
+ this.ApplicationForm = this.fb.group({
407
487
  name: ['', [Validators.required, Validators.maxLength(100)]],
408
488
  description: ['']
409
489
  });
@@ -412,7 +492,7 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
412
492
  // Initial setup
413
493
  }
414
494
  ngOnChanges(changes) {
415
- if (changes['visible'] && this.visible) {
495
+ if (changes['visible'] && this.Visible) {
416
496
  this.initializeDialog();
417
497
  }
418
498
  }
@@ -420,14 +500,14 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
420
500
  // Cleanup if needed
421
501
  }
422
502
  async initializeDialog() {
423
- if (!this.visible)
503
+ if (!this.Visible)
424
504
  return;
425
505
  try {
426
506
  this.isLoading = true;
427
507
  this.error = null;
428
508
  // Load all entities first
429
509
  await this.loadAllEntities();
430
- if (this.data?.application && this.isEditMode) {
510
+ if (this.Data?.application && this.IsEditMode) {
431
511
  await this.loadApplicationData();
432
512
  }
433
513
  else {
@@ -455,34 +535,42 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
455
535
  ResultType: 'entity_object',
456
536
  OrderBy: 'Name ASC'
457
537
  });
458
- this.allEntities = result.Success ? result.Results : [];
538
+ this.AllEntities = result.Success ? result.Results : [];
459
539
  }
460
540
  resetForm() {
461
- this.applicationForm.reset({
541
+ this.ApplicationForm.reset({
462
542
  name: '',
463
543
  description: ''
464
544
  });
465
- this.applicationEntities = [];
466
- this.availableEntities = [...this.allEntities];
467
- this.entitySearchTerm = '';
545
+ this.ApplicationEntities = [];
546
+ this.AvailableEntities = [...this.AllEntities];
547
+ this.EntitySearchTerm = '';
468
548
  this.error = null;
469
549
  }
470
550
  onEscapeKey() {
471
- if (this.visible) {
551
+ if (this.Visible) {
472
552
  this.onCancel();
473
553
  }
474
554
  }
555
+ get WindowTitle() {
556
+ return this.IsEditMode ? 'Edit Application' : 'Create New Application';
557
+ }
558
+ /** @deprecated Use {@link WindowTitle}. */
475
559
  get windowTitle() {
476
- return this.isEditMode ? 'Edit Application' : 'Create New Application';
560
+ return this.WindowTitle;
561
+ }
562
+ get IsEditMode() {
563
+ return this.Data?.mode === 'edit';
477
564
  }
565
+ /** @deprecated Use {@link IsEditMode}. */
478
566
  get isEditMode() {
479
- return this.data?.mode === 'edit';
567
+ return this.IsEditMode;
480
568
  }
481
569
  async loadApplicationData() {
482
- if (!this.data?.application)
570
+ if (!this.Data?.application)
483
571
  return;
484
- const app = this.data.application;
485
- this.applicationForm.patchValue({
572
+ const app = this.Data.application;
573
+ this.ApplicationForm.patchValue({
486
574
  name: app.Name,
487
575
  description: app.Description
488
576
  });
@@ -499,12 +587,12 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
499
587
  OrderBy: 'Sequence ASC'
500
588
  });
501
589
  if (result.Success && result.Results) {
502
- this.applicationEntities = [];
590
+ this.ApplicationEntities = [];
503
591
  const usedEntityIds = new Set();
504
592
  for (const appEntity of result.Results) {
505
- const entity = this.allEntities.find(e => UUIDsEqual(e.ID, appEntity.EntityID));
593
+ const entity = this.AllEntities.find(e => UUIDsEqual(e.ID, appEntity.EntityID));
506
594
  if (entity) {
507
- this.applicationEntities.push({
595
+ this.ApplicationEntities.push({
508
596
  entity,
509
597
  applicationEntity: appEntity,
510
598
  sequence: appEntity.Sequence || 0,
@@ -516,19 +604,19 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
516
604
  }
517
605
  }
518
606
  // Set available entities (excluding already assigned ones)
519
- this.availableEntities = this.allEntities.filter(e => !usedEntityIds.has(e.ID));
607
+ this.AvailableEntities = this.AllEntities.filter(e => !usedEntityIds.has(e.ID));
520
608
  }
521
609
  }
522
610
  catch (error) {
523
611
  console.warn('Failed to load application entities:', error);
524
- this.availableEntities = [...this.allEntities];
612
+ this.AvailableEntities = [...this.AllEntities];
525
613
  }
526
614
  }
527
- addEntity(entity) {
615
+ AddEntity(entity) {
528
616
  // Add entity to application
529
- this.applicationEntities.push({
617
+ this.ApplicationEntities.push({
530
618
  entity,
531
- sequence: this.applicationEntities.length + 1,
619
+ sequence: this.ApplicationEntities.length + 1,
532
620
  defaultForNewUser: false,
533
621
  isNew: true,
534
622
  hasChanges: false
@@ -536,95 +624,143 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
536
624
  // Update all sequences to be consecutive
537
625
  this.updateSequences();
538
626
  // Remove from available entities
539
- this.availableEntities = this.availableEntities.filter(e => !UUIDsEqual(e.ID, entity.ID));
627
+ this.AvailableEntities = this.AvailableEntities.filter(e => !UUIDsEqual(e.ID, entity.ID));
540
628
  }
541
- removeEntity(config) {
629
+ /** @deprecated Use {@link AddEntity}. */
630
+ addEntity(entity) {
631
+ return this.AddEntity(entity);
632
+ }
633
+ RemoveEntity(config) {
542
634
  // Remove from application entities
543
- this.applicationEntities = this.applicationEntities.filter(ae => !UUIDsEqual(ae.entity.ID, config.entity.ID));
635
+ this.ApplicationEntities = this.ApplicationEntities.filter(ae => !UUIDsEqual(ae.entity.ID, config.entity.ID));
544
636
  // Update all sequences to be consecutive
545
637
  this.updateSequences();
546
638
  // Add back to available entities if not already there
547
- if (!this.availableEntities.find(e => UUIDsEqual(e.ID, config.entity.ID))) {
548
- this.availableEntities.push(config.entity);
549
- this.availableEntities.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));
639
+ if (!this.AvailableEntities.find(e => UUIDsEqual(e.ID, config.entity.ID))) {
640
+ this.AvailableEntities.push(config.entity);
641
+ this.AvailableEntities.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));
550
642
  }
551
643
  }
552
- moveEntityUp(index) {
644
+ /** @deprecated Use {@link RemoveEntity}. */
645
+ removeEntity(config) {
646
+ return this.RemoveEntity(config);
647
+ }
648
+ MoveEntityUp(index) {
553
649
  if (index > 0) {
554
- const temp = this.applicationEntities[index];
555
- this.applicationEntities[index] = this.applicationEntities[index - 1];
556
- this.applicationEntities[index - 1] = temp;
650
+ const temp = this.ApplicationEntities[index];
651
+ this.ApplicationEntities[index] = this.ApplicationEntities[index - 1];
652
+ this.ApplicationEntities[index - 1] = temp;
557
653
  this.updateSequences();
558
654
  }
559
655
  }
560
- moveEntityDown(index) {
561
- if (index < this.applicationEntities.length - 1) {
562
- const temp = this.applicationEntities[index];
563
- this.applicationEntities[index] = this.applicationEntities[index + 1];
564
- this.applicationEntities[index + 1] = temp;
656
+ /** @deprecated Use {@link MoveEntityUp}. */
657
+ moveEntityUp(index) {
658
+ return this.MoveEntityUp(index);
659
+ }
660
+ MoveEntityDown(index) {
661
+ if (index < this.ApplicationEntities.length - 1) {
662
+ const temp = this.ApplicationEntities[index];
663
+ this.ApplicationEntities[index] = this.ApplicationEntities[index + 1];
664
+ this.ApplicationEntities[index + 1] = temp;
565
665
  this.updateSequences();
566
666
  }
567
667
  }
668
+ /** @deprecated Use {@link MoveEntityDown}. */
669
+ moveEntityDown(index) {
670
+ return this.MoveEntityDown(index);
671
+ }
568
672
  updateSequences() {
569
- this.applicationEntities.forEach((config, index) => {
673
+ this.ApplicationEntities.forEach((config, index) => {
570
674
  config.sequence = index + 1;
571
675
  if (!config.isNew) {
572
676
  config.hasChanges = true;
573
677
  }
574
678
  });
575
679
  }
576
- onDefaultForNewUserChange(config) {
680
+ OnDefaultForNewUserChange(config) {
577
681
  if (!config.isNew) {
578
682
  config.hasChanges = true;
579
683
  }
580
684
  }
685
+ /** @deprecated Use {@link OnDefaultForNewUserChange}. */
686
+ onDefaultForNewUserChange(config) {
687
+ return this.OnDefaultForNewUserChange(config);
688
+ }
689
+ get HasEntityChanges() {
690
+ return this.ApplicationEntities.some(ae => ae.isNew || ae.hasChanges);
691
+ }
692
+ /** @deprecated Use {@link HasEntityChanges}. */
581
693
  get hasEntityChanges() {
582
- return this.applicationEntities.some(ae => ae.isNew || ae.hasChanges);
694
+ return this.HasEntityChanges;
583
695
  }
584
696
  // Filtered available entities based on search term
585
- get filteredAvailableEntities() {
586
- if (!this.entitySearchTerm || !this.entitySearchTerm.trim()) {
587
- return this.availableEntities;
697
+ get FilteredAvailableEntities() {
698
+ if (!this.EntitySearchTerm || !this.EntitySearchTerm.trim()) {
699
+ return this.AvailableEntities;
588
700
  }
589
- const searchLower = this.entitySearchTerm.toLowerCase().trim();
590
- return this.availableEntities.filter(entity => (entity.DisplayName || '').toLowerCase().includes(searchLower) ||
701
+ const searchLower = this.EntitySearchTerm.toLowerCase().trim();
702
+ return this.AvailableEntities.filter(entity => (entity.DisplayName || '').toLowerCase().includes(searchLower) ||
591
703
  (entity.Name || '').toLowerCase().includes(searchLower) ||
592
704
  (entity.Description || '').toLowerCase().includes(searchLower));
593
705
  }
594
- getEntityDisplayName(entity) {
706
+ /** @deprecated Use {@link FilteredAvailableEntities}. */
707
+ get filteredAvailableEntities() {
708
+ return this.FilteredAvailableEntities;
709
+ }
710
+ GetEntityDisplayName(entity) {
595
711
  return entity.DisplayName || entity.Name;
596
712
  }
597
- onEntitySearchChange(event) {
713
+ /** @deprecated Use {@link GetEntityDisplayName}. */
714
+ getEntityDisplayName(entity) {
715
+ return this.GetEntityDisplayName(entity);
716
+ }
717
+ OnEntitySearchChange(event) {
598
718
  const value = event.target.value;
599
- this.entitySearchTerm = value;
719
+ this.EntitySearchTerm = value;
720
+ }
721
+ /** @deprecated Use {@link OnEntitySearchChange}. */
722
+ onEntitySearchChange(event) {
723
+ return this.OnEntitySearchChange(event);
724
+ }
725
+ ClearEntitySearch() {
726
+ this.EntitySearchTerm = '';
600
727
  }
728
+ /** @deprecated Use {@link ClearEntitySearch}. */
601
729
  clearEntitySearch() {
602
- this.entitySearchTerm = '';
730
+ return this.ClearEntitySearch();
603
731
  }
604
732
  toggleSection(section) {
605
- this.sectionExpanded[section] = !this.sectionExpanded[section];
733
+ this.SectionExpanded[section] = !this.SectionExpanded[section];
606
734
  }
735
+ ToggleFullscreen() {
736
+ this.IsFullscreen = !this.IsFullscreen;
737
+ }
738
+ /** @deprecated Use {@link ToggleFullscreen}. */
607
739
  toggleFullscreen() {
608
- this.isFullscreen = !this.isFullscreen;
740
+ return this.ToggleFullscreen();
609
741
  }
610
- onEntityDrop(event) {
742
+ OnEntityDrop(event) {
611
743
  if (event.previousIndex !== event.currentIndex) {
612
- moveItemInArray(this.applicationEntities, event.previousIndex, event.currentIndex);
744
+ moveItemInArray(this.ApplicationEntities, event.previousIndex, event.currentIndex);
613
745
  this.updateSequences();
614
746
  }
615
747
  }
616
- async onSubmit() {
617
- if (this.applicationForm.invalid) {
618
- this.markFormGroupTouched(this.applicationForm);
748
+ /** @deprecated Use {@link OnEntityDrop}. */
749
+ onEntityDrop(event) {
750
+ return this.OnEntityDrop(event);
751
+ }
752
+ async OnSubmit() {
753
+ if (this.ApplicationForm.invalid) {
754
+ this.markFormGroupTouched(this.ApplicationForm);
619
755
  return;
620
756
  }
621
757
  this.isLoading = true;
622
758
  this.error = null;
623
759
  try {
624
760
  let application;
625
- if (this.isEditMode && this.data?.application) {
761
+ if (this.IsEditMode && this.Data?.application) {
626
762
  // Edit existing application
627
- application = this.data.application;
763
+ application = this.Data.application;
628
764
  }
629
765
  else {
630
766
  // Create new application
@@ -632,7 +768,7 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
632
768
  application.NewRecord();
633
769
  }
634
770
  // Update application properties
635
- const formValue = this.applicationForm.value;
771
+ const formValue = this.ApplicationForm.value;
636
772
  application.Name = formValue.name;
637
773
  application.Description = formValue.description || null;
638
774
  // Save application
@@ -641,10 +777,10 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
641
777
  throw new Error(application.LatestResult?.Message || 'Failed to save application');
642
778
  }
643
779
  // Save application entities if there are changes
644
- if (this.hasEntityChanges) {
780
+ if (this.HasEntityChanges) {
645
781
  await this.saveApplicationEntities(application.ID);
646
782
  }
647
- this.result.emit({ action: 'save', application });
783
+ this.Result.emit({ action: 'save', application });
648
784
  }
649
785
  catch (error) {
650
786
  console.error('Error saving application:', error);
@@ -660,9 +796,13 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
660
796
  });
661
797
  }
662
798
  }
799
+ /** @deprecated Use {@link OnSubmit}. */
800
+ async onSubmit() {
801
+ return this.OnSubmit();
802
+ }
663
803
  async saveApplicationEntities(applicationId) {
664
804
  // Save or update each MJApplicationEntity record
665
- for (const config of this.applicationEntities) {
805
+ for (const config of this.ApplicationEntities) {
666
806
  if (config.isNew || config.hasChanges) {
667
807
  let appEntity;
668
808
  if (config.isNew) {
@@ -689,7 +829,7 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
689
829
  }
690
830
  }
691
831
  onCancel() {
692
- this.result.emit({ action: 'cancel' });
832
+ this.Result.emit({ action: 'cancel' });
693
833
  }
694
834
  markFormGroupTouched(formGroup) {
695
835
  Object.keys(formGroup.controls).forEach(key => {
@@ -700,7 +840,7 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
700
840
  static ɵfac = function ApplicationDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ApplicationDialogComponent)(); };
701
841
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ApplicationDialogComponent, selectors: [["mj-application-dialog"]], hostBindings: function ApplicationDialogComponent_HostBindings(rf, ctx) { if (rf & 1) {
702
842
  i0.ɵɵlistener("keydown.escape", function ApplicationDialogComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
703
- } }, inputs: { data: "data", visible: "visible" }, outputs: { result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["role", "presentation", 1, "modal-backdrop"], ["role", "presentation", 1, "modal-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "application-dialog-title", "aria-describedby", "application-dialog-description", 1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "modal-header-content"], ["id", "application-dialog-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid"], ["id", "application-dialog-description", 1, "modal-subtitle"], [1, "modal-header-actions"], ["type", "button", 1, "modal-action-btn", 3, "click"], ["aria-label", "Close dialog", "type", "button", 1, "modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "modal-body"], [3, "ngSubmit", "formGroup"], [1, "form-section"], [1, "app-dialog-section", 3, "ExpandedChange", "Expanded"], ["mjAccordionTitle", ""], [1, "section-content"], [1, "form-grid"], [1, "form-field"], ["for", "app-name", 1, "field-label", "required"], ["id", "app-name", "type", "text", "formControlName", "name", "placeholder", "My Application", "aria-describedby", "app-name-error", 1, "field-input"], ["id", "app-name-error", "role", "alert", 1, "field-error"], ["for", "app-description", 1, "field-label"], ["id", "app-description", "formControlName", "description", "placeholder", "Describe the application's purpose and functionality...", "rows", "4", 1, "field-textarea"], [1, "field-hint"], [1, "assigned-entities"], [1, "no-entities"], [1, "available-entities"], [1, "all-assigned"], [1, "app-dialog-section", 3, "Expanded"], [1, "modal-footer"], ["type", "submit", "mjButton", "", "variant", "primary", 3, "click", "disabled"], ["type", "button", "mjButton", "", 3, "click"], ["Variant", "error", 3, "Message"], [1, "app-dialog-section-title"], [1, "section-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-info-circle"], [1, "section-description"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-circle"], ["aria-hidden", "true", 1, "fa-solid", "fa-database"], [1, "subsection-title"], ["role", "list", "cdkDropList", "", 1, "entities-list", 3, "cdkDropListDropped"], ["role", "listitem", "cdkDrag", "", 1, "entity-item", 3, "is-new", "has-changes"], ["role", "listitem", "cdkDrag", "", 1, "entity-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-grip-vertical", "drag-handle"], [1, "entity-info"], [1, "entity-icon"], ["aria-hidden", "true", 1, "fa-solid", "fa-table"], [1, "entity-details"], [1, "entity-name"], [1, "fa-solid", "fa-info-circle", "entity-info-icon", 3, "title"], [1, "entity-config"], [1, "config-item"], [1, "config-label"], ["type", "checkbox", 1, "config-checkbox", 3, "ngModelChange", "change", "ngModel", "ngModelOptions"], [1, "checkbox-text"], [1, "sequence-badge"], [1, "entity-actions"], ["type", "button", "title", "Remove entity", 1, "btn-icon", "btn-danger", 3, "click"], [1, "empty-subtext"], [1, "available-entities-header"], [1, "entity-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "entity-search-icon"], ["type", "text", "placeholder", "Search entities...", "aria-label", "Search available entities", 1, "entity-search-input", 3, "input", "value"], ["type", "button", "aria-label", "Clear search", 1, "entity-search-clear"], ["role", "list", 1, "entities-grid"], [1, "no-search-results"], ["type", "button", "aria-label", "Clear search", 1, "entity-search-clear", 3, "click"], ["type", "button", "role", "listitem", 1, "entity-chip"], ["type", "button", "role", "listitem", 1, "entity-chip", 3, "click"], [1, "chip-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], [1, "chip-name"], ["aria-hidden", "true", 1, "fa-solid", "fa-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-circle"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "fa-solid", "fa-save"]], template: function ApplicationDialogComponent_Template(rf, ctx) { if (rf & 1) {
843
+ } }, inputs: { Data: "Data", data: "data", Visible: "Visible", visible: "visible" }, outputs: { Result: "Result", result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["role", "presentation", 1, "modal-backdrop"], ["role", "presentation", 1, "modal-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "application-dialog-title", "aria-describedby", "application-dialog-description", 1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "modal-header-content"], ["id", "application-dialog-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid"], ["id", "application-dialog-description", 1, "modal-subtitle"], [1, "modal-header-actions"], ["type", "button", 1, "modal-action-btn", 3, "click"], ["aria-label", "Close dialog", "type", "button", 1, "modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "modal-body"], [3, "ngSubmit", "formGroup"], [1, "form-section"], [1, "app-dialog-section", 3, "ExpandedChange", "Expanded"], ["mjAccordionTitle", ""], [1, "section-content"], [1, "form-grid"], [1, "form-field"], ["for", "app-name", 1, "field-label", "required"], ["id", "app-name", "type", "text", "formControlName", "name", "placeholder", "My Application", "aria-describedby", "app-name-error", 1, "field-input"], ["id", "app-name-error", "role", "alert", 1, "field-error"], ["for", "app-description", 1, "field-label"], ["id", "app-description", "formControlName", "description", "placeholder", "Describe the application's purpose and functionality...", "rows", "4", 1, "field-textarea"], [1, "field-hint"], [1, "assigned-entities"], [1, "no-entities"], [1, "available-entities"], [1, "all-assigned"], [1, "app-dialog-section", 3, "Expanded"], [1, "modal-footer"], ["type", "submit", "mjButton", "", "variant", "primary", 3, "click", "disabled"], ["type", "button", "mjButton", "", 3, "click"], ["Variant", "error", 3, "Message"], [1, "app-dialog-section-title"], [1, "section-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-info-circle"], [1, "section-description"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-circle"], ["aria-hidden", "true", 1, "fa-solid", "fa-database"], [1, "subsection-title"], ["role", "list", "cdkDropList", "", 1, "entities-list", 3, "cdkDropListDropped"], ["role", "listitem", "cdkDrag", "", 1, "entity-item", 3, "is-new", "has-changes"], ["role", "listitem", "cdkDrag", "", 1, "entity-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-grip-vertical", "drag-handle"], [1, "entity-info"], [1, "entity-icon"], ["aria-hidden", "true", 1, "fa-solid", "fa-table"], [1, "entity-details"], [1, "entity-name"], [1, "fa-solid", "fa-info-circle", "entity-info-icon", 3, "title"], [1, "entity-config"], [1, "config-item"], [1, "config-label"], ["type", "checkbox", 1, "config-checkbox", 3, "ngModelChange", "change", "ngModel", "ngModelOptions"], [1, "checkbox-text"], [1, "sequence-badge"], [1, "entity-actions"], ["type", "button", "title", "Remove entity", 1, "btn-icon", "btn-danger", 3, "click"], [1, "empty-subtext"], [1, "available-entities-header"], [1, "entity-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "entity-search-icon"], ["type", "text", "placeholder", "Search entities...", "aria-label", "Search available entities", 1, "entity-search-input", 3, "input", "value"], ["type", "button", "aria-label", "Clear search", 1, "entity-search-clear"], ["role", "list", 1, "entities-grid"], [1, "no-search-results"], ["type", "button", "aria-label", "Clear search", 1, "entity-search-clear", 3, "click"], ["type", "button", "role", "listitem", 1, "entity-chip"], ["type", "button", "role", "listitem", 1, "entity-chip", 3, "click"], [1, "chip-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], [1, "chip-name"], ["aria-hidden", "true", 1, "fa-solid", "fa-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-circle"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "fa-solid", "fa-save"]], template: function ApplicationDialogComponent_Template(rf, ctx) { if (rf & 1) {
704
844
  i0.ɵɵconditionalCreate(0, ApplicationDialogComponent_Conditional_0_Template, 47, 31, "div", 0);
705
845
  } if (rf & 2) {
706
846
  i0.ɵɵconditional(ctx.visible ? 0 : -1);
@@ -709,10 +849,16 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
709
849
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ApplicationDialogComponent, [{
710
850
  type: Component,
711
851
  args: [{ standalone: false, selector: 'mj-application-dialog', template: "@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\" role=\"presentation\">\n <div\n class=\"modal-dialog\"\n [class.fullscreen]=\"isFullscreen\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"application-dialog-title\"\n aria-describedby=\"application-dialog-description\"\n >\n <!-- Modal Header -->\n <div class=\"modal-header\" [class.create-mode]=\"!isEditMode\" [class.edit-mode]=\"isEditMode\">\n <div class=\"modal-header-content\">\n <h2 class=\"modal-title\" id=\"application-dialog-title\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!isEditMode\" [class.fa-layer-group]=\"isEditMode\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Edit Application' : 'Create New Application' }}\n </h2>\n <p class=\"modal-subtitle\" id=\"application-dialog-description\">\n {{ isEditMode ? 'Update application information and settings' : 'Add a new application to the system' }}\n </p>\n </div>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleFullscreen()\"\n [attr.aria-label]=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isFullscreen\" [class.fa-expand]=\"!isFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"modal-close\"\n (click)=\"onCancel()\"\n aria-label=\"Close dialog\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"applicationForm\" (ngSubmit)=\"onSubmit()\">\n <!-- Error Alert -->\n @if (error) {\n <div class=\"form-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n\n <!-- Basic Information Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.basicInfo\" (ExpandedChange)=\"toggleSection('basicInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n Application Information\n </span>\n <span class=\"section-description\">Define the application's basic properties</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"app-name\">Application Name</label>\n <input\n id=\"app-name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"My Application\"\n [class.error]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n [attr.aria-invalid]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n aria-describedby=\"app-name-error\"\n />\n @if (applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched) {\n <div class=\"field-error\" id=\"app-name-error\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-circle\" aria-hidden=\"true\"></i>\n @if (applicationForm.get('name')?.errors?.['required']) {\n Application name is required\n }\n @if (applicationForm.get('name')?.errors?.['maxlength']) {\n Application name cannot exceed 100 characters\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"app-description\">Description</label>\n <textarea\n id=\"app-description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the application's purpose and functionality...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this application does and its main features.\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- Entity Management Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.entities\" (ExpandedChange)=\"toggleSection('entities')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Application Entities\n </span>\n <span class=\"section-description\">Manage which entities are included in this application</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <!-- Assigned Entities -->\n @if (applicationEntities.length > 0) {\n <div class=\"assigned-entities\">\n <h4 class=\"subsection-title\">Assigned Entities ({{ applicationEntities.length }})</h4>\n <div class=\"entities-list\"\n role=\"list\"\n cdkDropList\n (cdkDropListDropped)=\"onEntityDrop($event)\">\n @for (config of applicationEntities; track config.entity.ID; let i = $index) {\n <div\n class=\"entity-item\"\n [class.is-new]=\"config.isNew\"\n [class.has-changes]=\"config.hasChanges\"\n role=\"listitem\"\n cdkDrag\n >\n <i class=\"fa-solid fa-grip-vertical drag-handle\" aria-hidden=\"true\"></i>\n <div class=\"entity-info\">\n <div class=\"entity-icon\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"entity-details\">\n <div class=\"entity-name\">\n {{ getEntityDisplayName(config.entity) }}\n @if (config.entity.Description) {\n <i\n class=\"fa-solid fa-info-circle entity-info-icon\"\n [title]=\"config.entity.Description\"\n [attr.aria-label]=\"'Entity description: ' + config.entity.Description\"\n ></i>\n }\n </div>\n </div>\n </div>\n\n <div class=\"entity-config\">\n <div class=\"config-item\">\n <label class=\"config-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"config.defaultForNewUser\"\n [ngModelOptions]=\"{standalone: true}\"\n (change)=\"onDefaultForNewUserChange(config)\"\n class=\"config-checkbox\"\n />\n <span class=\"checkbox-text\">Default for new users</span>\n </label>\n </div>\n <div class=\"sequence-badge\" [attr.aria-label]=\"'Sequence ' + config.sequence\">{{ config.sequence }}</div>\n </div>\n\n <div class=\"entity-actions\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeEntity(config)\"\n title=\"Remove entity\"\n [attr.aria-label]=\"'Remove ' + getEntityDisplayName(config.entity)\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"no-entities\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n <p>No entities assigned to this application</p>\n <p class=\"empty-subtext\">Add entities from the available list below</p>\n </div>\n }\n\n <!-- Available Entities -->\n @if (availableEntities.length > 0) {\n <div class=\"available-entities\">\n <div class=\"available-entities-header\">\n <h4 class=\"subsection-title\">Available Entities ({{ filteredAvailableEntities.length }} of {{ availableEntities.length }})</h4>\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search entity-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"entity-search-input\"\n placeholder=\"Search entities...\"\n [value]=\"entitySearchTerm\"\n (input)=\"onEntitySearchChange($event)\"\n aria-label=\"Search available entities\"\n />\n @if (entitySearchTerm) {\n <button\n type=\"button\"\n class=\"entity-search-clear\"\n (click)=\"clearEntitySearch()\"\n aria-label=\"Clear search\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n @if (filteredAvailableEntities.length > 0) {\n <div class=\"entities-grid\" role=\"list\">\n @for (entity of filteredAvailableEntities; track entity.ID) {\n <button\n type=\"button\"\n class=\"entity-chip\"\n (click)=\"addEntity(entity)\"\n role=\"listitem\"\n [attr.aria-label]=\"'Add ' + getEntityDisplayName(entity)\"\n >\n <div class=\"chip-content\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"chip-name\">{{ getEntityDisplayName(entity) }}</span>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"no-search-results\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <p>No entities match \"{{ entitySearchTerm }}\"</p>\n </div>\n }\n </div>\n } @else {\n <div class=\"all-assigned\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <p>All entities have been assigned to this application</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- System Information Section (Edit Mode Only) -->\n @if (isEditMode) {\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.systemInfo\" (ExpandedChange)=\"toggleSection('systemInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n System Information\n </span>\n <span class=\"section-description\">Application metadata and audit information</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{ data?.application?.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Updated</span>\n <span class=\"info-value\">{{ data?.application?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Application ID</span>\n <span class=\"info-value\">{{ data?.application?.ID }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Total Entities</span>\n <span class=\"info-value\">{{ applicationEntities.length }}</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </form>\n </div>\n\n <!-- Modal Footer - Primary and Cancel buttons on RIGHT -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n mjButton variant=\"primary\"\n [disabled]=\"applicationForm.invalid || isLoading\"\n (click)=\"onSubmit()\"\n [attr.aria-busy]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Update Application' : 'Create Application' }}\n }\n </button>\n <button type=\"button\" mjButton (click)=\"onCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: ["/* =============================================================================\n Application Dialog Component\n Uses MJ Design Tokens (--mj-*)\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Modal Backdrop & Container\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0, 0, 0.2, 1);\n padding: 1rem;\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 900px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Fullscreen mode */\n.modal-dialog.fullscreen {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Header\n ----------------------------------------------------------------------------- */\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 1.5rem 1.5rem 1rem 1.5rem;\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n flex-shrink: 0;\n}\n\n.modal-header-content {\n flex: 1;\n min-width: 0;\n}\n\n.modal-header .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-brand-on-primary);\n margin: 0;\n}\n\n.modal-header .modal-title i {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.2);\n border-radius: var(--mj-radius-lg);\n font-size: 1.125rem;\n flex-shrink: 0;\n}\n\n/* Create mode - Plus icon with inverted styling */\n.modal-header.create-mode .modal-title i {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n/* Edit mode - Grid icon with semi-transparent background */\n.modal-header.edit-mode .modal-title i {\n background: rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Header Actions */\n.modal-header-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n.modal-header .modal-subtitle {\n margin: 0.375rem 0 0 0;\n font-size: 0.8125rem;\n color: var(--mj-brand-on-primary);\n opacity: 0.85;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-header .modal-close:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-header .modal-close:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Body\n ----------------------------------------------------------------------------- */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n padding: 0;\n background: var(--mj-bg-page);\n}\n\n/* -----------------------------------------------------------------------------\n Modal Footer - Primary and Cancel buttons on RIGHT\n ----------------------------------------------------------------------------- */\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Form Sections (Fieldset)\n ----------------------------------------------------------------------------- */\n.form-section {\n border: none;\n margin: 0;\n padding: 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.form-section:last-of-type {\n border-bottom: none;\n}\n\n/* -----------------------------------------------------------------------------\n Collapsible Sections \u2014 now <mj-accordion-panel>. The bespoke fieldset/legend\n chrome (.section-header / .section-title-row / .chevron-icon) was removed; the\n title (icon + title + description) is projected into the accordion title slot.\n ----------------------------------------------------------------------------- */\n.app-dialog-section-title {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n min-width: 0;\n}\n\n.app-dialog-section-title .section-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.app-dialog-section-title .section-title i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.app-dialog-section-title .section-description {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n font-weight: normal;\n}\n\n.section-content {\n animation: expandSection 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes expandSection {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Form Grid Layout\n ----------------------------------------------------------------------------- */\n.form-grid {\n display: grid;\n gap: 1.25rem;\n}\n\n.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Form Fields\n ----------------------------------------------------------------------------- */\n.form-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.form-field .field-label {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.form-field .field-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-field .field-input,\n.form-field .field-select,\n.form-field .field-textarea {\n width: 100%;\n min-height: 44px;\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n font-size: 0.9375rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n}\n\n.form-field .field-input:focus,\n.form-field .field-select:focus,\n.form-field .field-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-field .field-input.error,\n.form-field .field-select.error,\n.form-field .field-textarea.error {\n border-color: var(--mj-status-error);\n}\n\n.form-field .field-input.error:focus,\n.form-field .field-select.error:focus,\n.form-field .field-textarea.error:focus {\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.form-field .field-input::placeholder,\n.form-field .field-textarea::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.form-field .field-textarea {\n min-height: 100px;\n resize: vertical;\n line-height: 1.5;\n}\n\n.form-field .field-error {\n margin-top: 0.25rem;\n font-size: 0.8125rem;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.form-field .field-error i {\n font-size: 0.625rem;\n}\n\n.form-field .field-hint {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Entity Management Styles\n ----------------------------------------------------------------------------- */\n.subsection-title {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 1rem 0;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.assigned-entities {\n margin-bottom: 1.5rem;\n}\n\n.assigned-entities .entities-list {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.entity-item {\n display: flex;\n align-items: center;\n padding: 1rem 1.25rem;\n border-bottom: 1px solid var(--mj-bg-surface);\n transition: all 0.15s ease;\n}\n\n.entity-item:last-child {\n border-bottom: none;\n}\n\n.entity-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.is-new {\n background: color-mix(in srgb, var(--mj-status-success) 8%, transparent);\n border-left: 3px solid var(--mj-status-success);\n}\n\n.entity-item.has-changes {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, transparent);\n border-left: 3px solid var(--mj-status-warning);\n}\n\n.entity-item .entity-info {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-icon {\n width: 40px;\n height: 40px;\n background: var(--mj-brand-accent-subtle);\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.entity-item .entity-info .entity-details {\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-details .entity-name {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 0.125rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon {\n color: var(--mj-status-warning);\n font-size: 0.875rem;\n cursor: help;\n opacity: 0.7;\n transition: all 0.15s ease;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon:hover {\n opacity: 1;\n transform: scale(1.1);\n}\n\n.entity-item .entity-config {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n margin: 0 1.5rem;\n}\n\n.entity-item .entity-config .config-item .config-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.entity-item .entity-config .config-item .config-label .config-checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.entity-item .entity-config .sequence-badge {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n padding: 0.25rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.75rem;\n font-weight: 600;\n min-width: 24px;\n text-align: center;\n}\n\n.entity-item .entity-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Drag and Drop Styles\n ----------------------------------------------------------------------------- */\n.drag-handle {\n color: var(--mj-text-secondary);\n cursor: grab;\n margin-right: 0.75rem;\n font-size: 1rem;\n transition: color 0.2s ease;\n flex-shrink: 0;\n}\n\n.drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.entity-item.cdk-drag-preview {\n box-shadow: var(--mj-shadow-xl);\n transform: rotate(1deg);\n opacity: 0.9;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-page);\n}\n\n.entity-item.cdk-drag-placeholder {\n opacity: 0.4;\n border-style: dashed;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.entities-list.cdk-drop-list-dragging .entity-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty States\n ----------------------------------------------------------------------------- */\n.no-entities,\n.all-assigned {\n text-align: center;\n padding: 2rem;\n color: var(--mj-text-secondary);\n}\n\n.no-entities i,\n.all-assigned i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 1rem;\n display: block;\n}\n\n.no-entities p,\n.all-assigned p {\n margin: 0 0 0.25rem 0;\n font-size: 0.9375rem;\n}\n\n.no-entities .empty-subtext,\n.all-assigned .empty-subtext {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Section\n ----------------------------------------------------------------------------- */\n.available-entities-header {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n margin-bottom: 1rem;\n}\n\n@media (min-width: 640px) {\n .available-entities-header {\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n }\n}\n\n.available-entities-header .subsection-title {\n margin: 0;\n}\n\n/* Entity Search Bar - Enhanced prominent search */\n.entity-search {\n position: relative;\n min-width: 200px;\n max-width: 100%;\n width: 100%;\n}\n\n@media (min-width: 640px) {\n .entity-search {\n min-width: 280px;\n max-width: 400px;\n width: auto;\n }\n}\n\n@media (min-width: 768px) {\n .entity-search {\n min-width: 320px;\n max-width: 450px;\n }\n}\n\n.entity-search .entity-search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-icon {\n left: 1.125rem;\n font-size: 1.125rem;\n }\n}\n\n.entity-search .entity-search-input {\n width: 100%;\n padding: 0.875rem 2.75rem 0.875rem 2.75rem;\n border: 2px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;\n min-height: 48px;\n box-shadow: var(--mj-shadow-sm);\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-input {\n padding: 1rem 3rem 1rem 3rem;\n min-height: 52px;\n font-size: 1.0625rem;\n border-radius: var(--mj-radius-full);\n }\n}\n\n.entity-search .entity-search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.entity-search .entity-search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-search .entity-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md), 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-page);\n}\n\n.entity-search:focus-within .entity-search-icon {\n color: var(--mj-brand-primary);\n}\n\n.entity-search .entity-search-clear {\n position: absolute;\n right: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n min-height: 28px;\n transition: all 0.15s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-clear {\n right: 0.875rem;\n min-width: 32px;\n min-height: 32px;\n }\n}\n\n.entity-search .entity-search-clear:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n/* No Search Results State */\n.no-search-results {\n text-align: center;\n padding: 1.5rem;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n}\n\n.no-search-results i {\n font-size: 1.5rem;\n color: var(--mj-border-default);\n margin-bottom: 0.5rem;\n display: block;\n}\n\n.no-search-results p {\n margin: 0;\n font-size: 0.8125rem;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Grid\n ----------------------------------------------------------------------------- */\n.available-entities .entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 0.5rem;\n}\n\n.entity-chip {\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-chip .chip-content {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-chip .chip-content i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.entity-chip .chip-content .chip-name {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.entity-chip:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* -----------------------------------------------------------------------------\n Info Grid for System Information\n ----------------------------------------------------------------------------- */\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 1rem;\n}\n\n.info-grid .info-item {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.info-grid .info-item .info-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-grid .info-item .info-value {\n font-size: 0.9375rem;\n color: var(--mj-text-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Button Icon Styles\n ----------------------------------------------------------------------------- */\n.btn-icon {\n width: 36px;\n height: 36px;\n border: none;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n}\n\n.btn-icon:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-neutral {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n}\n\n.btn-icon.btn-neutral:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover:not(:disabled) {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Add/Create Icon Button */\n.btn-icon.btn-add {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-icon.btn-add:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-icon.btn-add:active:not(:disabled) {\n background: var(--mj-brand-primary-light);\n transform: scale(0.95);\n}\n\n/* -----------------------------------------------------------------------------\n Icon Wrapper - Prominent display icons\n ----------------------------------------------------------------------------- */\n.icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.icon-wrapper-sm {\n width: 32px;\n height: 32px;\n border-radius: var(--mj-radius-md);\n font-size: 0.875rem;\n}\n\n.icon-wrapper-md {\n width: 40px;\n height: 40px;\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n}\n\n.icon-wrapper-lg {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.25rem;\n}\n\n.icon-wrapper-xl {\n width: 56px;\n height: 56px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.5rem;\n}\n\n/* Icon wrapper color variants */\n.icon-wrapper-primary {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.icon-wrapper-secondary {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.icon-wrapper-tertiary {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.icon-wrapper-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Inverted icon wrapper (for dark backgrounds) */\n.icon-wrapper-inverted {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Buttons use the global `mjButton` directive (variant/size inputs) \u2014 no\n component-scoped `.mj-btn` overrides (they would collide with the directive). */\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Focus Indicators - Accessibility\n ----------------------------------------------------------------------------- */\n.field-input:focus-visible,\n.field-select:focus-visible,\n.field-textarea:focus-visible,\n.btn-icon:focus-visible,\n.entity-chip:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Reduced Motion Support\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile (< 640px)\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .modal-backdrop {\n padding: 0.5rem;\n }\n\n .modal-dialog {\n border-radius: var(--mj-radius-2xl);\n max-height: 95vh;\n }\n\n /* Fullscreen mode on mobile */\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n\n .modal-header {\n padding: 1.25rem 1rem 1rem 1rem;\n }\n\n .modal-header .modal-title {\n font-size: 1.125rem;\n }\n\n .modal-header .modal-close {\n border-radius: var(--mj-radius-full);\n }\n\n /* Modal title icon on mobile */\n .modal-header .modal-title i {\n width: 36px;\n height: 36px;\n font-size: 1rem;\n }\n\n /* Icon wrappers on mobile - slightly smaller */\n .icon-wrapper-lg {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .icon-wrapper-xl {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n\n /* Add button on mobile */\n .btn-icon.btn-add {\n border-radius: var(--mj-radius-full);\n }\n\n .form-section {\n padding: 1.25rem 1rem;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .modal-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n /* Full-width footer buttons on mobile \u2014 wrapper-scoped layout only, so the\n global mjButton directive still owns each button's appearance/shape. */\n .modal-footer button {\n width: 100%;\n justify-content: center;\n }\n\n /* Entity item mobile layout */\n .entity-item {\n flex-direction: column;\n align-items: stretch;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n position: relative;\n }\n\n /* Drag handle on mobile - Keep visible and touch-friendly */\n .drag-handle {\n position: static;\n margin-right: 0.75rem;\n margin-bottom: 0.5rem;\n font-size: 1.25rem;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: 0.5rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n cursor: grab;\n }\n\n .drag-handle:active {\n cursor: grabbing;\n background: var(--mj-brand-accent-subtle);\n }\n\n .entity-item .entity-info {\n gap: 0.75rem;\n }\n\n .entity-item .entity-info .entity-icon {\n width: 36px;\n height: 36px;\n font-size: 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-item .entity-info .entity-details .entity-name {\n font-size: 0.875rem;\n word-break: break-word;\n overflow-wrap: break-word;\n line-height: 1.3;\n flex-wrap: wrap;\n }\n\n .entity-item .entity-config {\n margin: 0;\n width: 100%;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .entity-item .entity-config .config-item .config-label {\n font-size: 0.8125rem;\n }\n\n .entity-item .entity-actions {\n width: 100%;\n justify-content: flex-end;\n gap: 0.5rem;\n }\n\n /* Entity chips in mobile */\n .available-entities .entities-grid {\n grid-template-columns: 1fr;\n }\n\n .entity-chip {\n padding: 0.625rem 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-chip .chip-content .chip-name {\n font-size: 0.75rem;\n word-break: break-word;\n }\n\n /* Entity search on mobile - still prominent */\n .entity-search {\n max-width: none;\n width: 100%;\n }\n\n .entity-search .entity-search-input {\n padding: 0.75rem 2.5rem 0.75rem 2.5rem;\n min-height: 44px;\n font-size: 0.9375rem;\n border-radius: var(--mj-radius-full);\n }\n\n .entity-search .entity-search-icon {\n left: 0.875rem;\n font-size: 0.875rem;\n }\n\n .entity-search .entity-search-clear {\n right: 0.625rem;\n border-radius: var(--mj-radius-full);\n }\n\n .info-grid {\n grid-template-columns: 1fr 1fr;\n }\n\n /* Icon buttons on mobile - keep rounded */\n .btn-icon {\n border-radius: var(--mj-radius-full);\n }\n}\n\n/* Tablet Portrait (640px - 767px) */\n@media (min-width: 640px) {\n .modal-dialog {\n max-width: 650px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n}\n\n/* Tablet Landscape (768px - 1023px) */\n@media (min-width: 768px) {\n .modal-dialog {\n max-width: 800px;\n }\n\n .modal-header {\n padding: 1.5rem 2rem 1.25rem 2rem;\n }\n\n .form-section {\n padding: 1.75rem 2rem;\n }\n\n .modal-footer {\n padding: 1.25rem 2rem;\n }\n}\n\n/* Laptop (1024px+) */\n@media (min-width: 1024px) {\n .modal-dialog {\n max-width: 900px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n }\n}\n"] }]
712
- }], () => [], { data: [{
852
+ }], () => [], { Data: [{
853
+ type: Input
854
+ }], data: [{
855
+ type: Input
856
+ }], Visible: [{
713
857
  type: Input
714
858
  }], visible: [{
715
859
  type: Input
860
+ }], Result: [{
861
+ type: Output
716
862
  }], result: [{
717
863
  type: Output
718
864
  }], onEscapeKey: [{