@flusys/ng-ui 6.0.1 → 6.1.0

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.
@@ -10118,6 +10118,113 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
10118
10118
  template: `<div [class]="'flex flex-col h-full ' + styleClass()" [style]="style()"><ng-content /></div>`,
10119
10119
  }]
10120
10120
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }] } });
10121
+ // ─── Tab — individual clickable tab button ────────────────────────────────────
10122
+ // Declared before TabListComponent: its content-query predicate below must
10123
+ // reference an already-declared class, otherwise the compiled query metadata
10124
+ // resolves the predicate as undefined.
10125
+ class TabComponent {
10126
+ ctx = inject(TabsContext);
10127
+ buttonRef = viewChild('btn', /* @ts-ignore */
10128
+ ...(ngDevMode ? [{ debugName: "buttonRef" }] : /* istanbul ignore next */ []));
10129
+ value = input('', /* @ts-ignore */
10130
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
10131
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
10132
+ closable = input(false, { ...(ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
10133
+ isActive = computed(() => this.ctx.active() === this.value(), /* @ts-ignore */
10134
+ ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
10135
+ onClose = output();
10136
+ triggerId = computed(() => `f-tab-trigger-${this.value()}`, /* @ts-ignore */
10137
+ ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
10138
+ panelId = computed(() => `f-tab-panel-${this.value()}`, /* @ts-ignore */
10139
+ ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
10140
+ hostClass = computed(() => {
10141
+ const base = 'inline-flex items-stretch border-b-[2.5px] -mb-px transition-all duration-[var(--f-transition-duration)]';
10142
+ return this.isActive() ? `${base} border-primary` : `${base} border-transparent hover:border-(--f-content-border-color)`;
10143
+ }, /* @ts-ignore */
10144
+ ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
10145
+ tabClass = computed(() => {
10146
+ const base = 'px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-all duration-[var(--f-transition-duration)] inline-flex items-center gap-1.5 focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-40 select-none';
10147
+ return this.isActive()
10148
+ ? `${base} text-primary`
10149
+ : `${base} text-(--f-text-muted-color) hover:text-(--f-text-hover-color) hover:bg-(--f-content-hover-background)/60`;
10150
+ }, /* @ts-ignore */
10151
+ ...(ngDevMode ? [{ debugName: "tabClass" }] : /* istanbul ignore next */ []));
10152
+ buttonEl() {
10153
+ return this.buttonRef()?.nativeElement;
10154
+ }
10155
+ focusButton() {
10156
+ this.buttonRef()?.nativeElement.focus();
10157
+ }
10158
+ onClick() {
10159
+ if (!this.disabled())
10160
+ this.ctx.setActive(this.value());
10161
+ }
10162
+ onCloseClick(e) {
10163
+ e.stopPropagation();
10164
+ this.onClose.emit({ originalEvent: e, value: this.value() });
10165
+ }
10166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: TabComponent, isStandalone: true, selector: "f-tab", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClose: "onClose" }, host: { properties: { "class": "hostClass()" } }, viewQueries: [{ propertyName: "buttonRef", first: true, predicate: ["btn"], descendants: true, isSignal: true }], ngImport: i0, template: `
10168
+ <button
10169
+ #btn
10170
+ type="button"
10171
+ role="tab"
10172
+ [class]="tabClass()"
10173
+ [disabled]="disabled()"
10174
+ [id]="triggerId()"
10175
+ [attr.aria-controls]="panelId()"
10176
+ [attr.aria-selected]="isActive() ? 'true' : 'false'"
10177
+ [attr.tabindex]="isActive() ? 0 : -1"
10178
+ (click)="onClick()"
10179
+ >
10180
+ <ng-content />
10181
+ </button>
10182
+ @if (closable()) {
10183
+ <button
10184
+ type="button"
10185
+ aria-label="Close"
10186
+ class="w-4 h-4 my-auto mr-2 flex items-center justify-center rounded-full hover:bg-(--f-content-border-color) text-(--f-text-muted-color) hover:text-(--f-text-hover-color) transition-all duration-[var(--f-transition-duration)] cursor-pointer focus:outline-none focus-visible:ring-focus"
10187
+ (click)="onCloseClick($event)"
10188
+ >
10189
+ <ui-icon name="times" class="text-[9px]"></ui-icon>
10190
+ </button>
10191
+ }
10192
+ `, isInline: true, dependencies: [{ kind: "component", type: UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }] });
10193
+ }
10194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TabComponent, decorators: [{
10195
+ type: Component,
10196
+ args: [{
10197
+ selector: 'f-tab',
10198
+ imports: [UiIconComponent],
10199
+ host: { '[class]': 'hostClass()' },
10200
+ template: `
10201
+ <button
10202
+ #btn
10203
+ type="button"
10204
+ role="tab"
10205
+ [class]="tabClass()"
10206
+ [disabled]="disabled()"
10207
+ [id]="triggerId()"
10208
+ [attr.aria-controls]="panelId()"
10209
+ [attr.aria-selected]="isActive() ? 'true' : 'false'"
10210
+ [attr.tabindex]="isActive() ? 0 : -1"
10211
+ (click)="onClick()"
10212
+ >
10213
+ <ng-content />
10214
+ </button>
10215
+ @if (closable()) {
10216
+ <button
10217
+ type="button"
10218
+ aria-label="Close"
10219
+ class="w-4 h-4 my-auto mr-2 flex items-center justify-center rounded-full hover:bg-(--f-content-border-color) text-(--f-text-muted-color) hover:text-(--f-text-hover-color) transition-all duration-[var(--f-transition-duration)] cursor-pointer focus:outline-none focus-visible:ring-focus"
10220
+ (click)="onCloseClick($event)"
10221
+ >
10222
+ <ui-icon name="times" class="text-[9px]"></ui-icon>
10223
+ </button>
10224
+ }
10225
+ `,
10226
+ }]
10227
+ }], propDecorators: { buttonRef: [{ type: i0.ViewChild, args: ['btn', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }] } });
10121
10228
  // ─── TabList — wraps tab buttons, with optional scroll navigators ────────────
10122
10229
  class TabListComponent {
10123
10230
  ctx = inject(TabsContext);
@@ -10258,110 +10365,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
10258
10365
  `,
10259
10366
  }]
10260
10367
  }], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TabComponent), { isSignal: true }] }], scrollContainerRef: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }] } });
10261
- // ─── Tab — individual clickable tab button ────────────────────────────────────
10262
- class TabComponent {
10263
- ctx = inject(TabsContext);
10264
- buttonRef = viewChild('btn', /* @ts-ignore */
10265
- ...(ngDevMode ? [{ debugName: "buttonRef" }] : /* istanbul ignore next */ []));
10266
- value = input('', /* @ts-ignore */
10267
- ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
10268
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
10269
- closable = input(false, { ...(ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
10270
- isActive = computed(() => this.ctx.active() === this.value(), /* @ts-ignore */
10271
- ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
10272
- onClose = output();
10273
- triggerId = computed(() => `f-tab-trigger-${this.value()}`, /* @ts-ignore */
10274
- ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
10275
- panelId = computed(() => `f-tab-panel-${this.value()}`, /* @ts-ignore */
10276
- ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
10277
- hostClass = computed(() => {
10278
- const base = 'inline-flex items-stretch border-b-[2.5px] -mb-px transition-all duration-[var(--f-transition-duration)]';
10279
- return this.isActive() ? `${base} border-primary` : `${base} border-transparent hover:border-(--f-content-border-color)`;
10280
- }, /* @ts-ignore */
10281
- ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
10282
- tabClass = computed(() => {
10283
- const base = 'px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-all duration-[var(--f-transition-duration)] inline-flex items-center gap-1.5 focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-40 select-none';
10284
- return this.isActive()
10285
- ? `${base} text-primary`
10286
- : `${base} text-(--f-text-muted-color) hover:text-(--f-text-hover-color) hover:bg-(--f-content-hover-background)/60`;
10287
- }, /* @ts-ignore */
10288
- ...(ngDevMode ? [{ debugName: "tabClass" }] : /* istanbul ignore next */ []));
10289
- buttonEl() {
10290
- return this.buttonRef()?.nativeElement;
10291
- }
10292
- focusButton() {
10293
- this.buttonRef()?.nativeElement.focus();
10294
- }
10295
- onClick() {
10296
- if (!this.disabled())
10297
- this.ctx.setActive(this.value());
10298
- }
10299
- onCloseClick(e) {
10300
- e.stopPropagation();
10301
- this.onClose.emit({ originalEvent: e, value: this.value() });
10302
- }
10303
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10304
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: TabComponent, isStandalone: true, selector: "f-tab", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClose: "onClose" }, host: { properties: { "class": "hostClass()" } }, viewQueries: [{ propertyName: "buttonRef", first: true, predicate: ["btn"], descendants: true, isSignal: true }], ngImport: i0, template: `
10305
- <button
10306
- #btn
10307
- type="button"
10308
- role="tab"
10309
- [class]="tabClass()"
10310
- [disabled]="disabled()"
10311
- [id]="triggerId()"
10312
- [attr.aria-controls]="panelId()"
10313
- [attr.aria-selected]="isActive() ? 'true' : 'false'"
10314
- [attr.tabindex]="isActive() ? 0 : -1"
10315
- (click)="onClick()"
10316
- >
10317
- <ng-content />
10318
- </button>
10319
- @if (closable()) {
10320
- <button
10321
- type="button"
10322
- aria-label="Close"
10323
- class="w-4 h-4 my-auto mr-2 flex items-center justify-center rounded-full hover:bg-(--f-content-border-color) text-(--f-text-muted-color) hover:text-(--f-text-hover-color) transition-all duration-[var(--f-transition-duration)] cursor-pointer focus:outline-none focus-visible:ring-focus"
10324
- (click)="onCloseClick($event)"
10325
- >
10326
- <ui-icon name="times" class="text-[9px]"></ui-icon>
10327
- </button>
10328
- }
10329
- `, isInline: true, dependencies: [{ kind: "component", type: UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }] });
10330
- }
10331
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TabComponent, decorators: [{
10332
- type: Component,
10333
- args: [{
10334
- selector: 'f-tab',
10335
- imports: [UiIconComponent],
10336
- host: { '[class]': 'hostClass()' },
10337
- template: `
10338
- <button
10339
- #btn
10340
- type="button"
10341
- role="tab"
10342
- [class]="tabClass()"
10343
- [disabled]="disabled()"
10344
- [id]="triggerId()"
10345
- [attr.aria-controls]="panelId()"
10346
- [attr.aria-selected]="isActive() ? 'true' : 'false'"
10347
- [attr.tabindex]="isActive() ? 0 : -1"
10348
- (click)="onClick()"
10349
- >
10350
- <ng-content />
10351
- </button>
10352
- @if (closable()) {
10353
- <button
10354
- type="button"
10355
- aria-label="Close"
10356
- class="w-4 h-4 my-auto mr-2 flex items-center justify-center rounded-full hover:bg-(--f-content-border-color) text-(--f-text-muted-color) hover:text-(--f-text-hover-color) transition-all duration-[var(--f-transition-duration)] cursor-pointer focus:outline-none focus-visible:ring-focus"
10357
- (click)="onCloseClick($event)"
10358
- >
10359
- <ui-icon name="times" class="text-[9px]"></ui-icon>
10360
- </button>
10361
- }
10362
- `,
10363
- }]
10364
- }], propDecorators: { buttonRef: [{ type: i0.ViewChild, args: ['btn', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }] } });
10365
10368
  // ─── TabPanels — wrapper around individual panels ─────────────────────────────
10366
10369
  class TabPanelsComponent {
10367
10370
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: TabPanelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -10468,6 +10471,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
10468
10471
  type: Injectable
10469
10472
  }] });
10470
10473
 
10474
+ // ─── AccordionHeader — reads panel context, triggers toggle ───────────────────
10475
+ // Declared before AccordionComponent: its content-query predicate below must
10476
+ // reference an already-declared class, otherwise the compiled query metadata
10477
+ // resolves the predicate as undefined.
10478
+ class AccordionHeaderComponent {
10479
+ panelCtx = inject(AccordionPanelCtx);
10480
+ accordionCtx = inject(AccordionContext, { optional: true });
10481
+ buttonRef = viewChild('btn', /* @ts-ignore */
10482
+ ...(ngDevMode ? [{ debugName: "buttonRef" }] : /* istanbul ignore next */ []));
10483
+ disabled = computed(() => this.panelCtx.disabled(), /* @ts-ignore */
10484
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
10485
+ headerId = computed(() => `${this.accordionCtx?.id ?? 'f-accordion'}-header-${this.panelCtx.value()}`, /* @ts-ignore */
10486
+ ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
10487
+ contentId = computed(() => `${this.accordionCtx?.id ?? 'f-accordion'}-content-${this.panelCtx.value()}`, /* @ts-ignore */
10488
+ ...(ngDevMode ? [{ debugName: "contentId" }] : /* istanbul ignore next */ []));
10489
+ buttonEl() {
10490
+ return this.buttonRef()?.nativeElement;
10491
+ }
10492
+ focusButton() {
10493
+ this.buttonRef()?.nativeElement.focus();
10494
+ }
10495
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AccordionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10496
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: AccordionHeaderComponent, isStandalone: true, selector: "f-accordion-header", viewQueries: [{ propertyName: "buttonRef", first: true, predicate: ["btn"], descendants: true, isSignal: true }], ngImport: i0, template: `
10497
+ <button
10498
+ #btn
10499
+ type="button"
10500
+ class="w-full flex items-center justify-between px-5 py-3.5 text-sm font-semibold text-(--f-text-color) hover:bg-(--f-content-hover-background)/80 transition-all duration-[var(--f-transition-duration)] text-left select-none focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
10501
+ [id]="headerId()"
10502
+ [disabled]="panelCtx.disabled()"
10503
+ [attr.aria-expanded]="panelCtx.open()"
10504
+ [attr.aria-controls]="contentId()"
10505
+ (click)="panelCtx.toggle()"
10506
+ >
10507
+ <span class="flex-1 tracking-tight"><ng-content /></span>
10508
+ <ui-icon
10509
+ name="chevron-down"
10510
+ class="text-xs text-(--f-text-muted-color) ml-3 shrink-0 transition-transform duration-200"
10511
+ [class.rotate-180]="panelCtx.open()"
10512
+ ></ui-icon>
10513
+ </button>
10514
+ `, isInline: true, dependencies: [{ kind: "component", type: UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }] });
10515
+ }
10516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AccordionHeaderComponent, decorators: [{
10517
+ type: Component,
10518
+ args: [{
10519
+ selector: 'f-accordion-header',
10520
+ imports: [UiIconComponent],
10521
+ template: `
10522
+ <button
10523
+ #btn
10524
+ type="button"
10525
+ class="w-full flex items-center justify-between px-5 py-3.5 text-sm font-semibold text-(--f-text-color) hover:bg-(--f-content-hover-background)/80 transition-all duration-[var(--f-transition-duration)] text-left select-none focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
10526
+ [id]="headerId()"
10527
+ [disabled]="panelCtx.disabled()"
10528
+ [attr.aria-expanded]="panelCtx.open()"
10529
+ [attr.aria-controls]="contentId()"
10530
+ (click)="panelCtx.toggle()"
10531
+ >
10532
+ <span class="flex-1 tracking-tight"><ng-content /></span>
10533
+ <ui-icon
10534
+ name="chevron-down"
10535
+ class="text-xs text-(--f-text-muted-color) ml-3 shrink-0 transition-transform duration-200"
10536
+ [class.rotate-180]="panelCtx.open()"
10537
+ ></ui-icon>
10538
+ </button>
10539
+ `,
10540
+ }]
10541
+ }], propDecorators: { buttonRef: [{ type: i0.ViewChild, args: ['btn', { isSignal: true }] }] } });
10471
10542
  // ─── Accordion root — provides context ────────────────────────────────────────
10472
10543
  class AccordionComponent {
10473
10544
  multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -10482,8 +10553,7 @@ class AccordionComponent {
10482
10553
  onTabChange = output();
10483
10554
  onTabClose = output();
10484
10555
  ctx = inject(AccordionContext);
10485
- headers = contentChildren(AccordionHeaderComponent, /* @ts-ignore */
10486
- ...(ngDevMode ? [{ debugName: "headers" }] : /* istanbul ignore next */ []));
10556
+ headers = contentChildren(AccordionHeaderComponent, { ...(ngDevMode ? { debugName: "headers" } : /* istanbul ignore next */ {}), descendants: true });
10487
10557
  rootClass = computed(() => `border border-(--f-content-border-color) rounded-lg overflow-hidden shadow-sm bg-(--f-content-background) ${this.styleClass()}`, /* @ts-ignore */
10488
10558
  ...(ngDevMode ? [{ debugName: "rootClass" }] : /* istanbul ignore next */ []));
10489
10559
  constructor() {
@@ -10547,7 +10617,7 @@ class AccordionComponent {
10547
10617
  headers[nextIndex].focusButton();
10548
10618
  }
10549
10619
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10550
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: AccordionComponent, isStandalone: true, selector: "f-accordion", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onOpen: "onOpen", onClose: "onClose", onTabChange: "onTabChange", onTabClose: "onTabClose" }, host: { classAttribute: "block" }, providers: [AccordionContext], queries: [{ propertyName: "headers", predicate: AccordionHeaderComponent, isSignal: true }], ngImport: i0, template: `<div
10620
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: AccordionComponent, isStandalone: true, selector: "f-accordion", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onOpen: "onOpen", onClose: "onClose", onTabChange: "onTabChange", onTabClose: "onTabClose" }, host: { classAttribute: "block" }, providers: [AccordionContext], queries: [{ propertyName: "headers", predicate: AccordionHeaderComponent, descendants: true, isSignal: true }], ngImport: i0, template: `<div
10551
10621
  [class]="rootClass()"
10552
10622
  [style]="style()"
10553
10623
  (keydown)="onKeydown($event)"
@@ -10571,7 +10641,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
10571
10641
  <ng-content />
10572
10642
  </div>`,
10573
10643
  }]
10574
- }], ctorParameters: () => [], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onOpen: [{ type: i0.Output, args: ["onOpen"] }], onClose: [{ type: i0.Output, args: ["onClose"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }], onTabClose: [{ type: i0.Output, args: ["onTabClose"] }], headers: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AccordionHeaderComponent), { isSignal: true }] }] } });
10644
+ }], ctorParameters: () => [], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onOpen: [{ type: i0.Output, args: ["onOpen"] }], onClose: [{ type: i0.Output, args: ["onClose"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }], onTabClose: [{ type: i0.Output, args: ["onTabClose"] }], headers: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AccordionHeaderComponent), { ...{ descendants: true }, isSignal: true }] }] } });
10575
10645
  // ─── AccordionPanel — provides panel-level context ────────────────────────────
