commons-shared-web-ui 0.0.24 → 0.0.26

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.
@@ -44,7 +44,7 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
44
44
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
45
45
  import * as i3 from '@angular/common/http';
46
46
  import { HttpHeaders, HttpParams } from '@angular/common/http';
47
- import { BehaviorSubject, Subject, combineLatest, forkJoin, takeUntil as takeUntil$1, of } from 'rxjs';
47
+ import { Subject, BehaviorSubject, combineLatest, forkJoin, takeUntil as takeUntil$1, of } from 'rxjs';
48
48
  import * as i1$4 from '@angular/router';
49
49
  import { RouterModule } from '@angular/router';
50
50
  import { takeUntil, debounceTime, distinctUntilChanged, map, finalize, catchError } from 'rxjs/operators';
@@ -244,6 +244,9 @@ class SmartFormController {
244
244
  /** Custom label keys for form actions (Next, Submit, Add, etc.) */
245
245
  actionLabels;
246
246
  fieldSubjects = new Map();
247
+ fileAdded$ = new Subject();
248
+ fileUploadFinished$ = new Subject();
249
+ fileRemoved$ = new Subject();
247
250
  initialize(initialData) {
248
251
  this.formData = { ...initialData };
249
252
  this.fieldSubjects.forEach((subject, key) => {
@@ -1394,13 +1397,16 @@ class FormFieldComponent {
1394
1397
  }
1395
1398
  const placeholder = { mediaType: 'image', url: '', isUploading: true };
1396
1399
  this._appendMediaItem(placeholder);
1400
+ this.controller.fileAdded$.next(file);
1397
1401
  const formData = new FormData();
1398
1402
  formData.append('file', file);
1399
- if (mediaCfg.entityType)
1400
- formData.append('entity_type', mediaCfg.entityType);
1401
1403
  if (!mediaCfg.uploadUrl)
1402
1404
  return;
1403
- this.http.post(mediaCfg.uploadUrl, formData, { headers: this.getHeaders() })
1405
+ let finalUrl = mediaCfg.uploadUrl;
1406
+ if (finalUrl.includes('{fileName}')) {
1407
+ finalUrl = finalUrl.replace('{fileName}', encodeURIComponent(file.name));
1408
+ }
1409
+ this.http.post(finalUrl, formData, { headers: this.getHeaders() })
1404
1410
  .pipe(takeUntil(this.destroy$))
1405
1411
  .subscribe({
1406
1412
  next: (response) => {
@@ -1419,11 +1425,13 @@ class FormFieldComponent {
1419
1425
  };
1420
1426
  this.updateValue(current);
1421
1427
  this.mediaCarouselIndex = current.length - 1;
1428
+ this.controller.fileUploadFinished$.next(file);
1422
1429
  }
1423
1430
  },
1424
1431
  error: () => {
1425
1432
  const cleaned = this.mediaItems.filter(m => m !== placeholder);
1426
1433
  this.updateValue(cleaned.length ? cleaned : null);
1434
+ this.controller.fileUploadFinished$.next(file);
1427
1435
  }
1428
1436
  });
1429
1437
  });
@@ -1462,12 +1470,14 @@ class FormFieldComponent {
1462
1470
  ? [...(this.value || []), entry]
1463
1471
  : [entry];
1464
1472
  this.updateValue(withPlaceholder);
1473
+ this.controller.fileAdded$.next(file);
1465
1474
  const formData = new FormData();
1466
1475
  formData.append('file', file);
1467
- if (cfg.entityType) {
1468
- formData.append('entity_type', cfg.entityType);
1476
+ let finalUrl = cfg.uploadUrl;
1477
+ if (finalUrl.includes('{fileName}')) {
1478
+ finalUrl = finalUrl.replace('{fileName}', encodeURIComponent(file.name));
1469
1479
  }
1470
- this.http.post(cfg.uploadUrl, formData, { headers: this.getHeaders() })
1480
+ this.http.post(finalUrl, formData, { headers: this.getHeaders() })
1471
1481
  .pipe(takeUntil(this.destroy$))
1472
1482
  .subscribe({
1473
1483
  next: (response) => {
@@ -1481,6 +1491,7 @@ class FormFieldComponent {
1481
1491
  const updatedList = [...current];
1482
1492
  updatedList[idx] = updatedEntry;
1483
1493
  this.updateValue(updatedList);
1494
+ this.controller.fileUploadFinished$.next(file);
1484
1495
  }
1485
1496
  },
1486
1497
  error: () => {
@@ -1489,6 +1500,7 @@ class FormFieldComponent {
1489
1500
  const cleaned = current.filter(f => f !== entry);
1490
1501
  this.updateValue(cleaned.length ? cleaned : null);
1491
1502
  this.fileUploadError = `Failed to upload "${file.name}". Please try again.`;
1503
+ this.controller.fileUploadFinished$.next(file);
1492
1504
  }
1493
1505
  });
1494
1506
  }
@@ -1531,13 +1543,14 @@ class FormFieldComponent {
1531
1543
  }
1532
1544
  if (!deleteUrl.includes('reason=')) {
1533
1545
  // As requested in the API link, the reason is passed
1534
- params = params.set('reason', 'DELECTED BY CREATOR');
1546
+ params = params.set('reason', 'DELETED BY CREATOR');
1535
1547
  }
1536
1548
  this.http.delete(deleteUrl, { headers: this.getHeaders(), params })
1537
1549
  .pipe(takeUntil(this.destroy$))
1538
1550
  .subscribe({
1539
1551
  next: () => {
1540
1552
  removeLocally();
1553
+ this.controller.fileRemoved$.next(fileToRemove);
1541
1554
  },
1542
1555
  error: (err) => {
1543
1556
  console.error('Failed to delete attachment', err);
@@ -1549,6 +1562,7 @@ class FormFieldComponent {
1549
1562
  }
1550
1563
  else {
1551
1564
  removeLocally();
1565
+ this.controller.fileRemoved$.next(fileToRemove);
1552
1566
  }
1553
1567
  }
1554
1568
  getFileIcon(mimeType) {
@@ -1883,7 +1897,10 @@ class FormFieldComponent {
1883
1897
  this.http.delete(deleteUrl, { headers: this.getHeaders(), params })
1884
1898
  .pipe(takeUntil(this.destroy$))
1885
1899
  .subscribe({
1886
- next: () => removeLocally(),
1900
+ next: () => {
1901
+ removeLocally();
1902
+ this.controller.fileRemoved$.next(item);
1903
+ },
1887
1904
  error: (err) => {
1888
1905
  console.error('Failed to delete media attachment', err);
1889
1906
  item.isUploading = false;
@@ -1894,6 +1911,7 @@ class FormFieldComponent {
1894
1911
  else {
1895
1912
  // ── No id or no deleteUrl: remove locally, no API call ───────────────
1896
1913
  removeLocally();
1914
+ this.controller.fileRemoved$.next(item);
1897
1915
  }
1898
1916
  }
1899
1917
  _appendMediaItem(item) {
@@ -2298,6 +2316,8 @@ class SmartFormComponent {
2298
2316
  */
2299
2317
  labels = {};
2300
2318
  mode = 'CREATE';
2319
+ /** When true, all form fields are disabled and the action bar is hidden (preview/read-only mode). */
2320
+ readOnly = false;
2301
2321
  submit = new EventEmitter();
2302
2322
  draftSave = new EventEmitter();
2303
2323
  /**
@@ -2307,6 +2327,9 @@ class SmartFormComponent {
2307
2327
  */
2308
2328
  actionClick = new EventEmitter();
2309
2329
  valueChange = new EventEmitter();
2330
+ fileAdded = new EventEmitter();
2331
+ fileUploadFinished = new EventEmitter();
2332
+ fileRemoved = new EventEmitter();
2310
2333
  formSchema;
2311
2334
  formGroup;
2312
2335
  fieldList = [];
@@ -2331,6 +2354,9 @@ class SmartFormComponent {
2331
2354
  else if (this.initialValues) {
2332
2355
  this.controller.initialize(this.initialValues);
2333
2356
  }
2357
+ this.controller.fileAdded$.pipe(takeUntil$1(this.destroy$)).subscribe(file => this.fileAdded.emit(file));
2358
+ this.controller.fileUploadFinished$.pipe(takeUntil$1(this.destroy$)).subscribe(file => this.fileUploadFinished.emit(file));
2359
+ this.controller.fileRemoved$.pipe(takeUntil$1(this.destroy$)).subscribe(file => this.fileRemoved.emit(file));
2334
2360
  }
2335
2361
  loadEditData() {
2336
2362
  const config = this.formSchema.editConfig;
@@ -2395,10 +2421,16 @@ class SmartFormComponent {
2395
2421
  initializeForm() {
2396
2422
  this.formGroup = this.fb.group({});
2397
2423
  this.collectFields(this.fieldList);
2398
- // Emit value changes to parent
2399
- this.formGroup.valueChanges.pipe(takeUntil$1(this.destroy$)).subscribe(() => {
2400
- this.valueChange.emit(this.collectFormData());
2401
- });
2424
+ // In read-only mode, disable all controls so the form acts as a preview
2425
+ if (this.readOnly) {
2426
+ this.formGroup.disable();
2427
+ }
2428
+ // Emit value changes to parent (skipped in read-only mode)
2429
+ if (!this.readOnly) {
2430
+ this.formGroup.valueChanges.pipe(takeUntil$1(this.destroy$)).subscribe(() => {
2431
+ this.valueChange.emit(this.collectFormData());
2432
+ });
2433
+ }
2402
2434
  }
2403
2435
  collectFields(fields) {
2404
2436
  fields.forEach(field => {
@@ -2836,11 +2868,11 @@ class SmartFormComponent {
2836
2868
  }
2837
2869
  }
2838
2870
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, deps: [{ token: i1$3.FormBuilder }, { token: SmartFormController }, { token: ExpressionService }, { token: i3.HttpClient }, { token: SnackbarService }, { token: i1$4.Router }], target: i0.ɵɵFactoryTarget.Component });
2839
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
2871
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode", readOnly: "readOnly" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange", fileAdded: "fileAdded", fileUploadFinished: "fileUploadFinished", fileRemoved: "fileRemoved" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\" [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
2840
2872
  }
2841
2873
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, decorators: [{
2842
2874
  type: Component,
2843
- args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
2875
+ args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\" [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <!-- Optional: Navigational buttons like 'Previous' for stepper can be explicitly added to config, \r\n but we'll keep the logic if they are provided in the buttons array via action.kind === 'prev' -->\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>", styles: [".smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
2844
2876
  }], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: SmartFormController }, { type: ExpressionService }, { type: i3.HttpClient }, { type: SnackbarService }, { type: i1$4.Router }], propDecorators: { formJson: [{
2845
2877
  type: Input
2846
2878
  }], initialValues: [{
@@ -2851,6 +2883,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
2851
2883
  type: Input
2852
2884
  }], mode: [{
2853
2885
  type: Input
2886
+ }], readOnly: [{
2887
+ type: Input
2854
2888
  }], submit: [{
2855
2889
  type: Output
2856
2890
  }], draftSave: [{
@@ -2859,6 +2893,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
2859
2893
  type: Output
2860
2894
  }], valueChange: [{
2861
2895
  type: Output
2896
+ }], fileAdded: [{
2897
+ type: Output
2898
+ }], fileUploadFinished: [{
2899
+ type: Output
2900
+ }], fileRemoved: [{
2901
+ type: Output
2862
2902
  }] } });
2863
2903
 
2864
2904
  class ButtonModule {
@@ -4156,8 +4196,8 @@ class RadioComponent {
4156
4196
  setDisabledState(isDisabled) {
4157
4197
  this.disabled = isDisabled;
4158
4198
  }
4159
- onRadioChange(event) {
4160
- this.value = event.target.value;
4199
+ onRadioChange(option) {
4200
+ this.value = option.value;
4161
4201
  this.onChange(this.value);
4162
4202
  this.onTouched();
4163
4203
  this.selectionChange.emit(this.value);
@@ -4165,6 +4205,19 @@ class RadioComponent {
4165
4205
  getStyleValue(value) {
4166
4206
  return value ? `${value}` : undefined;
4167
4207
  }
4208
+ getThemeColor(colorStr) {
4209
+ if (!colorStr)
4210
+ return undefined;
4211
+ const themeColors = {
4212
+ 'primary': 'var(--cc-radio-primary-bg, var(--cc-btn-primary-bg, #1A73E8))',
4213
+ 'warning': 'var(--cc-radio-warning-bg, var(--cc-btn-warning-bg, #F9C80E))',
4214
+ 'danger': 'var(--cc-radio-danger-bg, var(--cc-btn-danger-bg, #dc3545))',
4215
+ 'success': 'var(--cc-radio-success-bg, var(--cc-btn-success-bg, #28a745))',
4216
+ 'warn': 'var(--cc-radio-danger-bg, var(--cc-btn-danger-bg, #dc3545))',
4217
+ 'accent': 'var(--cc-radio-accent-bg, #ff4081)'
4218
+ };
4219
+ return themeColors[colorStr] || colorStr;
4220
+ }
4168
4221
  get wrapperStyles() {
4169
4222
  return {
4170
4223
  '--cc-radio-font-family': this.getStyleValue(this.fontFamily),
@@ -4173,7 +4226,7 @@ class RadioComponent {
4173
4226
  '--cc-radio-label-color': this.getStyleValue(this.labelColor),
4174
4227
  '--cc-radio-size': this.getStyleValue(this.size),
4175
4228
  '--cc-radio-border-radius': this.getStyleValue(this.borderRadius),
4176
- '--cc-radio-checked-color': this.getStyleValue(this.checkedColor),
4229
+ '--cc-radio-checked-color': this.getStyleValue(this.getThemeColor(this.checkedColor || this.color)),
4177
4230
  '--cc-radio-unchecked-color': this.getStyleValue(this.uncheckedColor),
4178
4231
  '--cc-radio-disabled-color': this.getStyleValue(this.disabledColor),
4179
4232
  '--cc-radio-error-color': this.getStyleValue(this.errorColor),
@@ -4190,7 +4243,7 @@ class RadioComponent {
4190
4243
  useExisting: forwardRef(() => RadioComponent),
4191
4244
  multi: true
4192
4245
  }
4193
- ], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange($event)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4246
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange(option)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4194
4247
  }
4195
4248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: RadioComponent, decorators: [{
4196
4249
  type: Component,
@@ -4200,7 +4253,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
4200
4253
  useExisting: forwardRef(() => RadioComponent),
4201
4254
  multi: true
4202
4255
  }
4203
- ], template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange($event)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\n"] }]
4256
+ ], template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange(option)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\n"] }]
4204
4257
  }], propDecorators: { config: [{
4205
4258
  type: Input
4206
4259
  }], label: [{
@@ -4356,6 +4409,17 @@ class ToggleComponent {
4356
4409
  getStyleValue(value) {
4357
4410
  return value ? `${value}` : undefined;
4358
4411
  }
4412
+ getThemeColor(colorStr) {
4413
+ if (!colorStr)
4414
+ return undefined;
4415
+ const themeColors = {
4416
+ 'primary': 'var(--cc-toggle-primary-bg, var(--cc-btn-primary-bg, #1A73E8))',
4417
+ 'warning': 'var(--cc-toggle-warning-bg, var(--cc-btn-warning-bg, #F9C80E))',
4418
+ 'danger': 'var(--cc-toggle-danger-bg, var(--cc-btn-danger-bg, #dc3545))',
4419
+ 'success': 'var(--cc-toggle-success-bg, var(--cc-btn-success-bg, #28a745))'
4420
+ };
4421
+ return themeColors[colorStr] || colorStr;
4422
+ }
4359
4423
  get wrapperStyles() {
4360
4424
  return {
4361
4425
  '--cc-toggle-font-family': this.getStyleValue(this.fontFamily),
@@ -4366,7 +4430,7 @@ class ToggleComponent {
4366
4430
  '--cc-toggle-height': this.getStyleValue(this.toggleHeight),
4367
4431
  '--cc-toggle-gap': this.getStyleValue(this.gap),
4368
4432
  '--cc-toggle-unchecked-bg': this.getStyleValue(this.uncheckedColor),
4369
- '--cc-toggle-checked-bg': this.getStyleValue(this.checkedColor || this.color),
4433
+ '--cc-toggle-checked-bg': this.getStyleValue(this.getThemeColor(this.checkedColor || this.color)),
4370
4434
  '--cc-toggle-thumb-color': this.getStyleValue(this.thumbColor || this.sliderColor),
4371
4435
  '--cc-toggle-checked-thumb-color': this.getStyleValue(this.checkedThumbColor),
4372
4436
  '--cc-toggle-disabled-color': this.getStyleValue(this.disabledColor)
@@ -5841,26 +5905,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
5841
5905
  type: Injectable
5842
5906
  }] });
5843
5907
 
5908
+ /** Available field types that users can switch to in the configurator. */
5909
+ const SWITCHABLE_FIELD_TYPES = [
5910
+ { label: 'Short Text', value: 'shortText' },
5911
+ { label: 'Long Text', value: 'longText' },
5912
+ { label: 'Email', value: 'email' },
5913
+ { label: 'Phone', value: 'phone' },
5914
+ { label: 'Password', value: 'password' },
5915
+ { label: 'Number (Integer)', value: 'number' },
5916
+ { label: 'Number (Decimal)', value: 'decimal' },
5917
+ { label: 'Date', value: 'date' },
5918
+ { label: 'Time', value: 'time' },
5919
+ { label: 'Date & Time', value: 'dateTime' },
5920
+ { label: 'Dropdown', value: 'dropdown' },
5921
+ { label: 'Multi-Select', value: 'multiSelect' },
5922
+ { label: 'Autocomplete', value: 'autocomplete' },
5923
+ { label: 'Checkbox', value: 'checkbox' },
5924
+ { label: 'Multi-Checkbox', value: 'multiCheckbox' },
5925
+ { label: 'Radio', value: 'radio' },
5926
+ { label: 'Toggle', value: 'toggle' },
5927
+ { label: 'Chips', value: 'chip' },
5928
+ { label: 'Rich Text', value: 'richText' },
5929
+ { label: 'File Upload', value: 'file' },
5930
+ { label: 'Rating', value: 'rating' },
5931
+ { label: 'Location', value: 'location' },
5932
+ { label: 'Formula (Auto)', value: 'generated' },
5933
+ ];
5934
+ /**
5935
+ * Field types that are driven by option configurations (optionConfig).
5936
+ * When `hideToggleForOptionTypes` is true on the field-selection configurator,
5937
+ * these field types will not show the enable/disable toggle — they are
5938
+ * UI element types whose options are pre-filled by the developer.
5939
+ */
5940
+ const OPTION_DRIVEN_FIELD_TYPES = new Set([
5941
+ 'DROPDOWN',
5942
+ 'MULTI_SELECT',
5943
+ 'RADIO',
5944
+ 'AUTOCOMPLETE',
5945
+ 'CHECKBOX',
5946
+ 'MULTI_CHECKBOX',
5947
+ 'CHIP',
5948
+ ]);
5949
+
5844
5950
  class SelectionFieldNodeComponent {
5845
5951
  field;
5846
5952
  toggleSelected = new EventEmitter();
5953
+ /**
5954
+ * When true, the enable/disable toggle is hidden for option-driven field types
5955
+ * (DROPDOWN, RADIO, MULTI_SELECT, etc.). These types have their options
5956
+ * pre-configured by the developer and shouldn't be toggled by business users.
5957
+ */
5958
+ hideToggleForOptionTypes = false;
5959
+ get isOptionDrivenType() {
5960
+ return OPTION_DRIVEN_FIELD_TYPES.has((this.field?.fieldConfig?.type ?? '').toUpperCase());
5961
+ }
5847
5962
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionFieldNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5848
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionFieldNodeComponent, isStandalone: false, selector: "lib-selection-field-node", inputs: { field: "field" }, outputs: { toggleSelected: "toggleSelected" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5963
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionFieldNodeComponent, isStandalone: false, selector: "lib-selection-field-node", inputs: { field: "field", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleSelected: "toggleSelected" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5849
5964
  }
5850
5965
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionFieldNodeComponent, decorators: [{
5851
5966
  type: Component,
5852
- args: [{ selector: 'lib-selection-field-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}\n"] }]
5967
+ args: [{ selector: 'lib-selection-field-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"] }]
5853
5968
  }], propDecorators: { field: [{
5854
5969
  type: Input,
5855
5970
  args: [{ required: true }]
5856
5971
  }], toggleSelected: [{
5857
5972
  type: Output
5973
+ }], hideToggleForOptionTypes: [{
5974
+ type: Input
5858
5975
  }] } });
5859
5976
 
5860
5977
  class SelectionSectionNodeComponent {
5861
5978
  section;
5862
5979
  sectionIndex;
5863
5980
  depth = 0;
5981
+ /** Propagated from FieldSelectionComponent — see SelectionFieldNodeComponent for details. */
5982
+ hideToggleForOptionTypes = false;
5864
5983
  /** Emits the sub-path from this node downward (empty [] for self) */
5865
5984
  toggleEnabled = new EventEmitter();
5866
5985
  toggleExpanded = new EventEmitter();
@@ -5899,11 +6018,11 @@ class SelectionSectionNodeComponent {
5899
6018
  return index;
5900
6019
  }
5901
6020
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5902
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6021
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field", "hideToggleForOptionTypes"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5903
6022
  }
5904
6023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, decorators: [{
5905
6024
  type: Component,
5906
- args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}\n"] }]
6025
+ args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}\n"] }]
5907
6026
  }], propDecorators: { section: [{
5908
6027
  type: Input,
5909
6028
  args: [{ required: true }]
@@ -5912,6 +6031,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
5912
6031
  args: [{ required: true }]
5913
6032
  }], depth: [{
5914
6033
  type: Input
6034
+ }], hideToggleForOptionTypes: [{
6035
+ type: Input
5915
6036
  }], toggleEnabled: [{
5916
6037
  type: Output
5917
6038
  }], toggleExpanded: [{
@@ -5923,6 +6044,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
5923
6044
  class GroupNodeComponent {
5924
6045
  group;
5925
6046
  groupIndex;
6047
+ /** Propagated from FieldSelectionComponent — see SelectionFieldNodeComponent for details. */
6048
+ hideToggleForOptionTypes = false;
5926
6049
  toggleEnabled = new EventEmitter();
5927
6050
  toggleExpanded = new EventEmitter();
5928
6051
  sectionToggleEnabled = new EventEmitter();
@@ -5944,17 +6067,19 @@ class GroupNodeComponent {
5944
6067
  return index;
5945
6068
  }
5946
6069
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5947
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GroupNodeComponent, isStandalone: false, selector: "lib-group-node", inputs: { group: "group", groupIndex: "groupIndex" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", sectionToggleEnabled: "sectionToggleEnabled", sectionToggleExpanded: "sectionToggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6070
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GroupNodeComponent, isStandalone: false, selector: "lib-group-node", inputs: { group: "group", groupIndex: "groupIndex", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", sectionToggleEnabled: "sectionToggleEnabled", sectionToggleExpanded: "sectionToggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5948
6071
  }
5949
6072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupNodeComponent, decorators: [{
5950
6073
  type: Component,
5951
- args: [{ selector: 'lib-group-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}\n"] }]
6074
+ args: [{ selector: 'lib-group-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}\n"] }]
5952
6075
  }], propDecorators: { group: [{
5953
6076
  type: Input,
5954
6077
  args: [{ required: true }]
5955
6078
  }], groupIndex: [{
5956
6079
  type: Input,
5957
6080
  args: [{ required: true }]
6081
+ }], hideToggleForOptionTypes: [{
6082
+ type: Input
5958
6083
  }], toggleEnabled: [{
5959
6084
  type: Output
5960
6085
  }], toggleExpanded: [{
@@ -5970,6 +6095,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
5970
6095
  class FieldSelectionComponent {
5971
6096
  schema;
5972
6097
  schemaChange = new EventEmitter();
6098
+ /**
6099
+ * When true, the enable/disable toggle is hidden for option-driven field types
6100
+ * (DROPDOWN, RADIO, MULTI_SELECT, etc.).
6101
+ * Useful for business-user-facing form configurators where developers
6102
+ * pre-fill the option data and these fields should always be included.
6103
+ * Defaults to false (show toggle for all fields).
6104
+ */
6105
+ hideToggleForOptionTypes = false;
5973
6106
  store = inject(FieldSelectionService);
5974
6107
  ngOnChanges(changes) {
5975
6108
  if (changes['schema'] && this.schema) {
@@ -6004,16 +6137,18 @@ class FieldSelectionComponent {
6004
6137
  }
6005
6138
  }
6006
6139
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldSelectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6007
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: FieldSelectionComponent, isStandalone: false, selector: "lib-field-selection", inputs: { schema: "schema" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldSelectionService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}\n"], dependencies: [{ kind: "component", type: GroupNodeComponent, selector: "lib-group-node", inputs: ["group", "groupIndex"], outputs: ["toggleEnabled", "toggleExpanded", "sectionToggleEnabled", "sectionToggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6140
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: FieldSelectionComponent, isStandalone: false, selector: "lib-field-selection", inputs: { schema: "schema", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldSelectionService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}\n"], dependencies: [{ kind: "component", type: GroupNodeComponent, selector: "lib-group-node", inputs: ["group", "groupIndex", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "sectionToggleEnabled", "sectionToggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6008
6141
  }
6009
6142
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldSelectionComponent, decorators: [{
6010
6143
  type: Component,
6011
- args: [{ selector: 'lib-field-selection', standalone: false, providers: [FieldSelectionService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}\n"] }]
6144
+ args: [{ selector: 'lib-field-selection', standalone: false, providers: [FieldSelectionService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}\n"] }]
6012
6145
  }], propDecorators: { schema: [{
6013
6146
  type: Input,
6014
6147
  args: [{ required: true }]
6015
6148
  }], schemaChange: [{
6016
6149
  type: Output
6150
+ }], hideToggleForOptionTypes: [{
6151
+ type: Input
6017
6152
  }] } });
6018
6153
 
6019
6154
  /**
@@ -6244,33 +6379,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
6244
6379
  */
6245
6380
  const BUILDER_FIELD_TYPE_SCHEMA_MAP = new InjectionToken('BUILDER_FIELD_TYPE_SCHEMA_MAP');
6246
6381
 
6247
- /** Available field types that users can switch to in the configurator. */
6248
- const SWITCHABLE_FIELD_TYPES = [
6249
- { label: 'Short Text', value: 'shortText' },
6250
- { label: 'Long Text', value: 'longText' },
6251
- { label: 'Email', value: 'email' },
6252
- { label: 'Phone', value: 'phone' },
6253
- { label: 'Password', value: 'password' },
6254
- { label: 'Number (Integer)', value: 'number' },
6255
- { label: 'Number (Decimal)', value: 'decimal' },
6256
- { label: 'Date', value: 'date' },
6257
- { label: 'Time', value: 'time' },
6258
- { label: 'Date & Time', value: 'dateTime' },
6259
- { label: 'Dropdown', value: 'dropdown' },
6260
- { label: 'Multi-Select', value: 'multiSelect' },
6261
- { label: 'Autocomplete', value: 'autocomplete' },
6262
- { label: 'Checkbox', value: 'checkbox' },
6263
- { label: 'Multi-Checkbox', value: 'multiCheckbox' },
6264
- { label: 'Radio', value: 'radio' },
6265
- { label: 'Toggle', value: 'toggle' },
6266
- { label: 'Chips', value: 'chip' },
6267
- { label: 'Rich Text', value: 'richText' },
6268
- { label: 'File Upload', value: 'file' },
6269
- { label: 'Rating', value: 'rating' },
6270
- { label: 'Location', value: 'location' },
6271
- { label: 'Formula (Auto)', value: 'generated' },
6272
- ];
6273
-
6274
6382
  // ─────────────────────────────────────────────────────────────────────────────
6275
6383
  // SHARED BASE FIELDS (common to ALL field types)
6276
6384
  // These fields come from the core FieldConfig interface.
@@ -6638,6 +6746,12 @@ class ConfiguratorConfigPanelComponent {
6638
6746
  fieldTypeSchemaMap = {};
6639
6747
  configChange = new EventEmitter();
6640
6748
  typeChange = new EventEmitter();
6749
+ /**
6750
+ * When false, all `optionConfig.*` fields (apiUrl, dataPath, labelPath, etc.)
6751
+ * are hidden from the config panel. Business users don't need to configure
6752
+ * option URLs — these are pre-filled by the developer in the master JSON.
6753
+ */
6754
+ showOptionConfig = true;
6641
6755
  /** Exposed to the template for the native type-switcher select */
6642
6756
  switchableFieldTypes = SWITCHABLE_FIELD_TYPES;
6643
6757
  configFormJson = '';
@@ -6706,13 +6820,17 @@ class ConfiguratorConfigPanelComponent {
6706
6820
  _buildConfigFormForType(builderType) {
6707
6821
  if (!this.fieldTypeSchemaMap || !this.selectedField)
6708
6822
  return;
6709
- const schema = this.fieldTypeSchemaMap[builderType];
6823
+ let schema = this.fieldTypeSchemaMap[builderType];
6710
6824
  if (!schema) {
6711
6825
  this.showConfigForm = false;
6712
6826
  this.configFormJson = '';
6713
6827
  this.cdr.markForCheck();
6714
6828
  return;
6715
6829
  }
6830
+ // When optionConfig should be hidden, filter it out of the schema
6831
+ if (!this.showOptionConfig) {
6832
+ schema = this._filterSchemaForOptionConfig(schema);
6833
+ }
6716
6834
  // 1. Destroy current SmartForm instance
6717
6835
  this.showConfigForm = false;
6718
6836
  this.cdr.detectChanges();
@@ -6725,6 +6843,46 @@ class ConfiguratorConfigPanelComponent {
6725
6843
  this.cdr.detectChanges();
6726
6844
  });
6727
6845
  }
6846
+ /**
6847
+ * Deep-clones the schema and removes any field whose `name` starts with
6848
+ * `optionConfig.` and removes entire sections that become empty after that.
6849
+ */
6850
+ _filterSchemaForOptionConfig(schema) {
6851
+ const isOptionField = (f) => typeof f?.name === 'string' && f.name.startsWith('optionConfig.');
6852
+ const filterChildren = (children) => children
6853
+ .map((child) => {
6854
+ // ROW — filter its inline children
6855
+ if (child.type === 'ROW' && Array.isArray(child.children)) {
6856
+ const filtered = child.children.filter((c) => !isOptionField(c));
6857
+ return filtered.length ? { ...child, children: filtered } : null;
6858
+ }
6859
+ // GROUP / section wrapper — recurse into sectionConfig.children
6860
+ if (child.sectionConfig?.children) {
6861
+ const filteredChildren = filterChildren(child.sectionConfig.children);
6862
+ // Drop the entire section if it becomes empty
6863
+ if (!filteredChildren.length)
6864
+ return null;
6865
+ return {
6866
+ ...child,
6867
+ sectionConfig: { ...child.sectionConfig, children: filteredChildren },
6868
+ };
6869
+ }
6870
+ // Leaf field
6871
+ if (isOptionField(child))
6872
+ return null;
6873
+ return child;
6874
+ })
6875
+ .filter(Boolean);
6876
+ const topChildren = schema.sectionConfig?.children
6877
+ ? filterChildren(schema.sectionConfig.children)
6878
+ : [];
6879
+ return {
6880
+ ...schema,
6881
+ sectionConfig: schema.sectionConfig
6882
+ ? { ...schema.sectionConfig, children: topChildren }
6883
+ : schema.sectionConfig,
6884
+ };
6885
+ }
6728
6886
  // ─── Private: Extract initial values from FieldConfig ─────────────────────
6729
6887
  _extractInitialValuesFromField(field) {
6730
6888
  const v = {};
@@ -6890,11 +7048,11 @@ class ConfiguratorConfigPanelComponent {
6890
7048
  return patch;
6891
7049
  }
6892
7050
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
6893
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:20px 32px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;padding:40px}.fb-config-panel__form-wrapper .fb-config-card{background:var(--fb-fc-card-bg, #ffffff);border-radius:12px;border:1px solid var(--fb-fc-card-border, #e5e7eb);padding:40px;box-shadow:0 4px 20px #00000008;max-width:800px;margin:0 auto;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 0;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 24px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .75rem 1rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode"], outputs: ["submit", "draftSave", "actionClick", "valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7051
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap", showOptionConfig: "showOptionConfig" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:20px 32px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;padding:20px}.fb-config-panel__form-wrapper .fb-config-card{background:var(--fb-fc-card-bg, #ffffff);border-radius:12px;border:1px solid var(--fb-fc-card-border, #e5e7eb);padding:24px;box-shadow:0 4px 20px #00000008;max-width:800px;margin:0 auto;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 0;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{flex-wrap:wrap;gap:12px 16px}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{flex:1;min-width:100px}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode", "readOnly"], outputs: ["submit", "draftSave", "actionClick", "valueChange", "fileAdded", "fileUploadFinished", "fileRemoved"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6894
7052
  }
6895
7053
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, decorators: [{
6896
7054
  type: Component,
6897
- args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:20px 32px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;padding:40px}.fb-config-panel__form-wrapper .fb-config-card{background:var(--fb-fc-card-bg, #ffffff);border-radius:12px;border:1px solid var(--fb-fc-card-border, #e5e7eb);padding:40px;box-shadow:0 4px 20px #00000008;max-width:800px;margin:0 auto;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 0;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 24px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .75rem 1rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}\n"] }]
7055
+ args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:20px 32px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;padding:20px}.fb-config-panel__form-wrapper .fb-config-card{background:var(--fb-fc-card-bg, #ffffff);border-radius:12px;border:1px solid var(--fb-fc-card-border, #e5e7eb);padding:24px;box-shadow:0 4px 20px #00000008;max-width:800px;margin:0 auto;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 0;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #FFFAF1;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 0 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{flex-wrap:wrap;gap:12px 16px}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{flex:1;min-width:100px}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}\n"] }]
6898
7056
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { selectedField: [{
6899
7057
  type: Input
6900
7058
  }], selectedFieldInfo: [{
@@ -6907,11 +7065,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
6907
7065
  type: Output
6908
7066
  }], typeChange: [{
6909
7067
  type: Output
7068
+ }], showOptionConfig: [{
7069
+ type: Input
6910
7070
  }] } });
6911
7071
 
6912
7072
  class FieldConfiguratorComponent {
6913
7073
  schema;
6914
7074
  schemaChange = new EventEmitter();
7075
+ /**
7076
+ * When false, the optionConfig section (apiUrl, dataPath, etc.) is hidden
7077
+ * from the configurator panel. Useful for business-user-facing configurators
7078
+ * where option URLs are pre-filled by the developer.
7079
+ * Defaults to true (show everything).
7080
+ */
7081
+ showOptionConfig = true;
6915
7082
  store = inject(FieldConfiguratorService);
6916
7083
  schemaMapOverride = inject(BUILDER_FIELD_TYPE_SCHEMA_MAP, { optional: true });
6917
7084
  /**
@@ -6949,16 +7116,18 @@ class FieldConfiguratorComponent {
6949
7116
  }
6950
7117
  }
6951
7118
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6952
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FieldConfiguratorComponent, isStandalone: false, selector: "lib-field-configurator", inputs: { schema: "schema" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldConfiguratorService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden}.fb-configurator__sidebar{width:var(--fb-fc-sidebar-width, 400px);flex-shrink:0;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden}.fb-configurator__main{flex:1;overflow-y:auto;background:var(--fb-fc-main-bg, #ffffff)}\n"], dependencies: [{ kind: "component", type: ConfiguratorTreeComponent, selector: "lib-configurator-tree", inputs: ["tree", "selectedFieldPath"], outputs: ["selectField", "toggleExpanded"] }, { kind: "component", type: ConfiguratorConfigPanelComponent, selector: "lib-configurator-config-panel", inputs: ["selectedField", "selectedFieldInfo", "builderFieldType", "fieldTypeSchemaMap"], outputs: ["configChange", "typeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7119
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FieldConfiguratorComponent, isStandalone: false, selector: "lib-field-configurator", inputs: { schema: "schema", showOptionConfig: "showOptionConfig" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldConfiguratorService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden}.fb-configurator__sidebar{width:var(--fb-fc-sidebar-width, 400px);flex-shrink:0;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden}.fb-configurator__main{flex:1;overflow-y:auto;background:var(--fb-fc-main-bg, #ffffff)}\n"], dependencies: [{ kind: "component", type: ConfiguratorTreeComponent, selector: "lib-configurator-tree", inputs: ["tree", "selectedFieldPath"], outputs: ["selectField", "toggleExpanded"] }, { kind: "component", type: ConfiguratorConfigPanelComponent, selector: "lib-configurator-config-panel", inputs: ["selectedField", "selectedFieldInfo", "builderFieldType", "fieldTypeSchemaMap", "showOptionConfig"], outputs: ["configChange", "typeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6953
7120
  }
6954
7121
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldConfiguratorComponent, decorators: [{
6955
7122
  type: Component,
6956
- args: [{ selector: 'lib-field-configurator', standalone: false, providers: [FieldConfiguratorService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden}.fb-configurator__sidebar{width:var(--fb-fc-sidebar-width, 400px);flex-shrink:0;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden}.fb-configurator__main{flex:1;overflow-y:auto;background:var(--fb-fc-main-bg, #ffffff)}\n"] }]
7123
+ args: [{ selector: 'lib-field-configurator', standalone: false, providers: [FieldConfiguratorService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden}.fb-configurator__sidebar{width:var(--fb-fc-sidebar-width, 400px);flex-shrink:0;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden}.fb-configurator__main{flex:1;overflow-y:auto;background:var(--fb-fc-main-bg, #ffffff)}\n"] }]
6957
7124
  }], propDecorators: { schema: [{
6958
7125
  type: Input,
6959
7126
  args: [{ required: true }]
6960
7127
  }], schemaChange: [{
6961
7128
  type: Output
7129
+ }], showOptionConfig: [{
7130
+ type: Input
6962
7131
  }] } });
6963
7132
 
6964
7133
  const COMPONENTS = [
@@ -7005,6 +7174,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7005
7174
  class ConfirmationModalComponent {
7006
7175
  config;
7007
7176
  isOpen = false;
7177
+ confirmDisabled = false;
7178
+ confirmLoading = false;
7008
7179
  confirm = new EventEmitter();
7009
7180
  cancel = new EventEmitter();
7010
7181
  close = new EventEmitter();
@@ -7024,6 +7195,7 @@ class ConfirmationModalComponent {
7024
7195
  };
7025
7196
  mergedConfig;
7026
7197
  previousActiveElement = null;
7198
+ isSubmitting = false;
7027
7199
  ngOnInit() {
7028
7200
  this.updateConfig();
7029
7201
  // Store currently focused element
@@ -7037,9 +7209,20 @@ class ConfirmationModalComponent {
7037
7209
  this.updateConfig();
7038
7210
  if (this.isOpen !== undefined) {
7039
7211
  this.toggleBodyScroll(this.isOpen);
7212
+ if (!this.isOpen) {
7213
+ this.isSubmitting = false; // Reset submission guard when modal closes
7214
+ }
7215
+ }
7216
+ // Reset submission guard when loading state finishes
7217
+ if (this.isSubmitting && !this.confirmLoading && !this.mergedConfig.confirmButton.loading) {
7218
+ this.isSubmitting = false;
7040
7219
  }
7041
7220
  }
7042
7221
  updateConfig() {
7222
+ if (!this.config) {
7223
+ this.mergedConfig = { ...this.defaultConfig };
7224
+ return;
7225
+ }
7043
7226
  // Merge user config with defaults
7044
7227
  this.mergedConfig = {
7045
7228
  ...this.defaultConfig,
@@ -7052,6 +7235,9 @@ class ConfirmationModalComponent {
7052
7235
  ...this.config.confirmButton
7053
7236
  }
7054
7237
  };
7238
+ if (this.mergedConfig.confirmButton) {
7239
+ // Logic handled by input/flag
7240
+ }
7055
7241
  }
7056
7242
  ngOnDestroy() {
7057
7243
  // Restore body scroll
@@ -7083,8 +7269,10 @@ class ConfirmationModalComponent {
7083
7269
  }
7084
7270
  }
7085
7271
  onConfirm() {
7086
- if (!this.mergedConfig.confirmButton.disabled &&
7087
- !this.mergedConfig.confirmButton.loading) {
7272
+ const isDisabled = this.confirmDisabled || this.mergedConfig.confirmButton.disabled;
7273
+ const isLoading = this.confirmLoading || this.mergedConfig.confirmButton.loading;
7274
+ if (!isDisabled && !isLoading && !this.isSubmitting) {
7275
+ this.isSubmitting = true;
7088
7276
  this.confirm.emit();
7089
7277
  }
7090
7278
  }
@@ -7114,7 +7302,8 @@ class ConfirmationModalComponent {
7114
7302
  danger: 'cc-btn-danger',
7115
7303
  warning: 'cc-btn-warning'
7116
7304
  };
7117
- return `cc-btn ${typeMap[this.mergedConfig.confirmButton.type]}`;
7305
+ const isLoading = this.confirmLoading || this.mergedConfig.confirmButton.loading;
7306
+ return `cc-btn ${typeMap[this.mergedConfig.confirmButton.type]} ${isLoading ? 'cc-btn-loading' : ''}`;
7118
7307
  }
7119
7308
  getHeaderClass() {
7120
7309
  return `modal-header modal-header--${this.mergedConfig.headerTheme}`;
@@ -7141,15 +7330,19 @@ class ConfirmationModalComponent {
7141
7330
  return typeof icon === 'object' ? icon.color : undefined;
7142
7331
  }
7143
7332
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7144
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfirmationModalComponent, isStandalone: false, selector: "cc-confirmation-modal", inputs: { config: "config", isOpen: "isOpen" }, outputs: { confirm: "confirm", cancel: "cancel", close: "close", showCodeSnippet: "showCodeSnippet" }, host: { listeners: { "document:keydown.escape": "handleEscape($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"mergedConfig.confirmButton.disabled || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
7333
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfirmationModalComponent, isStandalone: false, selector: "cc-confirmation-modal", inputs: { config: "config", isOpen: "isOpen", confirmDisabled: "confirmDisabled", confirmLoading: "confirmLoading" }, outputs: { confirm: "confirm", cancel: "cancel", close: "close", showCodeSnippet: "showCodeSnippet" }, host: { listeners: { "document:keydown.escape": "handleEscape($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
7145
7334
  }
7146
7335
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, decorators: [{
7147
7336
  type: Component,
7148
- args: [{ selector: 'cc-confirmation-modal', standalone: false, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"mergedConfig.confirmButton.disabled || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"] }]
7337
+ args: [{ selector: 'cc-confirmation-modal', standalone: false, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"] }]
7149
7338
  }], propDecorators: { config: [{
7150
7339
  type: Input
7151
7340
  }], isOpen: [{
7152
7341
  type: Input
7342
+ }], confirmDisabled: [{
7343
+ type: Input
7344
+ }], confirmLoading: [{
7345
+ type: Input
7153
7346
  }], confirm: [{
7154
7347
  type: Output
7155
7348
  }], cancel: [{
@@ -7295,7 +7488,7 @@ class ButtonDropdownComponent {
7295
7488
  this.confirmMessage = '';
7296
7489
  }
7297
7490
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonDropdownComponent, deps: [{ token: i0.ElementRef }, { token: i1$4.Router }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
7298
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ButtonDropdownComponent, isStandalone: false, selector: "lib-button-dropdown", inputs: { label: "label", variant: "variant", menuTheme: "menuTheme", icon: "icon", actions: "actions", data: "data", disabled: "disabled" }, outputs: { apiActionStart: "apiActionStart", apiActionSuccess: "apiActionSuccess", apiActionError: "apiActionError", actionClick: "actionClick" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-btn-dropdown-container\">\r\n <!-- Main Toggle Button -->\r\n <lib-button \r\n [variant]=\"variant\" \r\n [disabled]=\"disabled\"\r\n (click)=\"toggleDropdown($event)\">\r\n <span class=\"cc-btn-dropdown-content\">\r\n {{ label }}\r\n <i *ngIf=\"icon\" [class]=\"icon\" class=\"cc-btn-dropdown-icon\"></i>\r\n </span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Menu -->\r\n <div class=\"cc-dropdown-menu\" [ngClass]=\"'cc-dropdown-menu--' + menuTheme\" *ngIf=\"isOpen\">\r\n <button \r\n type=\"button\" \r\n class=\"cc-dropdown-item\" \r\n *ngFor=\"let action of actions\"\r\n [disabled]=\"action.disabled\"\r\n [ngClass]=\"action.variant ? 'cc-dropdown-item--' + action.variant : (action.color === 'red' || action.color === 'danger') ? 'cc-dropdown-item--danger' : ''\"\r\n [style.color]=\"action.color && !action.variant && action.color !== 'red' && action.color !== 'danger' ? action.color : null\"\r\n (click)=\"onActionItemClick(action, $event)\">\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\" class=\"cc-dropdown-item-icon\"></i>\r\n <span>{{ action.label }}</span>\r\n </button>\r\n <div class=\"cc-dropdown-empty\" *ngIf=\"!actions || actions.length === 0\">\r\n No actions available\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Confirmation Modal for Critical Actions -->\r\n<cc-confirmation-modal \r\n *ngIf=\"isConfirmModalOpen\"\r\n [isOpen]=\"isConfirmModalOpen\" \r\n [config]=\"confirmConfig!\"\r\n (confirm)=\"invokePendingAction()\"\r\n (close)=\"closeConfirmModal()\"\r\n (cancel)=\"closeConfirmModal()\">\r\n <p>{{ confirmMessage }}</p>\r\n</cc-confirmation-modal>\r\n", styles: [".cc-btn-dropdown-container{position:relative;display:inline-block}.cc-btn-dropdown-container .cc-btn-dropdown-content{display:flex;align-items:center;gap:.5rem}.cc-btn-dropdown-container .cc-btn-dropdown-icon{font-size:.85em;margin-left:2px}.cc-dropdown-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:1000;min-width:140px;border-radius:var(--cc-btn-dropdown-radius, 4px);padding:.25rem 0;font-family:var(--cc-btn-font-family, \"Inter\", sans-serif);font-size:var(--cc-btn-font-size, .875rem)}.cc-dropdown-menu--light{background-color:var(--cc-btn-dropdown-light-bg, #ffffff);border:var(--cc-btn-dropdown-border-light, 1px solid #e0e0e0);box-shadow:var(--cc-btn-dropdown-shadow-light, 0 4px 6px rgba(0, 0, 0, .1))}.cc-dropdown-menu--light .cc-dropdown-item{color:var(--cc-btn-dropdown-light-item-color, #333333)}.cc-dropdown-menu--light .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-light-item-hover-bg, #f5f5f5)}.cc-dropdown-menu--light .cc-dropdown-empty{color:#888}.cc-dropdown-menu--dark{background-color:var(--cc-btn-dropdown-dark-bg, #1a1a1a);border:var(--cc-btn-dropdown-border-dark, 1px solid #444444);box-shadow:var(--cc-btn-dropdown-shadow-dark, 0 4px 6px rgba(0, 0, 0, .5))}.cc-dropdown-menu--dark .cc-dropdown-item{color:var(--cc-btn-dropdown-dark-item-color, #ffffff)}.cc-dropdown-menu--dark .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-dark-item-hover-bg, #2d2d2d)}.cc-dropdown-menu--dark .cc-dropdown-empty{color:#bbb}.cc-dropdown-menu .cc-dropdown-empty{padding:.5rem 1rem;font-style:italic}.cc-dropdown-menu .cc-dropdown-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background-color .2s,color .2s}.cc-dropdown-menu .cc-dropdown-item:disabled{opacity:.5;cursor:not-allowed}.cc-dropdown-menu .cc-dropdown-item .cc-dropdown-item-icon{margin-right:.5rem;width:1rem;text-align:center}.cc-dropdown-menu .cc-dropdown-item--primary{background-color:var(--cc-btn-dropdown-primary-bg, #262125);color:var(--cc-btn-dropdown-primary-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--primary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-primary-hover, #3d353b)}.cc-dropdown-menu .cc-dropdown-item--warning{background-color:var(--cc-btn-dropdown-warning-bg, #F9C80E);color:var(--cc-btn-dropdown-warning-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--warning:hover:not(:disabled){background-color:var(--cc-btn-dropdown-warning-hover, #ebd573)}.cc-dropdown-menu .cc-dropdown-item--danger{background-color:var(--cc-btn-dropdown-danger-bg, #E63E30);color:var(--cc-btn-dropdown-danger-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--danger:hover:not(:disabled){background-color:var(--cc-btn-dropdown-danger-hover, #c93528)}.cc-dropdown-menu .cc-dropdown-item--success{background-color:var(--cc-btn-dropdown-success-bg, #16A34A);color:var(--cc-btn-dropdown-success-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--success:hover:not(:disabled){background-color:var(--cc-btn-dropdown-success-hover, #148f41)}.cc-dropdown-menu .cc-dropdown-item--secondary{background-color:var(--cc-btn-dropdown-secondary-bg, #E8EAED);color:var(--cc-btn-dropdown-secondary-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--secondary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-secondary-hover, #d1d5db)}.cc-dropdown-menu .cc-dropdown-item--outline{background-color:var(--cc-btn-dropdown-outline-bg, transparent);color:var(--cc-btn-dropdown-outline-color, #000000);border:1px solid var(--cc-btn-dropdown-outline-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--outline:hover:not(:disabled){background-color:var(--cc-btn-dropdown-outline-hover, rgba(0, 0, 0, .05))}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }] });
7491
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ButtonDropdownComponent, isStandalone: false, selector: "lib-button-dropdown", inputs: { label: "label", variant: "variant", menuTheme: "menuTheme", icon: "icon", actions: "actions", data: "data", disabled: "disabled" }, outputs: { apiActionStart: "apiActionStart", apiActionSuccess: "apiActionSuccess", apiActionError: "apiActionError", actionClick: "actionClick" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-btn-dropdown-container\">\r\n <!-- Main Toggle Button -->\r\n <lib-button \r\n [variant]=\"variant\" \r\n [disabled]=\"disabled\"\r\n (click)=\"toggleDropdown($event)\">\r\n <span class=\"cc-btn-dropdown-content\">\r\n {{ label }}\r\n <i *ngIf=\"icon\" [class]=\"icon\" class=\"cc-btn-dropdown-icon\"></i>\r\n </span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Menu -->\r\n <div class=\"cc-dropdown-menu\" [ngClass]=\"'cc-dropdown-menu--' + menuTheme\" *ngIf=\"isOpen\">\r\n <button \r\n type=\"button\" \r\n class=\"cc-dropdown-item\" \r\n *ngFor=\"let action of actions\"\r\n [disabled]=\"action.disabled\"\r\n [ngClass]=\"action.variant ? 'cc-dropdown-item--' + action.variant : (action.color === 'red' || action.color === 'danger') ? 'cc-dropdown-item--danger' : ''\"\r\n [style.color]=\"action.color && !action.variant && action.color !== 'red' && action.color !== 'danger' ? action.color : null\"\r\n (click)=\"onActionItemClick(action, $event)\">\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\" class=\"cc-dropdown-item-icon\"></i>\r\n <span>{{ action.label }}</span>\r\n </button>\r\n <div class=\"cc-dropdown-empty\" *ngIf=\"!actions || actions.length === 0\">\r\n No actions available\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Confirmation Modal for Critical Actions -->\r\n<cc-confirmation-modal \r\n *ngIf=\"isConfirmModalOpen\"\r\n [isOpen]=\"isConfirmModalOpen\" \r\n [config]=\"confirmConfig!\"\r\n (confirm)=\"invokePendingAction()\"\r\n (close)=\"closeConfirmModal()\"\r\n (cancel)=\"closeConfirmModal()\">\r\n <p>{{ confirmMessage }}</p>\r\n</cc-confirmation-modal>\r\n", styles: [".cc-btn-dropdown-container{position:relative;display:inline-block}.cc-btn-dropdown-container .cc-btn-dropdown-content{display:flex;align-items:center;gap:.5rem}.cc-btn-dropdown-container .cc-btn-dropdown-icon{font-size:.85em;margin-left:2px}.cc-dropdown-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:1000;min-width:140px;border-radius:var(--cc-btn-dropdown-radius, 4px);padding:.25rem 0;font-family:var(--cc-btn-font-family, \"Inter\", sans-serif);font-size:var(--cc-btn-font-size, .875rem)}.cc-dropdown-menu--light{background-color:var(--cc-btn-dropdown-light-bg, #ffffff);border:var(--cc-btn-dropdown-border-light, 1px solid #e0e0e0);box-shadow:var(--cc-btn-dropdown-shadow-light, 0 4px 6px rgba(0, 0, 0, .1))}.cc-dropdown-menu--light .cc-dropdown-item{color:var(--cc-btn-dropdown-light-item-color, #333333)}.cc-dropdown-menu--light .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-light-item-hover-bg, #f5f5f5)}.cc-dropdown-menu--light .cc-dropdown-empty{color:#888}.cc-dropdown-menu--dark{background-color:var(--cc-btn-dropdown-dark-bg, #1a1a1a);border:var(--cc-btn-dropdown-border-dark, 1px solid #444444);box-shadow:var(--cc-btn-dropdown-shadow-dark, 0 4px 6px rgba(0, 0, 0, .5))}.cc-dropdown-menu--dark .cc-dropdown-item{color:var(--cc-btn-dropdown-dark-item-color, #ffffff)}.cc-dropdown-menu--dark .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-dark-item-hover-bg, #2d2d2d)}.cc-dropdown-menu--dark .cc-dropdown-empty{color:#bbb}.cc-dropdown-menu .cc-dropdown-empty{padding:.5rem 1rem;font-style:italic}.cc-dropdown-menu .cc-dropdown-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background-color .2s,color .2s}.cc-dropdown-menu .cc-dropdown-item:disabled{opacity:.5;cursor:not-allowed}.cc-dropdown-menu .cc-dropdown-item .cc-dropdown-item-icon{margin-right:.5rem;width:1rem;text-align:center}.cc-dropdown-menu .cc-dropdown-item--primary{background-color:var(--cc-btn-dropdown-primary-bg, #262125);color:var(--cc-btn-dropdown-primary-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--primary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-primary-hover, #3d353b)}.cc-dropdown-menu .cc-dropdown-item--warning{background-color:var(--cc-btn-dropdown-warning-bg, #F9C80E);color:var(--cc-btn-dropdown-warning-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--warning:hover:not(:disabled){background-color:var(--cc-btn-dropdown-warning-hover, #ebd573)}.cc-dropdown-menu .cc-dropdown-item--danger{background-color:var(--cc-btn-dropdown-danger-bg, #E63E30);color:var(--cc-btn-dropdown-danger-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--danger:hover:not(:disabled){background-color:var(--cc-btn-dropdown-danger-hover, #c93528)}.cc-dropdown-menu .cc-dropdown-item--success{background-color:var(--cc-btn-dropdown-success-bg, #16A34A);color:var(--cc-btn-dropdown-success-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--success:hover:not(:disabled){background-color:var(--cc-btn-dropdown-success-hover, #148f41)}.cc-dropdown-menu .cc-dropdown-item--secondary{background-color:var(--cc-btn-dropdown-secondary-bg, #E8EAED);color:var(--cc-btn-dropdown-secondary-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--secondary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-secondary-hover, #d1d5db)}.cc-dropdown-menu .cc-dropdown-item--outline{background-color:var(--cc-btn-dropdown-outline-bg, transparent);color:var(--cc-btn-dropdown-outline-color, #000000);border:1px solid var(--cc-btn-dropdown-outline-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--outline:hover:not(:disabled){background-color:var(--cc-btn-dropdown-outline-hover, rgba(0, 0, 0, .05))}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }] });
7299
7492
  }
7300
7493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonDropdownComponent, decorators: [{
7301
7494
  type: Component,
@@ -9223,11 +9416,29 @@ class SmartTableComponent {
9223
9416
  cdr;
9224
9417
  ngZone;
9225
9418
  config;
9419
+ /**
9420
+ * External data mode: pass table rows directly from the parent.
9421
+ * When this input is provided, the component will NOT make any internal API calls.
9422
+ * Instead, it emits sortChange / pageChange / searchChange / filterChange events
9423
+ * so the parent can fetch and supply updated data.
9424
+ */
9425
+ tableData;
9426
+ /**
9427
+ * Total number of items — used by the pagination component when operating in
9428
+ * external-data mode. Must be kept in sync by the parent.
9429
+ */
9430
+ totalItemsCount;
9226
9431
  action = new EventEmitter();
9227
9432
  topAction = new EventEmitter(); // For top bar buttons
9228
9433
  filterChange = new EventEmitter();
9229
9434
  rowSelect = new EventEmitter();
9230
9435
  columnClick = new EventEmitter();
9436
+ /** Emitted in external-data mode when the user changes the sort column/direction. */
9437
+ sortChange = new EventEmitter();
9438
+ /** Emitted in external-data mode when the user changes the page or page size. */
9439
+ pageChange = new EventEmitter();
9440
+ /** Emitted in external-data mode when the user types in the search box. */
9441
+ searchChange = new EventEmitter();
9231
9442
  data = [];
9232
9443
  totalItems = 0;
9233
9444
  currentPage = 1;
@@ -9241,6 +9452,12 @@ class SmartTableComponent {
9241
9452
  stickyColumnStyles = {};
9242
9453
  hasStickyColumns = false;
9243
9454
  openDropdownId = null;
9455
+ /** Viewport-relative position used to render the dropdown as position:fixed. */
9456
+ dropdownPosition = { top: 0, right: 0 };
9457
+ // --- Delete confirmation modal state ---
9458
+ deleteModalOpen = false;
9459
+ deleteModalConfig = {};
9460
+ pendingDeleteAction = null;
9244
9461
  searchSubject = new Subject();
9245
9462
  stickyHeaders;
9246
9463
  resizeObserver = null;
@@ -9254,7 +9471,13 @@ class SmartTableComponent {
9254
9471
  this.searchSubject.pipe(debounceTime(this.config?.searchConfig?.debounceTime || 300), distinctUntilChanged()).subscribe(term => {
9255
9472
  this.searchTerm = term;
9256
9473
  this.currentPage = 1;
9257
- this.loadData();
9474
+ if (this.tableData !== undefined) {
9475
+ // External-data mode: delegate to parent via event
9476
+ this.searchChange.emit(this.buildChangeEvent());
9477
+ }
9478
+ else {
9479
+ this.loadData();
9480
+ }
9258
9481
  });
9259
9482
  }
9260
9483
  ngOnInit() {
@@ -9267,13 +9490,33 @@ class SmartTableComponent {
9267
9490
  this.isSortActive = true;
9268
9491
  }
9269
9492
  this.loadFilterOptions();
9270
- this.loadData();
9493
+ if (this.tableData !== undefined) {
9494
+ // External-data mode: sync incoming data, skip internal API call
9495
+ this.data = this.tableData;
9496
+ if (this.totalItemsCount !== undefined) {
9497
+ this.totalItems = this.totalItemsCount;
9498
+ }
9499
+ }
9500
+ else {
9501
+ this.loadData();
9502
+ }
9271
9503
  }
9272
9504
  }
9273
9505
  ngOnChanges(changes) {
9506
+ // External data changed — sync directly without an API call
9507
+ if (changes['tableData']) {
9508
+ this.data = this.tableData || [];
9509
+ }
9510
+ // Total count updated from parent
9511
+ if (changes['totalItemsCount'] && this.totalItemsCount !== undefined) {
9512
+ this.totalItems = this.totalItemsCount;
9513
+ }
9514
+ // Config changed (non-first) — reload filter opts; reload data only if NOT in external mode
9274
9515
  if (changes['config'] && !changes['config'].firstChange) {
9275
9516
  this.loadFilterOptions();
9276
- this.loadData();
9517
+ if (this.tableData === undefined) {
9518
+ this.loadData();
9519
+ }
9277
9520
  setTimeout(() => this.calculateStickyPositions());
9278
9521
  }
9279
9522
  }
@@ -9470,13 +9713,23 @@ class SmartTableComponent {
9470
9713
  // --- Actions ---
9471
9714
  onPageChange(page) {
9472
9715
  this.currentPage = page;
9473
- this.loadData();
9716
+ if (this.tableData !== undefined) {
9717
+ this.pageChange.emit(this.buildChangeEvent());
9718
+ }
9719
+ else {
9720
+ this.loadData();
9721
+ }
9474
9722
  }
9475
9723
  onPageSizeChange(size) {
9476
9724
  if (this.config.pagination) {
9477
9725
  this.config.pagination.pageSize = size;
9478
9726
  this.currentPage = 1; // Reset to first page
9479
- this.loadData();
9727
+ if (this.tableData !== undefined) {
9728
+ this.pageChange.emit(this.buildChangeEvent());
9729
+ }
9730
+ else {
9731
+ this.loadData();
9732
+ }
9480
9733
  }
9481
9734
  }
9482
9735
  onSort(col) {
@@ -9490,7 +9743,13 @@ class SmartTableComponent {
9490
9743
  this.activeSort.direction = 'ASC';
9491
9744
  }
9492
9745
  this.isSortActive = true; // User has actively sorted, include orderBy in API call
9493
- this.loadData();
9746
+ if (this.tableData !== undefined) {
9747
+ // External-data mode: let the parent handle the API call
9748
+ this.sortChange.emit(this.buildChangeEvent());
9749
+ }
9750
+ else {
9751
+ this.loadData();
9752
+ }
9494
9753
  }
9495
9754
  onSearch(event) {
9496
9755
  const value = event.target.value;
@@ -9501,7 +9760,24 @@ class SmartTableComponent {
9501
9760
  this.activeFilters[key] = value;
9502
9761
  this.currentPage = 1;
9503
9762
  this.filterChange.emit({ key, value });
9504
- this.loadData();
9763
+ if (this.tableData === undefined) {
9764
+ this.loadData();
9765
+ }
9766
+ }
9767
+ // --- Private helpers ---
9768
+ /**
9769
+ * Assembles the current table state into a `TableDataChangeEvent` object.
9770
+ * Emitted to the parent in external-data mode so it can fetch and supply new data.
9771
+ */
9772
+ buildChangeEvent() {
9773
+ return {
9774
+ page: this.currentPage,
9775
+ pageSize: this.config.pagination?.pageSize || 10,
9776
+ sortBy: this.activeSort.key || undefined,
9777
+ orderBy: this.isSortActive ? this.activeSort.direction : undefined,
9778
+ searchTerm: this.searchTerm || undefined,
9779
+ filters: { ...this.activeFilters }
9780
+ };
9505
9781
  }
9506
9782
  onAction(action, row) {
9507
9783
  if (action.type === 'callback' && action.callback) {
@@ -9531,6 +9807,10 @@ class SmartTableComponent {
9531
9807
  }
9532
9808
  onActionItemClick(item, row, event) {
9533
9809
  event.stopPropagation();
9810
+ if (item.type === 'delete') {
9811
+ this.openDeleteConfirmModal(item, row);
9812
+ return;
9813
+ }
9534
9814
  if (item.type === 'callback' && item.callback) {
9535
9815
  item.callback(row);
9536
9816
  }
@@ -9556,6 +9836,48 @@ class SmartTableComponent {
9556
9836
  this.action.emit({ action: item, row });
9557
9837
  }
9558
9838
  }
9839
+ openDeleteConfirmModal(item, row) {
9840
+ const cfg = item.deleteConfig || {};
9841
+ this.deleteModalConfig = {
9842
+ title: cfg.modalTitle || 'Confirm Delete',
9843
+ size: 'sm',
9844
+ headerTheme: 'dark',
9845
+ confirmButton: {
9846
+ label: cfg.confirmLabel || 'Delete',
9847
+ type: 'danger'
9848
+ },
9849
+ cancelButton: {
9850
+ label: cfg.cancelLabel || 'Cancel',
9851
+ show: true
9852
+ }
9853
+ };
9854
+ this.deleteModalMessage = cfg.modalMessage || 'Are you sure you want to delete this item?';
9855
+ this.pendingDeleteAction = { item, row };
9856
+ this.deleteModalOpen = true;
9857
+ }
9858
+ deleteModalMessage = '';
9859
+ onDeleteConfirm() {
9860
+ this.deleteModalOpen = false;
9861
+ if (!this.pendingDeleteAction)
9862
+ return;
9863
+ const { item, row } = this.pendingDeleteAction;
9864
+ const cfg = item.deleteConfig || {};
9865
+ const idField = cfg.idField || 'id';
9866
+ const url = cfg.apiUrl.replace(`:${idField}`, row[idField]);
9867
+ this.pendingDeleteAction = null;
9868
+ this.loading = true;
9869
+ this.http.delete(url, { headers: this.getHeaders() }).pipe(finalize(() => this.loading = false)).subscribe({
9870
+ next: () => {
9871
+ this.loadData();
9872
+ this.action.emit({ action: item, row });
9873
+ },
9874
+ error: (err) => console.error('[SmartTable] Delete API Error', err)
9875
+ });
9876
+ }
9877
+ onDeleteCancel() {
9878
+ this.deleteModalOpen = false;
9879
+ this.pendingDeleteAction = null;
9880
+ }
9559
9881
  onTopAction(action) {
9560
9882
  if (action.type === 'callback' && action.callback) {
9561
9883
  action.callback(null); // No row for top action
@@ -9793,19 +10115,35 @@ class SmartTableComponent {
9793
10115
  }
9794
10116
  toggleDropdown(id, event) {
9795
10117
  event.stopPropagation();
9796
- this.openDropdownId = this.openDropdownId === id ? null : id;
10118
+ if (this.openDropdownId === id) {
10119
+ this.openDropdownId = null;
10120
+ return;
10121
+ }
10122
+ // Compute fixed position from the trigger button so the menu escapes
10123
+ // any overflow:auto ancestor (the table container).
10124
+ const btn = event.currentTarget;
10125
+ const rect = btn.getBoundingClientRect();
10126
+ this.dropdownPosition = {
10127
+ top: rect.bottom + 4,
10128
+ right: window.innerWidth - rect.right
10129
+ };
10130
+ this.openDropdownId = id;
9797
10131
  }
9798
10132
  closeDropdown() {
9799
10133
  this.openDropdownId = null;
9800
10134
  }
9801
10135
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, deps: [{ token: i3.HttpClient }, { token: i1$4.Router }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
9802
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data; let rowIndex = index\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" \n [class.sticky-col]=\"col.sticky\" \n [ngStyle]=\"stickyColumnStyles[col.key]\"\n [class.clickable-cell]=\"col.clickAction\"\n (click)=\"onColumnClick(row, col)\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\n <ng-container *ngIf=\"action.type === 'dropdown'\">\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\n <button class=\"st-dropdown-btn\" (click)=\"toggleDropdown(rowIndex + '-' + i, $event)\">\n <i [class]=\"action.icon || 'fa fa-ellipsis-h'\"></i>\n </button>\n <div class=\"st-dropdown-menu\" *ngIf=\"openDropdownId === (rowIndex + '-' + i)\">\n <button class=\"st-dropdown-item\" *ngFor=\"let item of action.items\" (click)=\"onActionItemClick(item, row, $event); closeDropdown()\">\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\n <span>{{ item.label }}</span>\n </button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </ng-container>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n</div>\n", styles: [".smart-table-wrapper{margin:var(--st-margin, 1.5rem 0);font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:auto;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table tbody tr .clickable-cell:hover{background:var(--st-cell-hover-bg, #f0f0f0)!important}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;font-size:1.1rem;padding:4px 8px;color:var(--st-text-color, #333);border-radius:4px}.st-dropdown-btn:hover{background:#0000000d}.st-dropdown-menu{position:absolute;top:100%;right:0;min-width:150px;background:var(--st-card-bg, #fff);border:1px solid var(--border-color, #e0e0e0);border-radius:4px;box-shadow:0 4px 12px #00000026;z-index:1000;display:flex;flex-direction:column;padding:4px 0;margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:8px 16px;text-align:left;cursor:pointer;display:flex;align-items:center;font-size:14px;color:var(--st-text-color, #333);transition:background .2s}.st-dropdown-item:hover{background:#0000000d}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888)}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }] });
10136
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config", tableData: "tableData", totalItemsCount: "totalItemsCount" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick", sortChange: "sortChange", pageChange: "pageChange", searchChange: "searchChange" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data; let rowIndex = index\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" \n [class.sticky-col]=\"col.sticky\" \n [ngStyle]=\"stickyColumnStyles[col.key]\"\n [class.clickable-cell]=\"col.clickAction\"\n (click)=\"onColumnClick(row, col)\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\n <ng-container *ngIf=\"action.type === 'dropdown'\">\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\n <button class=\"st-dropdown-btn\" (click)=\"toggleDropdown(rowIndex + '-' + i, $event)\">\n <i [class]=\"action.icon || 'fa fa-ellipsis-h'\"></i>\n </button>\n <div class=\"st-dropdown-menu\"\n *ngIf=\"openDropdownId === (rowIndex + '-' + i)\"\n [ngStyle]=\"{\n position: 'fixed',\n top: dropdownPosition.top + 'px',\n right: dropdownPosition.right + 'px',\n left: 'auto'\n }\">\n <button class=\"st-dropdown-item\" *ngFor=\"let item of action.items\" (click)=\"onActionItemClick(item, row, $event); closeDropdown()\">\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\n <span>{{ item.label }}</span>\n </button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </ng-container>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n\n <!-- Built-in Delete Confirmation Modal -->\n <cc-confirmation-modal\n [isOpen]=\"deleteModalOpen\"\n [config]=\"deleteModalConfig\"\n (confirm)=\"onDeleteConfirm()\"\n (cancel)=\"onDeleteCancel()\"\n (close)=\"onDeleteCancel()\">\n <p>{{ deleteModalMessage }}</p>\n </cc-confirmation-modal>\n</div>\n\n", styles: [".smart-table-wrapper{margin:var(--st-margin, 1.5rem 0);font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:visible;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table tbody tr .clickable-cell:hover{background:var(--st-cell-hover-bg, #f0f0f0)!important}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;font-size:1.1rem;padding:4px 8px;color:var(--st-text-color, #333);border-radius:4px}.st-dropdown-btn:hover{background:#0000000d}.st-dropdown-menu{min-width:150px;background:var(--st-card-bg, #fff);border:1px solid var(--border-color, #e0e0e0);border-radius:4px;box-shadow:0 4px 12px #00000026;z-index:9999;display:flex;flex-direction:column;padding:4px 0;margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:8px 16px;text-align:left;cursor:pointer;display:flex;align-items:center;font-size:14px;color:var(--st-text-color, #333);transition:background .2s}.st-dropdown-item:hover{background:#0000000d}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }] });
9803
10137
  }
9804
10138
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, decorators: [{
9805
10139
  type: Component,
9806
- args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data; let rowIndex = index\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" \n [class.sticky-col]=\"col.sticky\" \n [ngStyle]=\"stickyColumnStyles[col.key]\"\n [class.clickable-cell]=\"col.clickAction\"\n (click)=\"onColumnClick(row, col)\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\n <ng-container *ngIf=\"action.type === 'dropdown'\">\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\n <button class=\"st-dropdown-btn\" (click)=\"toggleDropdown(rowIndex + '-' + i, $event)\">\n <i [class]=\"action.icon || 'fa fa-ellipsis-h'\"></i>\n </button>\n <div class=\"st-dropdown-menu\" *ngIf=\"openDropdownId === (rowIndex + '-' + i)\">\n <button class=\"st-dropdown-item\" *ngFor=\"let item of action.items\" (click)=\"onActionItemClick(item, row, $event); closeDropdown()\">\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\n <span>{{ item.label }}</span>\n </button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </ng-container>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n</div>\n", styles: [".smart-table-wrapper{margin:var(--st-margin, 1.5rem 0);font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:auto;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table tbody tr .clickable-cell:hover{background:var(--st-cell-hover-bg, #f0f0f0)!important}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;font-size:1.1rem;padding:4px 8px;color:var(--st-text-color, #333);border-radius:4px}.st-dropdown-btn:hover{background:#0000000d}.st-dropdown-menu{position:absolute;top:100%;right:0;min-width:150px;background:var(--st-card-bg, #fff);border:1px solid var(--border-color, #e0e0e0);border-radius:4px;box-shadow:0 4px 12px #00000026;z-index:1000;display:flex;flex-direction:column;padding:4px 0;margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:8px 16px;text-align:left;cursor:pointer;display:flex;align-items:center;font-size:14px;color:var(--st-text-color, #333);transition:background .2s}.st-dropdown-item:hover{background:#0000000d}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888)}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
10140
+ args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data; let rowIndex = index\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" \n [class.sticky-col]=\"col.sticky\" \n [ngStyle]=\"stickyColumnStyles[col.key]\"\n [class.clickable-cell]=\"col.clickAction\"\n (click)=\"onColumnClick(row, col)\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\n <ng-container *ngIf=\"action.type === 'dropdown'\">\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\n <button class=\"st-dropdown-btn\" (click)=\"toggleDropdown(rowIndex + '-' + i, $event)\">\n <i [class]=\"action.icon || 'fa fa-ellipsis-h'\"></i>\n </button>\n <div class=\"st-dropdown-menu\"\n *ngIf=\"openDropdownId === (rowIndex + '-' + i)\"\n [ngStyle]=\"{\n position: 'fixed',\n top: dropdownPosition.top + 'px',\n right: dropdownPosition.right + 'px',\n left: 'auto'\n }\">\n <button class=\"st-dropdown-item\" *ngFor=\"let item of action.items\" (click)=\"onActionItemClick(item, row, $event); closeDropdown()\">\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\n <span>{{ item.label }}</span>\n </button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </ng-container>\n </div>\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n\n <!-- Built-in Delete Confirmation Modal -->\n <cc-confirmation-modal\n [isOpen]=\"deleteModalOpen\"\n [config]=\"deleteModalConfig\"\n (confirm)=\"onDeleteConfirm()\"\n (cancel)=\"onDeleteCancel()\"\n (close)=\"onDeleteCancel()\">\n <p>{{ deleteModalMessage }}</p>\n </cc-confirmation-modal>\n</div>\n\n", styles: [".smart-table-wrapper{margin:var(--st-margin, 1.5rem 0);font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:visible;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table tbody tr .clickable-cell:hover{background:var(--st-cell-hover-bg, #f0f0f0)!important}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;font-size:1.1rem;padding:4px 8px;color:var(--st-text-color, #333);border-radius:4px}.st-dropdown-btn:hover{background:#0000000d}.st-dropdown-menu{min-width:150px;background:var(--st-card-bg, #fff);border:1px solid var(--border-color, #e0e0e0);border-radius:4px;box-shadow:0 4px 12px #00000026;z-index:9999;display:flex;flex-direction:column;padding:4px 0;margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:8px 16px;text-align:left;cursor:pointer;display:flex;align-items:center;font-size:14px;color:var(--st-text-color, #333);transition:background .2s}.st-dropdown-item:hover{background:#0000000d}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
9807
10141
  }], ctorParameters: () => [{ type: i3.HttpClient }, { type: i1$4.Router }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], propDecorators: { config: [{
9808
10142
  type: Input
10143
+ }], tableData: [{
10144
+ type: Input
10145
+ }], totalItemsCount: [{
10146
+ type: Input
9809
10147
  }], action: [{
9810
10148
  type: Output
9811
10149
  }], topAction: [{
@@ -9816,6 +10154,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
9816
10154
  type: Output
9817
10155
  }], columnClick: [{
9818
10156
  type: Output
10157
+ }], sortChange: [{
10158
+ type: Output
10159
+ }], pageChange: [{
10160
+ type: Output
10161
+ }], searchChange: [{
10162
+ type: Output
9819
10163
  }], stickyHeaders: [{
9820
10164
  type: ViewChildren,
9821
10165
  args: ['stickyHeader']
@@ -9830,12 +10174,14 @@ class SmartTableModule {
9830
10174
  FormsModule,
9831
10175
  PaginationModule,
9832
10176
  ButtonModule,
9833
- MaterialModule], exports: [SmartTableComponent] });
10177
+ MaterialModule,
10178
+ ConfirmationModalModule], exports: [SmartTableComponent] });
9834
10179
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableModule, imports: [CommonModule,
9835
10180
  FormsModule,
9836
10181
  PaginationModule,
9837
10182
  ButtonModule,
9838
- MaterialModule] });
10183
+ MaterialModule,
10184
+ ConfirmationModalModule] });
9839
10185
  }
9840
10186
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableModule, decorators: [{
9841
10187
  type: NgModule,
@@ -9848,7 +10194,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
9848
10194
  FormsModule,
9849
10195
  PaginationModule,
9850
10196
  ButtonModule,
9851
- MaterialModule
10197
+ MaterialModule,
10198
+ ConfirmationModalModule
9852
10199
  ],
9853
10200
  exports: [
9854
10201
  SmartTableComponent