@cqa-lib/cqa-ui 1.1.555 → 1.1.556

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.
@@ -11634,6 +11634,12 @@ class MoveTestSuiteDialogComponent {
11634
11634
  this.pickedFolderIdChange = new EventEmitter();
11635
11635
  this.submitted = new EventEmitter();
11636
11636
  this.cancelled = new EventEmitter();
11637
+ /** Fires when a folder needs its children fetched. Emitted by `pick` (row
11638
+ * click) and `toggleExpanded` (chevron click) when the target node has
11639
+ * `hasChildren = true` but `loadedPages == null` and is not already fetching.
11640
+ * Hosts subscribe and call their paginated fetch, mutating the FolderNode
11641
+ * in place (set `children`, `loadedPages`, `childrenLoading`). */
11642
+ this.folderChildrenRequested = new EventEmitter();
11637
11643
  /** Bubble cqa-custom-input focus/blur events up to hosts. Useful when
11638
11644
  * `fieldsDisabled = false` and the host wants to react to interaction. */
11639
11645
  this.currentFieldFocus = new EventEmitter();
@@ -11645,6 +11651,11 @@ class MoveTestSuiteDialogComponent {
11645
11651
  * suite starts in Unorganized (`currentFolderId = null`) so a fresh dialog
11646
11652
  * doesn't appear valid just because `pickedFolderId` also defaults to null. */
11647
11653
  this.pickedTouched = false;
11654
+ /** Folder ids currently expanded in the inlined picker. Managed entirely
11655
+ * inside this component (no external Input) so it survives the host pushing
11656
+ * a new `folders` reference after each lazy-fetch resolves. */
11657
+ this.expandedIds = new Set();
11658
+ this.trackById = (_, row) => row.id;
11648
11659
  }
11649
11660
  set folders(value) {
11650
11661
  this._folders = value || [];
@@ -11661,18 +11672,79 @@ class MoveTestSuiteDialogComponent {
11661
11672
  this.cdr.markForCheck();
11662
11673
  }
11663
11674
  get testSuiteLabels() { return this._testSuiteLabels; }
11664
- onParentPicked(id) {
11665
- let next = null;
11666
- if (id != null) {
11667
- const coerced = typeof id === 'number' ? id : Number(id);
11668
- if (Number.isFinite(coerced))
11669
- next = coerced;
11675
+ ngOnInit() {
11676
+ this.seedExpandedIds();
11677
+ }
11678
+ ngOnChanges(changes) {
11679
+ // Re-seed only when expansion-intent inputs change. NEVER on `folders` —
11680
+ // the host pushes a new top-level reference after every lazy fetch and a
11681
+ // reseed there would collapse the folder the user just expanded.
11682
+ if (changes['currentFolderId'] || changes['pickedFolderId']) {
11683
+ this.seedExpandedIds();
11670
11684
  }
11671
- this.pickedFolderId = next;
11685
+ }
11686
+ /** Folder-row click handler. Selects the folder as the destination and, when
11687
+ * the folder has unloaded children, auto-expands it and asks the host to
11688
+ * fetch its children. */
11689
+ pick(id) {
11690
+ this.pickedFolderId = id;
11672
11691
  this.pickedTouched = true;
11673
- this.pickedFolderIdChange.emit(next);
11692
+ this.pickedFolderIdChange.emit(id);
11693
+ if (id != null) {
11694
+ this.expandedIds.add(id);
11695
+ this.requestChildrenIfMissing(id);
11696
+ }
11697
+ this.cdr.markForCheck();
11698
+ }
11699
+ /** Chevron click handler. Toggles expansion locally; on expand path, asks
11700
+ * the host to fetch children when not already loaded. */
11701
+ toggleExpanded(id, event) {
11702
+ event.stopPropagation();
11703
+ if (this.expandedIds.has(id)) {
11704
+ this.expandedIds.delete(id);
11705
+ }
11706
+ else {
11707
+ this.expandedIds.add(id);
11708
+ this.requestChildrenIfMissing(id);
11709
+ }
11674
11710
  this.cdr.markForCheck();
11675
11711
  }
11712
+ isPicked(id) {
11713
+ return this.pickedFolderId === id;
11714
+ }
11715
+ /** "Unorganized" row is disabled when the suite is already in Unorganized. */
11716
+ get isUnorganizedDisabled() {
11717
+ return this.currentFolderId == null;
11718
+ }
11719
+ /** Flattened, depth-indented row descriptors fed into the template `*ngFor`.
11720
+ * Walks `_folders`, derives chevron / loading / expanded state per node. */
11721
+ get flatRows() {
11722
+ const out = [];
11723
+ const walk = (nodes, depth) => {
11724
+ for (const n of nodes || []) {
11725
+ // Drive the chevron from the backend's authoritative `hasChildren` so
11726
+ // it shows BEFORE children are loaded — required for lazy-load.
11727
+ const hasChildren = !!n.hasChildren;
11728
+ const expanded = this.expandedIds.has(n.id);
11729
+ const childrenLoading = !!n.childrenLoading;
11730
+ const childrenLoaded = !!(n.children && n.children.length);
11731
+ out.push({
11732
+ id: n.id,
11733
+ name: n.name,
11734
+ depth,
11735
+ disabled: n.id === this.currentFolderId,
11736
+ hasChildren,
11737
+ expanded,
11738
+ childrenLoading,
11739
+ showLoadingPlaceholder: expanded && childrenLoading && !childrenLoaded,
11740
+ });
11741
+ if (expanded && childrenLoaded)
11742
+ walk(n.children, depth + 1);
11743
+ }
11744
+ };
11745
+ walk(this._folders, 0);
11746
+ return out;
11747
+ }
11676
11748
  /** True once the user has picked a destination via the embedded tree. Drives
11677
11749
  * the destination-readout styling (indigo when picked, muted when not). */
11678
11750
  get hasPick() {
@@ -11742,6 +11814,47 @@ class MoveTestSuiteDialogComponent {
11742
11814
  onDestinationFieldBlurred(event) {
11743
11815
  this.destinationFieldBlur.emit(event);
11744
11816
  }
11817
+ requestChildrenIfMissing(id) {
11818
+ const node = this.findNode(this._folders, id);
11819
+ if (!node)
11820
+ return;
11821
+ if (node.hasChildren && node.loadedPages == null && !node.childrenLoading) {
11822
+ this.folderChildrenRequested.emit(id);
11823
+ }
11824
+ }
11825
+ seedExpandedIds() {
11826
+ this.expandedIds = new Set();
11827
+ const seed = this.currentFolderId != null ? this.currentFolderId : this.pickedFolderId;
11828
+ if (seed != null) {
11829
+ const trail = [];
11830
+ this.collectAncestors(this._folders, seed, trail);
11831
+ trail.forEach((id) => this.expandedIds.add(id));
11832
+ }
11833
+ }
11834
+ collectAncestors(nodes, targetId, acc) {
11835
+ for (const n of nodes || []) {
11836
+ acc.push(n.id);
11837
+ if (n.id === targetId)
11838
+ return true;
11839
+ if (n.children && this.collectAncestors(n.children, targetId, acc))
11840
+ return true;
11841
+ acc.pop();
11842
+ }
11843
+ return false;
11844
+ }
11845
+ findNode(nodes, id) {
11846
+ var _a;
11847
+ for (const n of nodes || []) {
11848
+ if (n.id === id)
11849
+ return n;
11850
+ if ((_a = n.children) === null || _a === void 0 ? void 0 : _a.length) {
11851
+ const hit = this.findNode(n.children, id);
11852
+ if (hit)
11853
+ return hit;
11854
+ }
11855
+ }
11856
+ return null;
11857
+ }
11745
11858
  findFolderName(nodes, id) {
11746
11859
  var _a;
11747
11860
  for (const n of nodes || []) {
@@ -11757,7 +11870,7 @@ class MoveTestSuiteDialogComponent {
11757
11870
  }
11758
11871
  }
11759
11872
  MoveTestSuiteDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MoveTestSuiteDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
11760
- MoveTestSuiteDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MoveTestSuiteDialogComponent, selector: "cqa-move-test-suite-dialog", inputs: { folders: "folders", labels: "labels", testSuiteLabels: "testSuiteLabels", currentFolderId: "currentFolderId", currentFolderName: "currentFolderName", suiteName: "suiteName", pickedFolderId: "pickedFolderId", pickerHeight: "pickerHeight", fieldsDisabled: "fieldsDisabled" }, outputs: { pickedFolderIdChange: "pickedFolderIdChange", submitted: "submitted", cancelled: "cancelled", currentFieldFocus: "currentFieldFocus", currentFieldBlur: "currentFieldBlur", destinationFieldFocus: "destinationFieldFocus", destinationFieldBlur: "destinationFieldBlur" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: `
11873
+ MoveTestSuiteDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MoveTestSuiteDialogComponent, selector: "cqa-move-test-suite-dialog", inputs: { folders: "folders", labels: "labels", testSuiteLabels: "testSuiteLabels", currentFolderId: "currentFolderId", currentFolderName: "currentFolderName", suiteName: "suiteName", pickedFolderId: "pickedFolderId", pickerHeight: "pickerHeight", fieldsDisabled: "fieldsDisabled" }, outputs: { pickedFolderIdChange: "pickedFolderIdChange", submitted: "submitted", cancelled: "cancelled", folderChildrenRequested: "folderChildrenRequested", currentFieldFocus: "currentFieldFocus", currentFieldBlur: "currentFieldBlur", destinationFieldFocus: "destinationFieldFocus", destinationFieldBlur: "destinationFieldBlur" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: `
11761
11874
  <div class="cqa-flex cqa-flex-col cqa-gap-2 cqa-w-full">
11762
11875
  <!-- Test suite name (read-only display; surfaces which suite is being moved) -->
11763
11876
  <cqa-custom-input
@@ -11790,17 +11903,84 @@ MoveTestSuiteDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12
11790
11903
  (blurred)="onDestinationFieldBlurred($event)"
11791
11904
  ></cqa-custom-input>
11792
11905
 
11793
- <!-- Folder tree picker -->
11794
- <cqa-move-to-folder-dialog
11795
- [folders]="folders"
11796
- [labels]="labels"
11797
- [currentFolderId]="currentFolderId"
11798
- [pickedFolderId]="pickedFolderId"
11799
- [pickerHeight]="pickerHeight"
11800
- (pickedFolderIdChange)="onParentPicked($event)"
11801
- ></cqa-move-to-folder-dialog>
11906
+ <!-- Folder tree picker (inlined; takes reference from cqa-move-to-folder-dialog
11907
+ but does not embed it, so the lazy-fetch wiring and expansion state stay
11908
+ local to this dialog). -->
11909
+ <ng-template #folderIconTpl>
11910
+ <svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="cqa-flex-shrink-0">
11911
+ <path d="M15.6375 12.6377C15.6375 13.0355 15.4794 13.4171 15.1981 13.6984C14.9168 13.9797 14.5353 14.1377 14.1375 14.1377H2.13745C1.73963 14.1377 1.3581 13.9797 1.07679 13.6984C0.795486 13.4171 0.637451 13.0355 0.637451 12.6377V2.1377C0.637451 1.73987 0.795486 1.35834 1.07679 1.07704C1.3581 0.795731 1.73963 0.637695 2.13745 0.637695H5.88745L7.38745 2.8877H14.1375C14.5353 2.8877 14.9168 3.04573 15.1981 3.32704C15.4794 3.60834 15.6375 3.98987 15.6375 4.3877V12.6377Z" stroke="currentColor" stroke-width="1.275" stroke-linecap="round" stroke-linejoin="round"/>
11912
+ </svg>
11913
+ </ng-template>
11914
+
11915
+ <ng-template #unorganizedIconTpl>
11916
+ <svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="cqa-flex-shrink-0">
11917
+ <path d="M14.6875 5.5V12.5C14.6875 13.3 14.0375 14 13.1875 14H3.8125C2.9625 14 2.3125 13.3 2.3125 12.5V5.5M14.6875 5.5L12.7875 1.7C12.5375 1.2 12.0875 1 11.5875 1H5.4125C4.9125 1 4.4625 1.2 4.2125 1.7L2.3125 5.5M14.6875 5.5H2.3125M6.1875 8.5H10.8125" stroke="currentColor" stroke-width="1.275" stroke-linecap="round" stroke-linejoin="round"/>
11918
+ </svg>
11919
+ </ng-template>
11920
+
11921
+ <div class="cqa-flex cqa-flex-col cqa-border-solid cqa-border cqa-border-[#E2E2E3] cqa-rounded-[10px] cqa-py-2 cqa-w-full cqa-overflow-y-auto cqa-bg-white cqa-scrollbar-thin" [style.height]="pickerHeight">
11922
+ <div
11923
+ role="button"
11924
+ tabindex="0"
11925
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-px-4 cqa-py-2 cqa-cursor-pointer cqa-transition-colors cqa-text-sm"
11926
+ [ngClass]="isPicked(null) ? 'cqa-bg-indigo-50 cqa-text-indigo-700' : 'cqa-text-neutral-800 hover:cqa-bg-neutral-50'"
11927
+ [class.cqa-opacity-40]="isUnorganizedDisabled"
11928
+ [class.cqa-cursor-not-allowed]="isUnorganizedDisabled"
11929
+ [attr.aria-disabled]="isUnorganizedDisabled || null"
11930
+ (click)="!isUnorganizedDisabled && pick(null)"
11931
+ (keydown.enter)="!isUnorganizedDisabled && pick(null)"
11932
+ (keydown.space)="$event.preventDefault(); !isUnorganizedDisabled && pick(null)"
11933
+ >
11934
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
11935
+ <ng-container *ngTemplateOutlet="unorganizedIconTpl"></ng-container>
11936
+ <span>{{ labels.moveDialogRoot }}</span>
11937
+ </div>
11938
+
11939
+ <ng-container *ngFor="let row of flatRows; trackBy: trackById">
11940
+ <div
11941
+ role="button"
11942
+ tabindex="0"
11943
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-py-2 cqa-pr-4 cqa-cursor-pointer cqa-transition-colors cqa-text-sm"
11944
+ [ngClass]="isPicked(row.id) ? 'cqa-bg-indigo-50 cqa-text-indigo-700' : 'cqa-text-neutral-800 hover:cqa-bg-neutral-50'"
11945
+ [class.cqa-opacity-40]="row.disabled"
11946
+ [class.cqa-cursor-not-allowed]="row.disabled"
11947
+ [style.paddingLeft.px]="16 + row.depth * 24"
11948
+ (click)="!row.disabled && pick(row.id)"
11949
+ (keydown.enter)="!row.disabled && pick(row.id)"
11950
+ (keydown.space)="!row.disabled && $event.preventDefault(); !row.disabled && pick(row.id)"
11951
+ >
11952
+ <button
11953
+ *ngIf="row.hasChildren; else chevronPlaceholder"
11954
+ type="button"
11955
+ class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-w-5 cqa-h-5 cqa-flex-shrink-0 cqa-rounded cqa-text-neutral-600 hover:cqa-bg-neutral-100 hover:cqa-text-neutral-900"
11956
+ [attr.aria-label]="row.expanded ? 'Collapse ' + row.name : 'Expand ' + row.name"
11957
+ (click)="toggleExpanded(row.id!, $event)"
11958
+ >
11959
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
11960
+ [class.cqa-rotate-90]="row.expanded" style="transition: transform 120ms ease;">
11961
+ <path d="M5 3L9 7L5 11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
11962
+ </svg>
11963
+ </button>
11964
+ <ng-template #chevronPlaceholder>
11965
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
11966
+ </ng-template>
11967
+
11968
+ <ng-container *ngTemplateOutlet="folderIconTpl"></ng-container>
11969
+ <span class="cqa-truncate">{{ row.name }}</span>
11970
+ </div>
11971
+
11972
+ <div
11973
+ *ngIf="row.showLoadingPlaceholder"
11974
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-py-2 cqa-pr-4 cqa-text-sm cqa-text-neutral-500 cqa-italic"
11975
+ [style.paddingLeft.px]="16 + (row.depth + 1) * 24"
11976
+ >
11977
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
11978
+ <span>Loading…</span>
11979
+ </div>
11980
+ </ng-container>
11981
+ </div>
11802
11982
  </div>
11803
- `, isInline: true, components: [{ type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["inputId", "label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: MoveToFolderDialogComponent, selector: "cqa-move-to-folder-dialog", inputs: ["folders", "labels", "currentFolderId", "pickedFolderId", "initialExpandedIds", "rootDisabled", "pickerHeight"], outputs: ["folderPicked", "pickedFolderIdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11983
+ `, isInline: true, components: [{ type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["inputId", "label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11804
11984
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MoveTestSuiteDialogComponent, decorators: [{
11805
11985
  type: Component,
11806
11986
  args: [{ selector: 'cqa-move-test-suite-dialog', template: `
@@ -11836,15 +12016,82 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
11836
12016
  (blurred)="onDestinationFieldBlurred($event)"
11837
12017
  ></cqa-custom-input>
11838
12018
 
11839
- <!-- Folder tree picker -->
11840
- <cqa-move-to-folder-dialog
11841
- [folders]="folders"
11842
- [labels]="labels"
11843
- [currentFolderId]="currentFolderId"
11844
- [pickedFolderId]="pickedFolderId"
11845
- [pickerHeight]="pickerHeight"
11846
- (pickedFolderIdChange)="onParentPicked($event)"
11847
- ></cqa-move-to-folder-dialog>
12019
+ <!-- Folder tree picker (inlined; takes reference from cqa-move-to-folder-dialog
12020
+ but does not embed it, so the lazy-fetch wiring and expansion state stay
12021
+ local to this dialog). -->
12022
+ <ng-template #folderIconTpl>
12023
+ <svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="cqa-flex-shrink-0">
12024
+ <path d="M15.6375 12.6377C15.6375 13.0355 15.4794 13.4171 15.1981 13.6984C14.9168 13.9797 14.5353 14.1377 14.1375 14.1377H2.13745C1.73963 14.1377 1.3581 13.9797 1.07679 13.6984C0.795486 13.4171 0.637451 13.0355 0.637451 12.6377V2.1377C0.637451 1.73987 0.795486 1.35834 1.07679 1.07704C1.3581 0.795731 1.73963 0.637695 2.13745 0.637695H5.88745L7.38745 2.8877H14.1375C14.5353 2.8877 14.9168 3.04573 15.1981 3.32704C15.4794 3.60834 15.6375 3.98987 15.6375 4.3877V12.6377Z" stroke="currentColor" stroke-width="1.275" stroke-linecap="round" stroke-linejoin="round"/>
12025
+ </svg>
12026
+ </ng-template>
12027
+
12028
+ <ng-template #unorganizedIconTpl>
12029
+ <svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="cqa-flex-shrink-0">
12030
+ <path d="M14.6875 5.5V12.5C14.6875 13.3 14.0375 14 13.1875 14H3.8125C2.9625 14 2.3125 13.3 2.3125 12.5V5.5M14.6875 5.5L12.7875 1.7C12.5375 1.2 12.0875 1 11.5875 1H5.4125C4.9125 1 4.4625 1.2 4.2125 1.7L2.3125 5.5M14.6875 5.5H2.3125M6.1875 8.5H10.8125" stroke="currentColor" stroke-width="1.275" stroke-linecap="round" stroke-linejoin="round"/>
12031
+ </svg>
12032
+ </ng-template>
12033
+
12034
+ <div class="cqa-flex cqa-flex-col cqa-border-solid cqa-border cqa-border-[#E2E2E3] cqa-rounded-[10px] cqa-py-2 cqa-w-full cqa-overflow-y-auto cqa-bg-white cqa-scrollbar-thin" [style.height]="pickerHeight">
12035
+ <div
12036
+ role="button"
12037
+ tabindex="0"
12038
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-px-4 cqa-py-2 cqa-cursor-pointer cqa-transition-colors cqa-text-sm"
12039
+ [ngClass]="isPicked(null) ? 'cqa-bg-indigo-50 cqa-text-indigo-700' : 'cqa-text-neutral-800 hover:cqa-bg-neutral-50'"
12040
+ [class.cqa-opacity-40]="isUnorganizedDisabled"
12041
+ [class.cqa-cursor-not-allowed]="isUnorganizedDisabled"
12042
+ [attr.aria-disabled]="isUnorganizedDisabled || null"
12043
+ (click)="!isUnorganizedDisabled && pick(null)"
12044
+ (keydown.enter)="!isUnorganizedDisabled && pick(null)"
12045
+ (keydown.space)="$event.preventDefault(); !isUnorganizedDisabled && pick(null)"
12046
+ >
12047
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
12048
+ <ng-container *ngTemplateOutlet="unorganizedIconTpl"></ng-container>
12049
+ <span>{{ labels.moveDialogRoot }}</span>
12050
+ </div>
12051
+
12052
+ <ng-container *ngFor="let row of flatRows; trackBy: trackById">
12053
+ <div
12054
+ role="button"
12055
+ tabindex="0"
12056
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-py-2 cqa-pr-4 cqa-cursor-pointer cqa-transition-colors cqa-text-sm"
12057
+ [ngClass]="isPicked(row.id) ? 'cqa-bg-indigo-50 cqa-text-indigo-700' : 'cqa-text-neutral-800 hover:cqa-bg-neutral-50'"
12058
+ [class.cqa-opacity-40]="row.disabled"
12059
+ [class.cqa-cursor-not-allowed]="row.disabled"
12060
+ [style.paddingLeft.px]="16 + row.depth * 24"
12061
+ (click)="!row.disabled && pick(row.id)"
12062
+ (keydown.enter)="!row.disabled && pick(row.id)"
12063
+ (keydown.space)="!row.disabled && $event.preventDefault(); !row.disabled && pick(row.id)"
12064
+ >
12065
+ <button
12066
+ *ngIf="row.hasChildren; else chevronPlaceholder"
12067
+ type="button"
12068
+ class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-w-5 cqa-h-5 cqa-flex-shrink-0 cqa-rounded cqa-text-neutral-600 hover:cqa-bg-neutral-100 hover:cqa-text-neutral-900"
12069
+ [attr.aria-label]="row.expanded ? 'Collapse ' + row.name : 'Expand ' + row.name"
12070
+ (click)="toggleExpanded(row.id!, $event)"
12071
+ >
12072
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
12073
+ [class.cqa-rotate-90]="row.expanded" style="transition: transform 120ms ease;">
12074
+ <path d="M5 3L9 7L5 11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
12075
+ </svg>
12076
+ </button>
12077
+ <ng-template #chevronPlaceholder>
12078
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
12079
+ </ng-template>
12080
+
12081
+ <ng-container *ngTemplateOutlet="folderIconTpl"></ng-container>
12082
+ <span class="cqa-truncate">{{ row.name }}</span>
12083
+ </div>
12084
+
12085
+ <div
12086
+ *ngIf="row.showLoadingPlaceholder"
12087
+ class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-py-2 cqa-pr-4 cqa-text-sm cqa-text-neutral-500 cqa-italic"
12088
+ [style.paddingLeft.px]="16 + (row.depth + 1) * 24"
12089
+ >
12090
+ <span class="cqa-inline-block cqa-w-5 cqa-h-5 cqa-flex-shrink-0"></span>
12091
+ <span>Loading…</span>
12092
+ </div>
12093
+ </ng-container>
12094
+ </div>
11848
12095
  </div>
11849
12096
  `, host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [] }]
11850
12097
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { folders: [{
@@ -11871,6 +12118,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
11871
12118
  type: Output
11872
12119
  }], cancelled: [{
11873
12120
  type: Output
12121
+ }], folderChildrenRequested: [{
12122
+ type: Output
11874
12123
  }], currentFieldFocus: [{
11875
12124
  type: Output
11876
12125
  }], currentFieldBlur: [{