10576
10646
  class AccordionPanelComponent {
10577
10647
  value = input('', /* @ts-ignore */
@@ -10620,71 +10690,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
10620
10690
  </div>`,
10621
10691
  }]
10622
10692
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
10623
- // ─── AccordionHeader — reads panel context, triggers toggle ───────────────────
10624
- class AccordionHeaderComponent {
10625
- panelCtx = inject(AccordionPanelCtx);
10626
- accordionCtx = inject(AccordionContext, { optional: true });
10627
- buttonRef = viewChild('btn', /* @ts-ignore */
10628
- ...(ngDevMode ? [{ debugName: "buttonRef" }] : /* istanbul ignore next */ []));
10629
- disabled = computed(() => this.panelCtx.disabled(), /* @ts-ignore */
10630
- ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
10631
- headerId = computed(() => `${this.accordionCtx?.id ?? 'f-accordion'}-header-${this.panelCtx.value()}`, /* @ts-ignore */
10632
- ...(ngDevMode ? [{ debugName: "headerId" }] : /* istanbul ignore next */ []));
10633
- contentId = computed(() => `${this.accordionCtx?.id ?? 'f-accordion'}-content-${this.panelCtx.value()}`, /* @ts-ignore */
10634
- ...(ngDevMode ? [{ debugName: "contentId" }] : /* istanbul ignore next */ []));
10635
- buttonEl() {
10636
- return this.buttonRef()?.nativeElement;
10637
- }
10638
- focusButton() {
10639
- this.buttonRef()?.nativeElement.focus();
10640
- }
10641
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AccordionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10642
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", type: AccordionHeaderComponent, isStandalone: true, selector: "f-accordion-header", viewQueries: [{ propertyName: "buttonRef", first: true, predicate: ["btn"], descendants: true, isSignal: true }], ngImport: i0, template: `
10643
- <button
10644
- #btn
10645
- type="button"
10646
- class="w-full flex items-center justify-between px-5 py-3.5 text-sm font-semibold text-(--f-text-color) hover:bg-(--f-content-hover-background)/80 transition-all duration-[var(--f-transition-duration)] text-left select-none focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
10647
- [id]="headerId()"
10648
- [disabled]="panelCtx.disabled()"
10649
- [attr.aria-expanded]="panelCtx.open()"
10650
- [attr.aria-controls]="contentId()"
10651
- (click)="panelCtx.toggle()"
10652
- >
10653
- <span class="flex-1 tracking-tight"><ng-content /></span>
10654
- <ui-icon
10655
- name="chevron-down"
10656
- class="text-xs text-(--f-text-muted-color) ml-3 shrink-0 transition-transform duration-200"
10657
- [class.rotate-180]="panelCtx.open()"
10658
- ></ui-icon>
10659
- </button>
10660
- `, isInline: true, dependencies: [{ kind: "component", type: UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }] });
10661
- }
10662
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: AccordionHeaderComponent, decorators: [{
10663
- type: Component,
10664
- args: [{
10665
- selector: 'f-accordion-header',
10666
- imports: [UiIconComponent],
10667
- template: `
10668
- <button
10669
- #btn
10670
- type="button"
10671
- class="w-full flex items-center justify-between px-5 py-3.5 text-sm font-semibold text-(--f-text-color) hover:bg-(--f-content-hover-background)/80 transition-all duration-[var(--f-transition-duration)] text-left select-none focus:outline-none focus-visible:ring-focus cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
10672
- [id]="headerId()"
10673
- [disabled]="panelCtx.disabled()"
10674
- [attr.aria-expanded]="panelCtx.open()"
10675
- [attr.aria-controls]="contentId()"
10676
- (click)="panelCtx.toggle()"
10677
- >
10678
- <span class="flex-1 tracking-tight"><ng-content /></span>
10679
- <ui-icon
10680
- name="chevron-down"
10681
- class="text-xs text-(--f-text-muted-color) ml-3 shrink-0 transition-transform duration-200"
10682
- [class.rotate-180]="panelCtx.open()"
10683
- ></ui-icon>
10684
- </button>
10685
- `,
10686
- }]
10687
- }], propDecorators: { buttonRef: [{ type: i0.ViewChild, args: ['btn', { isSignal: true }] }] } });
10688
10693
  // ─── AccordionContent — shows/hides via panel context ─────────────────────────
10689
10694
  class AccordionContentComponent {
10690
10695
  panelCtx = inject(AccordionPanelCtx);
@@ -15202,6 +15207,14 @@ class TreeTableComponent {
15202
15207
  return { nodes: out, matchedKeys };
15203
15208
  }
15204
15209
  sortNodesRecursive(nodes) {
15210
+ // Skip cloning entirely when there's nothing to sort — spreading nodes
15211
+ // here (even with no active sort) mints new object identities, which
15212
+ // desyncs the __uid assigned by assignKey() from the original nodes
15213
+ // held externally (e.g. by expandAll()/toggleRow() callers), silently
15214
+ // breaking expand/collapse state.
15215
+ const hasActiveSort = this.sortMode() === 'multiple' ? this.multiSortMeta().length > 0 : !!this.sortField();
15216
+ if (!hasActiveSort)
15217
+ return nodes;
15205
15218
  const withSortedChildren = nodes.map((n) => n.children?.length ? { ...n, children: this.sortNodesRecursive(n.children) } : n);
15206
15219
  if (this.sortMode() === 'multiple') {
15207
15220
  const metas = this.multiSortMeta();
@@ -26021,15 +26034,25 @@ class TerminalComponent {
26021
26034
  _current = signal('', /* @ts-ignore */
26022
26035
  ...(ngDevMode ? [{ debugName: "_current" }] : /* istanbul ignore next */ []));
26023
26036
  current = this._current.asReadonly();
26024
- _history = signal(this.welcomeMessage() ? [{ type: 'response', text: this.welcomeMessage() }] : [], /* @ts-ignore */
26037
+ _history = signal([], /* @ts-ignore */
26025
26038
  ...(ngDevMode ? [{ debugName: "_history" }] : /* istanbul ignore next */ []));
26026
26039
  history = this._history.asReadonly();
26027
26040
  _commandHistory = signal([], /* @ts-ignore */
26028
26041
  ...(ngDevMode ? [{ debugName: "_commandHistory" }] : /* istanbul ignore next */ []));
26029
26042
  historyIndex = -1;
26043
+ welcomeMessageShown = false;
26030
26044
  containerClass = computed(() => `bg-surface-950 text-surface-0 rounded-lg font-mono text-sm p-3 overflow-y-auto ${this.styleClass()}`, /* @ts-ignore */
26031
26045
  ...(ngDevMode ? [{ debugName: "containerClass" }] : /* istanbul ignore next */ []));
26032
26046
  constructor() {
26047
+ effect(() => {
26048
+ const welcome = this.welcomeMessage();
26049
+ // input() isn't populated yet at field-initializer time, so seed the
26050
+ // welcome message here instead, once, the first time it becomes available.
26051
+ if (welcome && !this.welcomeMessageShown) {
26052
+ this.welcomeMessageShown = true;
26053
+ this._history.update(h => [{ type: 'response', text: welcome }, ...h]);
26054
+ }
26055
+ });
26033
26056
  effect(() => {
26034
26057
  this.history();
26035
26058
  const el = this.scrollContainer()?.nativeElement;