ngx-dev-toolbar 1.0.4 → 2.0.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.
Files changed (27) hide show
  1. package/components/icons/bolt-icon.component.d.ts +6 -0
  2. package/components/icons/filter-icon.component.d.ts +6 -0
  3. package/components/icons/icon.models.d.ts +1 -1
  4. package/components/icons/lock-icon.component.d.ts +6 -0
  5. package/components/select/select.component.d.ts +1 -1
  6. package/components/window/window.component.d.ts +1 -1
  7. package/dev-toolbar-state.service.d.ts +1 -1
  8. package/dev-toolbar.component.d.ts +3 -2
  9. package/fesm2022/ngx-dev-toolbar.mjs +2074 -139
  10. package/fesm2022/ngx-dev-toolbar.mjs.map +1 -1
  11. package/index.d.ts +10 -0
  12. package/models/dev-toolbar-config.interface.d.ts +31 -0
  13. package/package.json +2 -2
  14. package/tools/app-features-tool/app-features-internal.service.d.ts +102 -0
  15. package/tools/app-features-tool/app-features-tool.component.d.ts +61 -0
  16. package/tools/app-features-tool/app-features.models.d.ts +109 -0
  17. package/tools/app-features-tool/app-features.service.d.ts +151 -0
  18. package/tools/feature-flags-tool/feature-flags-internal.service.d.ts +15 -0
  19. package/tools/language-tool/language-internal.service.d.ts +10 -0
  20. package/tools/permissions-tool/permissions-internal.service.d.ts +34 -0
  21. package/tools/permissions-tool/permissions-tool.component.d.ts +27 -0
  22. package/tools/permissions-tool/permissions.models.d.ts +34 -0
  23. package/tools/permissions-tool/permissions.service.d.ts +87 -0
  24. package/tools/presets-tool/presets-internal.service.d.ts +57 -0
  25. package/tools/presets-tool/presets-tool.component.d.ts +33 -0
  26. package/tools/presets-tool/presets.models.d.ts +24 -0
  27. package/tools/presets-tool/presets.service.d.ts +51 -0
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, Component, ChangeDetectionStrategy, input, inject, ElementRef, output, ViewChild, ContentChild, model, DestroyRef, isDevMode } from '@angular/core';
2
+ import { signal, computed, Injectable, Component, ChangeDetectionStrategy, input, inject, ElementRef, output, ViewEncapsulation, ViewChild, ContentChild, model, DestroyRef } from '@angular/core';
3
3
  import { trigger, state, style, transition, animate } from '@angular/animations';
4
4
  import * as i1 from '@angular/cdk/overlay';
5
5
  import { CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
@@ -158,6 +158,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
158
158
  }]
159
159
  }] });
160
160
 
161
+ class BoltIconComponent {
162
+ constructor() {
163
+ this.fill = input('#FFFF');
164
+ }
165
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: BoltIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
166
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.5", type: BoltIconComponent, isStandalone: true, selector: "ndt-bolt-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
167
+ <svg
168
+ [attr.fill]="fill()"
169
+ xmlns="http://www.w3.org/2000/svg"
170
+ width="24"
171
+ height="24"
172
+ viewBox="0 0 256 256"
173
+ >
174
+ <path
175
+ d="M160,16,144,96H208l-96,144,16-80H64Z"
176
+ opacity="0.2"
177
+ ></path>
178
+ <path
179
+ d="M215.79,118.17a8,8,0,0,0-5-5.66L153.18,90.9l14.66-73.33a8,8,0,0,0-13.69-7l-112,120a8,8,0,0,0,3,13l57.63,21.61L88.16,238.43a8,8,0,0,0,13.69,7l112-120A8,8,0,0,0,215.79,118.17ZM109.37,214l10.47-52.38a8,8,0,0,0-5-9.06L62,132.71l84.62-90.66L136.16,94.43a8,8,0,0,0,5,9.06l52.8,19.8Z"
180
+ ></path>
181
+ </svg>
182
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
183
+ }
184
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: BoltIconComponent, decorators: [{
185
+ type: Component,
186
+ args: [{
187
+ selector: 'ndt-bolt-icon',
188
+ standalone: true,
189
+ changeDetection: ChangeDetectionStrategy.OnPush,
190
+ template: `
191
+ <svg
192
+ [attr.fill]="fill()"
193
+ xmlns="http://www.w3.org/2000/svg"
194
+ width="24"
195
+ height="24"
196
+ viewBox="0 0 256 256"
197
+ >
198
+ <path
199
+ d="M160,16,144,96H208l-96,144,16-80H64Z"
200
+ opacity="0.2"
201
+ ></path>
202
+ <path
203
+ d="M215.79,118.17a8,8,0,0,0-5-5.66L153.18,90.9l14.66-73.33a8,8,0,0,0-13.69-7l-112,120a8,8,0,0,0,3,13l57.63,21.61L88.16,238.43a8,8,0,0,0,13.69,7l112-120A8,8,0,0,0,215.79,118.17ZM109.37,214l10.47-52.38a8,8,0,0,0-5-9.06L62,132.71l84.62-90.66L136.16,94.43a8,8,0,0,0,5,9.06l52.8,19.8Z"
204
+ ></path>
205
+ </svg>
206
+ `,
207
+ }]
208
+ }] });
209
+
161
210
  class BugIconComponent {
162
211
  constructor() {
163
212
  this.fill = input('#FFFF');
@@ -414,6 +463,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
414
463
  }]
415
464
  }] });
416
465
 
466
+ class FilterIconComponent {
467
+ constructor() {
468
+ this.fill = input('#FFFF');
469
+ }
470
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: FilterIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
471
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.5", type: FilterIconComponent, isStandalone: true, selector: "ndt-filter-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
472
+ <svg
473
+ [attr.fill]="fill()"
474
+ xmlns="http://www.w3.org/2000/svg"
475
+ width="24"
476
+ height="24"
477
+ viewBox="0 0 256 256"
478
+ >
479
+ <path
480
+ d="M227.81,66.76l-.08.09L160,139.17v55.49A8,8,0,0,1,156.94,201l-32,21.33A8,8,0,0,1,112,216V139.17L44.27,66.85l-.08-.09A16,16,0,0,1,56,40H200a16,16,0,0,1,11.84,26.76Z"
481
+ opacity="0.2"
482
+ ></path>
483
+ <path
484
+ d="M230.6,49.53A23.94,23.94,0,0,0,200,32H56A24,24,0,0,0,38.15,65.67L104,139.37V216a8,8,0,0,0,11.58,7.16l32-16A8,8,0,0,0,152,200V139.37l65.85-73.7A23.93,23.93,0,0,0,230.6,49.53ZM203.36,54.86a8,8,0,0,1,.07,9.12L136,139.17V196.58l-16,8V139.17L52.57,64A8,8,0,0,1,56,48H200A8,8,0,0,1,203.36,54.86Z"
485
+ ></path>
486
+ </svg>
487
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
488
+ }
489
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: FilterIconComponent, decorators: [{
490
+ type: Component,
491
+ args: [{
492
+ selector: 'ndt-filter-icon',
493
+ standalone: true,
494
+ changeDetection: ChangeDetectionStrategy.OnPush,
495
+ template: `
496
+ <svg
497
+ [attr.fill]="fill()"
498
+ xmlns="http://www.w3.org/2000/svg"
499
+ width="24"
500
+ height="24"
501
+ viewBox="0 0 256 256"
502
+ >
503
+ <path
504
+ d="M227.81,66.76l-.08.09L160,139.17v55.49A8,8,0,0,1,156.94,201l-32,21.33A8,8,0,0,1,112,216V139.17L44.27,66.85l-.08-.09A16,16,0,0,1,56,40H200a16,16,0,0,1,11.84,26.76Z"
505
+ opacity="0.2"
506
+ ></path>
507
+ <path
508
+ d="M230.6,49.53A23.94,23.94,0,0,0,200,32H56A24,24,0,0,0,38.15,65.67L104,139.37V216a8,8,0,0,0,11.58,7.16l32-16A8,8,0,0,0,152,200V139.37l65.85-73.7A23.93,23.93,0,0,0,230.6,49.53ZM203.36,54.86a8,8,0,0,1,.07,9.12L136,139.17V196.58l-16,8V139.17L52.57,64A8,8,0,0,1,56,48H200A8,8,0,0,1,203.36,54.86Z"
509
+ ></path>
510
+ </svg>
511
+ `,
512
+ }]
513
+ }] });
514
+
417
515
  class GaugeIconComponent {
418
516
  constructor() {
419
517
  this.fill = input('#FFFF');
@@ -729,6 +827,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
729
827
  }]
730
828
  }] });
731
829
 
830
+ class LockIconComponent {
831
+ constructor() {
832
+ this.fill = input('#FFFF');
833
+ }
834
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LockIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
835
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.5", type: LockIconComponent, isStandalone: true, selector: "ndt-lock-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
836
+ <svg
837
+ [attr.fill]="fill()"
838
+ xmlns="http://www.w3.org/2000/svg"
839
+ width="24"
840
+ height="24"
841
+ viewBox="0 0 256 256"
842
+ >
843
+ <path
844
+ d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z"
845
+ ></path>
846
+ </svg>
847
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
848
+ }
849
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LockIconComponent, decorators: [{
850
+ type: Component,
851
+ args: [{
852
+ selector: 'ndt-lock-icon',
853
+ standalone: true,
854
+ changeDetection: ChangeDetectionStrategy.OnPush,
855
+ template: `
856
+ <svg
857
+ [attr.fill]="fill()"
858
+ xmlns="http://www.w3.org/2000/svg"
859
+ width="24"
860
+ height="24"
861
+ viewBox="0 0 256 256"
862
+ >
863
+ <path
864
+ d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z"
865
+ ></path>
866
+ </svg>
867
+ `,
868
+ }]
869
+ }] });
870
+
732
871
  class MoonIconComponent {
733
872
  constructor() {
734
873
  this.fill = input('#FFFF');
@@ -1262,6 +1401,8 @@ class DevToolbarIconComponent {
1262
1401
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarIconComponent, isStandalone: true, selector: "ndt-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
1263
1402
  @switch (name()) { @case ('angular') {
1264
1403
  <ndt-angular-icon />
1404
+ } @case ('bolt') {
1405
+ <ndt-bolt-icon [fill]="fill()" />
1265
1406
  } @case ('bug') {
1266
1407
  <ndt-bug-icon [fill]="fill()" />
1267
1408
  } @case ('code') {
@@ -1272,6 +1413,8 @@ class DevToolbarIconComponent {
1272
1413
  <ndt-docs-icon [fill]="fill()" />
1273
1414
  } @case ('export') {
1274
1415
  <ndt-export-icon [fill]="fill()" />
1416
+ } @case ('filter') {
1417
+ <ndt-filter-icon [fill]="fill()" />
1275
1418
  } @case ('gauge') {
1276
1419
  <ndt-gauge-icon [fill]="fill()" />
1277
1420
  } @case ('gear') {
@@ -1286,6 +1429,8 @@ class DevToolbarIconComponent {
1286
1429
  <ndt-lighting-icon [fill]="fill()" />
1287
1430
  } @case ('lightbulb') {
1288
1431
  <ndt-lightbulb-icon [fill]="fill()" />
1432
+ } @case ('lock') {
1433
+ <ndt-lock-icon [fill]="fill()" />
1289
1434
  } @case ('network') {
1290
1435
  <ndt-network-icon [fill]="fill()" />
1291
1436
  } @case ('puzzle') {
@@ -1311,7 +1456,7 @@ class DevToolbarIconComponent {
1311
1456
  } @case ('trash') {
1312
1457
  <ndt-trash-icon [fill]="fill()" />
1313
1458
  } }
1314
- `, isInline: true, dependencies: [{ kind: "component", type: AngularIconComponent, selector: "ndt-angular-icon" }, { kind: "component", type: BugIconComponent, selector: "ndt-bug-icon", inputs: ["fill"] }, { kind: "component", type: CodeIconComponent, selector: "ndt-code-icon", inputs: ["fill"] }, { kind: "component", type: DatabaseIconComponent, selector: "ndt-database-icon", inputs: ["fill"] }, { kind: "component", type: DocsIconComponent, selector: "ndt-docs-icon", inputs: ["fill"] }, { kind: "component", type: DiscordIconComponent, selector: "ndt-discord-icon", inputs: ["fill"] }, { kind: "component", type: ExportIconComponent, selector: "ndt-export-icon", inputs: ["fill"] }, { kind: "component", type: GaugeIconComponent, selector: "ndt-gauge-icon", inputs: ["fill"] }, { kind: "component", type: GearIconComponent, selector: "ndt-gear-icon", inputs: ["fill"] }, { kind: "component", type: GitBranchIconComponent, selector: "ndt-git-branch-icon", inputs: ["fill"] }, { kind: "component", type: ImportIconComponent, selector: "ndt-import-icon", inputs: ["fill"] }, { kind: "component", type: LayoutIconComponent, selector: "ndt-layout-icon", inputs: ["fill"] }, { kind: "component", type: LightbulbIconComponent, selector: "ndt-lightbulb-icon", inputs: ["fill"] }, { kind: "component", type: LightingIconComponent, selector: "ndt-lighting-icon", inputs: ["fill"] }, { kind: "component", type: NetworkIconComponent, selector: "ndt-network-icon", inputs: ["fill"] }, { kind: "component", type: PuzzleIconComponent, selector: "ndt-puzzle-icon", inputs: ["fill"] }, { kind: "component", type: RefreshIconComponent, selector: "ndt-refresh-icon", inputs: ["fill"] }, { kind: "component", type: StarIconComponent, selector: "ndt-star-icon", inputs: ["fill"] }, { kind: "component", type: TerminalIconComponent, selector: "ndt-terminal-icon", inputs: ["fill"] }, { kind: "component", type: ToggleLeftIconComponent, selector: "ndt-toggle-left-icon", inputs: ["fill"] }, { kind: "component", type: UsersIconComponent, selector: "ndt-users-icon", inputs: ["fill"] }, { kind: "component", type: SunIconComponent, selector: "ndt-sun-icon", inputs: ["fill"] }, { kind: "component", type: MoonIconComponent, selector: "ndt-moon-icon", inputs: ["fill"] }, { kind: "component", type: TranslateIconComponent, selector: "ndt-translate-icon", inputs: ["fill"] }, { kind: "component", type: TrashIconComponent, selector: "ndt-trash-icon", inputs: ["fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1459
+ `, isInline: true, dependencies: [{ kind: "component", type: AngularIconComponent, selector: "ndt-angular-icon" }, { kind: "component", type: BoltIconComponent, selector: "ndt-bolt-icon", inputs: ["fill"] }, { kind: "component", type: BugIconComponent, selector: "ndt-bug-icon", inputs: ["fill"] }, { kind: "component", type: CodeIconComponent, selector: "ndt-code-icon", inputs: ["fill"] }, { kind: "component", type: DatabaseIconComponent, selector: "ndt-database-icon", inputs: ["fill"] }, { kind: "component", type: DocsIconComponent, selector: "ndt-docs-icon", inputs: ["fill"] }, { kind: "component", type: DiscordIconComponent, selector: "ndt-discord-icon", inputs: ["fill"] }, { kind: "component", type: ExportIconComponent, selector: "ndt-export-icon", inputs: ["fill"] }, { kind: "component", type: FilterIconComponent, selector: "ndt-filter-icon", inputs: ["fill"] }, { kind: "component", type: GaugeIconComponent, selector: "ndt-gauge-icon", inputs: ["fill"] }, { kind: "component", type: GearIconComponent, selector: "ndt-gear-icon", inputs: ["fill"] }, { kind: "component", type: GitBranchIconComponent, selector: "ndt-git-branch-icon", inputs: ["fill"] }, { kind: "component", type: ImportIconComponent, selector: "ndt-import-icon", inputs: ["fill"] }, { kind: "component", type: LayoutIconComponent, selector: "ndt-layout-icon", inputs: ["fill"] }, { kind: "component", type: LightbulbIconComponent, selector: "ndt-lightbulb-icon", inputs: ["fill"] }, { kind: "component", type: LightingIconComponent, selector: "ndt-lighting-icon", inputs: ["fill"] }, { kind: "component", type: LockIconComponent, selector: "ndt-lock-icon", inputs: ["fill"] }, { kind: "component", type: NetworkIconComponent, selector: "ndt-network-icon", inputs: ["fill"] }, { kind: "component", type: PuzzleIconComponent, selector: "ndt-puzzle-icon", inputs: ["fill"] }, { kind: "component", type: RefreshIconComponent, selector: "ndt-refresh-icon", inputs: ["fill"] }, { kind: "component", type: StarIconComponent, selector: "ndt-star-icon", inputs: ["fill"] }, { kind: "component", type: TerminalIconComponent, selector: "ndt-terminal-icon", inputs: ["fill"] }, { kind: "component", type: ToggleLeftIconComponent, selector: "ndt-toggle-left-icon", inputs: ["fill"] }, { kind: "component", type: UsersIconComponent, selector: "ndt-users-icon", inputs: ["fill"] }, { kind: "component", type: SunIconComponent, selector: "ndt-sun-icon", inputs: ["fill"] }, { kind: "component", type: MoonIconComponent, selector: "ndt-moon-icon", inputs: ["fill"] }, { kind: "component", type: TranslateIconComponent, selector: "ndt-translate-icon", inputs: ["fill"] }, { kind: "component", type: TrashIconComponent, selector: "ndt-trash-icon", inputs: ["fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1315
1460
  }
1316
1461
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarIconComponent, decorators: [{
1317
1462
  type: Component,
@@ -1320,12 +1465,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1320
1465
  standalone: true,
1321
1466
  imports: [
1322
1467
  AngularIconComponent,
1468
+ BoltIconComponent,
1323
1469
  BugIconComponent,
1324
1470
  CodeIconComponent,
1325
1471
  DatabaseIconComponent,
1326
1472
  DocsIconComponent,
1327
1473
  DiscordIconComponent,
1328
1474
  ExportIconComponent,
1475
+ FilterIconComponent,
1329
1476
  GaugeIconComponent,
1330
1477
  GearIconComponent,
1331
1478
  GitBranchIconComponent,
@@ -1333,6 +1480,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1333
1480
  LayoutIconComponent,
1334
1481
  LightbulbIconComponent,
1335
1482
  LightingIconComponent,
1483
+ LockIconComponent,
1336
1484
  NetworkIconComponent,
1337
1485
  PuzzleIconComponent,
1338
1486
  RefreshIconComponent,
@@ -1349,6 +1497,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1349
1497
  template: `
1350
1498
  @switch (name()) { @case ('angular') {
1351
1499
  <ndt-angular-icon />
1500
+ } @case ('bolt') {
1501
+ <ndt-bolt-icon [fill]="fill()" />
1352
1502
  } @case ('bug') {
1353
1503
  <ndt-bug-icon [fill]="fill()" />
1354
1504
  } @case ('code') {
@@ -1359,6 +1509,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1359
1509
  <ndt-docs-icon [fill]="fill()" />
1360
1510
  } @case ('export') {
1361
1511
  <ndt-export-icon [fill]="fill()" />
1512
+ } @case ('filter') {
1513
+ <ndt-filter-icon [fill]="fill()" />
1362
1514
  } @case ('gauge') {
1363
1515
  <ndt-gauge-icon [fill]="fill()" />
1364
1516
  } @case ('gear') {
@@ -1373,6 +1525,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1373
1525
  <ndt-lighting-icon [fill]="fill()" />
1374
1526
  } @case ('lightbulb') {
1375
1527
  <ndt-lightbulb-icon [fill]="fill()" />
1528
+ } @case ('lock') {
1529
+ <ndt-lock-icon [fill]="fill()" />
1376
1530
  } @case ('network') {
1377
1531
  <ndt-network-icon [fill]="fill()" />
1378
1532
  } @case ('puzzle') {
@@ -1464,7 +1618,7 @@ class DevToolbarToolButtonComponent {
1464
1618
  }
1465
1619
  <ng-content />
1466
1620
  </button>
1467
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.tool-button{display:flex;justify-content:center;align-items:center;width:44px;height:40px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:24px;height:24px;display:block;margin:auto}.tool-button__badge{position:absolute;top:-.25rem;right:-.25rem;background-color:var(--ndt-hover-danger);color:var(--ndt-text-primary);border-radius:var(--ndt-border-radius-full);min-width:1rem;height:1rem;font-size:.75rem;display:flex;align-items:center;justify-content:center;padding:.125rem}.tooltip{position:absolute;bottom:calc(100% + 1.2rem);left:50%;transform:translate(-50%);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);padding:.5rem .75rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip)}\n"], animations: [
1621
+ `, isInline: true, styles: [".tool-button{display:flex;justify-content:center;align-items:center;width:44px;height:40px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:24px;height:24px;display:block;margin:auto}.tool-button__badge{position:absolute;top:-.25rem;right:-.25rem;background-color:var(--ndt-hover-danger);color:var(--ndt-text-primary);border-radius:var(--ndt-border-radius-full);min-width:1rem;height:1rem;font-size:.75rem;display:flex;align-items:center;justify-content:center;padding:.125rem}.tooltip{position:absolute;bottom:calc(100% + 1.2rem);left:50%;transform:translate(-50%);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);padding:.5rem .75rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip)}\n"], animations: [
1468
1622
  trigger('tooltipAnimation', [
1469
1623
  state('hidden', style({
1470
1624
  opacity: 0,
@@ -1515,7 +1669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1515
1669
  transition('hidden => visible', [animate('200ms ease-out')]),
1516
1670
  transition('visible => hidden', [animate('150ms ease-in')]),
1517
1671
  ]),
1518
- ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.tool-button{display:flex;justify-content:center;align-items:center;width:44px;height:40px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:24px;height:24px;display:block;margin:auto}.tool-button__badge{position:absolute;top:-.25rem;right:-.25rem;background-color:var(--ndt-hover-danger);color:var(--ndt-text-primary);border-radius:var(--ndt-border-radius-full);min-width:1rem;height:1rem;font-size:.75rem;display:flex;align-items:center;justify-content:center;padding:.125rem}.tooltip{position:absolute;bottom:calc(100% + 1.2rem);left:50%;transform:translate(-50%);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);padding:.5rem .75rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip)}\n"] }]
1672
+ ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [".tool-button{display:flex;justify-content:center;align-items:center;width:44px;height:40px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:24px;height:24px;display:block;margin:auto}.tool-button__badge{position:absolute;top:-.25rem;right:-.25rem;background-color:var(--ndt-hover-danger);color:var(--ndt-text-primary);border-radius:var(--ndt-border-radius-full);min-width:1rem;height:1rem;font-size:.75rem;display:flex;align-items:center;justify-content:center;padding:.125rem}.tooltip{position:absolute;bottom:calc(100% + 1.2rem);left:50%;transform:translate(-50%);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);padding:.5rem .75rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip)}\n"] }]
1519
1673
  }] });
1520
1674
 
1521
1675
  class DevToolbarWindowComponent {
@@ -1575,11 +1729,11 @@ class DevToolbarWindowComponent {
1575
1729
  <ng-content></ng-content>
1576
1730
  </div>
1577
1731
  </div>
1578
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}:host{display:block;width:100%}.window{box-sizing:border-box;display:flex;flex-direction:column;width:100%;height:100%;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-window-padding);font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";color:var(--ndt-text-secondary);z-index:999999999;box-shadow:var(--ndt-shadow-window)}.header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start}.header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm)}.header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:1px 4px;margin-left:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.header__description{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-muted)}.header__content{display:flex;flex-direction:column}.header__controls{display:flex;gap:var(--ndt-spacing-sm)}.content{flex:1;overflow:auto}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md)}.control{background:none;border:none;color:var(--ndt-text-secondary);cursor:pointer;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-md);line-height:1;transition:var(--ndt-transition-smooth)}.control:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.control--close:hover{background:var(--ndt-hover-danger)}\n"] }); }
1732
+ `, isInline: true, styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:block;width:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.window{box-sizing:border-box;display:flex;flex-direction:column;width:100%;height:100%;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-window-padding);font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";color:var(--ndt-text-secondary);z-index:999999999;box-shadow:var(--ndt-shadow-window)}.header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start}.header h1{font-size:var(--ndt-font-size-lg);line-height:1.2;margin:0}.header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm)}.header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:1px 4px;margin-left:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.header__description{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-muted);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;line-height:1.4;margin:0}.header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.header__controls{display:flex;gap:var(--ndt-spacing-sm)}.content{flex:1;overflow:auto}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md)}.control{background:none;border:none;color:var(--ndt-text-secondary);cursor:pointer;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-md);line-height:1;transition:var(--ndt-transition-smooth)}.control:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.control--close:hover{background:var(--ndt-hover-danger)}\n"], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
1579
1733
  }
1580
1734
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarWindowComponent, decorators: [{
1581
1735
  type: Component,
1582
- args: [{ selector: 'ndt-window', standalone: true, template: `
1736
+ args: [{ selector: 'ndt-window', standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: `
1583
1737
  <div class="window dev-toolbar" [attr.data-theme]="theme()">
1584
1738
  <div class="header">
1585
1739
  <div class="header__content">
@@ -1617,7 +1771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1617
1771
  <ng-content></ng-content>
1618
1772
  </div>
1619
1773
  </div>
1620
- `, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}:host{display:block;width:100%}.window{box-sizing:border-box;display:flex;flex-direction:column;width:100%;height:100%;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-window-padding);font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";color:var(--ndt-text-secondary);z-index:999999999;box-shadow:var(--ndt-shadow-window)}.header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start}.header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm)}.header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:1px 4px;margin-left:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.header__description{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-muted)}.header__content{display:flex;flex-direction:column}.header__controls{display:flex;gap:var(--ndt-spacing-sm)}.content{flex:1;overflow:auto}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md)}.control{background:none;border:none;color:var(--ndt-text-secondary);cursor:pointer;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-md);line-height:1;transition:var(--ndt-transition-smooth)}.control:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.control--close:hover{background:var(--ndt-hover-danger)}\n"] }]
1774
+ `, styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:block;width:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.window{box-sizing:border-box;display:flex;flex-direction:column;width:100%;height:100%;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-window-padding);font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";color:var(--ndt-text-secondary);z-index:999999999;box-shadow:var(--ndt-shadow-window)}.header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start}.header h1{font-size:var(--ndt-font-size-lg);line-height:1.2;margin:0}.header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm)}.header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:1px 4px;margin-left:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.header__description{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-muted);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;line-height:1.4;margin:0}.header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.header__controls{display:flex;gap:var(--ndt-spacing-sm)}.content{flex:1;overflow:auto}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md)}.control{background:none;border:none;color:var(--ndt-text-secondary);cursor:pointer;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-md);line-height:1;transition:var(--ndt-transition-smooth)}.control:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.control--close:hover{background:var(--ndt-hover-danger)}\n"] }]
1621
1775
  }] });
1622
1776
 
1623
1777
  class DevToolbarToolComponent {
@@ -1718,7 +1872,7 @@ class DevToolbarToolComponent {
1718
1872
  </ng-template>
1719
1873
  }
1720
1874
  </div>
1721
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.tool{position:relative}.trigger{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: DevToolbarWindowComponent, selector: "ndt-window", inputs: ["config"], outputs: ["close", "maximize", "minimize"] }, { kind: "component", type: DevToolbarToolButtonComponent, selector: "ndt-tool-button", inputs: ["title", "toolId"], outputs: ["open"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], animations: [
1875
+ `, isInline: true, styles: [".tool{position:relative}.trigger{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: DevToolbarWindowComponent, selector: "ndt-window", inputs: ["config"], outputs: ["close", "maximize", "minimize"] }, { kind: "component", type: DevToolbarToolButtonComponent, selector: "ndt-tool-button", inputs: ["title", "toolId"], outputs: ["open"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], animations: [
1722
1876
  trigger('slideAnimation', [
1723
1877
  transition(':enter', [
1724
1878
  style({
@@ -1810,7 +1964,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1810
1964
  })),
1811
1965
  ]),
1812
1966
  ]),
1813
- ], styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.tool{position:relative}.trigger{cursor:pointer}\n"] }]
1967
+ ], styles: [".tool{position:relative}.trigger{cursor:pointer}\n"] }]
1814
1968
  }], propDecorators: { buttonContainer: [{
1815
1969
  type: ViewChild,
1816
1970
  args: ['buttonContainer']
@@ -1837,7 +1991,7 @@ class DevToolbarInputComponent {
1837
1991
  [placeholder]="placeholder()"
1838
1992
  (ngModelChange)="value.set($event)"
1839
1993
  />
1840
- `, isInline: true, styles: [":host{display:block}.input{width:100%;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);transition:var(--ndt-transition-default);box-sizing:border-box}.input::placeholder{color:var(--ndt-text-muted)}.input:focus{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.input:disabled{background-color:var(--ndt-bg-secondary);cursor:not-allowed;color:var(--ndt-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1994
+ `, isInline: true, styles: [":host{display:block}.input{width:100%;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);transition:var(--ndt-transition-default);box-sizing:border-box;min-height:36px}.input::placeholder{color:var(--ndt-text-muted)}.input:focus{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.input:disabled{background-color:var(--ndt-bg-secondary);cursor:not-allowed;color:var(--ndt-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1841
1995
  }
1842
1996
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInputComponent, decorators: [{
1843
1997
  type: Component,
@@ -1850,7 +2004,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1850
2004
  [placeholder]="placeholder()"
1851
2005
  (ngModelChange)="value.set($event)"
1852
2006
  />
1853
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.input{width:100%;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);transition:var(--ndt-transition-default);box-sizing:border-box}.input::placeholder{color:var(--ndt-text-muted)}.input:focus{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.input:disabled{background-color:var(--ndt-bg-secondary);cursor:not-allowed;color:var(--ndt-text-muted)}\n"] }]
2007
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.input{width:100%;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);transition:var(--ndt-transition-default);box-sizing:border-box;min-height:36px}.input::placeholder{color:var(--ndt-text-muted)}.input:focus{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.input:disabled{background-color:var(--ndt-bg-secondary);cursor:not-allowed;color:var(--ndt-text-muted)}\n"] }]
1854
2008
  }] });
1855
2009
 
1856
2010
  class DevToolbarSelectComponent {
@@ -1947,11 +2101,11 @@ class DevToolbarSelectComponent {
1947
2101
  }
1948
2102
  </div>
1949
2103
  </ng-template>
1950
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;height:32px;box-sizing:border-box}.select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.open .select__arrow{transform:rotate(180deg)}.select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1;margin-right:var(--ndt-spacing-sm);min-width:0}.select__arrow{width:16px;height:16px;flex-shrink:0;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:center;background-size:contain;transition:transform .2s ease;opacity:.9}.select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-xs) 0;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);box-shadow:var(--ndt-shadow-window);color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.select-menu::-webkit-scrollbar{width:8px;height:8px}.select-menu::-webkit-scrollbar-track{background:transparent}.select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:inherit;-webkit-user-select:none;user-select:none;min-width:64px;line-height:36px;padding:0 var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-sm);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.select-menu-item:hover{background-color:var(--ndt-hover-bg)}.select-menu-item:active{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected{color:var(--ndt-primary);background-color:rgba(var(--ndt-primary-rgb),.1);font-weight:500}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:8px;width:3px;height:calc(100% - 16px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:var(--ndt-hover-bg)}.select-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: CdkMenuModule }, { kind: "directive", type: i2.CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "directive", type: i2.CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2104
+ `, isInline: true, styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:inline-block;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;min-height:36px;box-sizing:border-box}.select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.open .select__arrow{transform:rotate(180deg)}.select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;margin-right:var(--ndt-spacing-sm);min-width:0;display:flex;align-items:center}.select__arrow{width:16px;height:16px;flex-shrink:0;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:center;background-size:contain;transition:transform .2s ease;opacity:.9}.select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-xs) 0;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);box-shadow:var(--ndt-shadow-window);color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.select-menu::-webkit-scrollbar{width:8px;height:8px}.select-menu::-webkit-scrollbar-track{background:transparent}.select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:inherit;-webkit-user-select:none;user-select:none;min-width:64px;line-height:36px;padding:0 var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-sm);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.select-menu-item:hover{background-color:var(--ndt-hover-bg)}.select-menu-item:active{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected{color:var(--ndt-primary);background-color:rgba(var(--ndt-primary-rgb),.1);font-weight:500}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:8px;width:3px;height:calc(100% - 16px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:var(--ndt-hover-bg)}.select-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: CdkMenuModule }, { kind: "directive", type: i2.CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "directive", type: i2.CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
1951
2105
  }
1952
2106
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarSelectComponent, decorators: [{
1953
2107
  type: Component,
1954
- args: [{ selector: 'ndt-select', standalone: true, imports: [CommonModule, FormsModule, OverlayModule, CdkMenuModule], template: `
2108
+ args: [{ selector: 'ndt-select', standalone: true, encapsulation: ViewEncapsulation.ShadowDom, imports: [CommonModule, FormsModule, OverlayModule, CdkMenuModule], template: `
1955
2109
  <div
1956
2110
  class="dev-toolbar select"
1957
2111
  [class.small]="size() === 'small'"
@@ -2000,7 +2154,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2000
2154
  }
2001
2155
  </div>
2002
2156
  </ng-template>
2003
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;height:32px;box-sizing:border-box}.select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.open .select__arrow{transform:rotate(180deg)}.select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1;margin-right:var(--ndt-spacing-sm);min-width:0}.select__arrow{width:16px;height:16px;flex-shrink:0;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:center;background-size:contain;transition:transform .2s ease;opacity:.9}.select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-xs) 0;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);box-shadow:var(--ndt-shadow-window);color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.select-menu::-webkit-scrollbar{width:8px;height:8px}.select-menu::-webkit-scrollbar-track{background:transparent}.select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:inherit;-webkit-user-select:none;user-select:none;min-width:64px;line-height:36px;padding:0 var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-sm);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.select-menu-item:hover{background-color:var(--ndt-hover-bg)}.select-menu-item:active{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected{color:var(--ndt-primary);background-color:rgba(var(--ndt-primary-rgb),.1);font-weight:500}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:8px;width:3px;height:calc(100% - 16px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:var(--ndt-hover-bg)}.select-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}\n"] }]
2157
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:inline-block;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background-color:var(--ndt-bg-primary);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;min-height:36px;box-sizing:border-box}.select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.select.open .select__arrow{transform:rotate(180deg)}.select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;margin-right:var(--ndt-spacing-sm);min-width:0;display:flex;align-items:center}.select__arrow{width:16px;height:16px;flex-shrink:0;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:center;background-size:contain;transition:transform .2s ease;opacity:.9}.select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-xs) 0;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);box-shadow:var(--ndt-shadow-window);color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.select-menu::-webkit-scrollbar{width:8px;height:8px}.select-menu::-webkit-scrollbar-track{background:transparent}.select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:inherit;-webkit-user-select:none;user-select:none;min-width:64px;line-height:36px;padding:0 var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-sm);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.select-menu-item:hover{background-color:var(--ndt-hover-bg)}.select-menu-item:active{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected{color:var(--ndt-primary);background-color:rgba(var(--ndt-primary-rgb),.1);font-weight:500}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.15)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:8px;width:3px;height:calc(100% - 16px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:var(--ndt-hover-bg)}.select-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}\n"] }]
2004
2158
  }] });
2005
2159
 
2006
2160
  class DevToolsStorageService {
@@ -2076,170 +2230,658 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2076
2230
  args: [{ providedIn: 'root' }]
2077
2231
  }] });
2078
2232
 
2079
- class DevToolbarInternalFeatureFlagService {
2233
+ /**
2234
+ * Internal service for managing app features state and forced overrides.
2235
+ *
2236
+ * This service handles:
2237
+ * - Feature configuration storage
2238
+ * - Forced feature state management
2239
+ * - localStorage persistence
2240
+ * - State validation and cleanup
2241
+ *
2242
+ * @internal This service is for internal toolbar use only. Consumers should use DevToolbarAppFeaturesService.
2243
+ */
2244
+ class DevToolbarInternalAppFeaturesService {
2080
2245
  constructor() {
2081
- this.STORAGE_KEY = 'feature-flags';
2246
+ this.STORAGE_KEY = 'app-features';
2082
2247
  this.storageService = inject(DevToolsStorageService);
2083
- this.appFlags$ = new BehaviorSubject([]);
2084
- this.forcedFlagsSubject = new BehaviorSubject({
2248
+ this.appFeaturesSubject = new BehaviorSubject([]);
2249
+ this.forcedFeaturesSubject = new BehaviorSubject({
2085
2250
  enabled: [],
2086
2251
  disabled: [],
2087
2252
  });
2088
- this.forcedFlags$ = this.forcedFlagsSubject.asObservable();
2089
- this.flags$ = combineLatest([
2090
- this.appFlags$,
2091
- this.forcedFlags$,
2092
- ]).pipe(map(([appFlags, { enabled, disabled }]) => {
2093
- return appFlags.map((flag) => ({
2094
- ...flag,
2095
- isForced: enabled.includes(flag.id) || disabled.includes(flag.id),
2096
- isEnabled: enabled.includes(flag.id),
2097
- }));
2098
- }));
2099
- this.flags = toSignal(this.flags$, { initialValue: [] });
2100
- this.loadForcedFlags();
2253
+ this.forcedFeatures$ = this.forcedFeaturesSubject.asObservable();
2254
+ /**
2255
+ * Observable stream of all features with merged forced state
2256
+ */
2257
+ this.features$ = combineLatest([
2258
+ this.appFeaturesSubject.asObservable(),
2259
+ this.forcedFeatures$,
2260
+ ]).pipe(map(([appFeatures, forcedState]) => this.mergeForcedState(appFeatures, forcedState)));
2261
+ /**
2262
+ * Signal containing current features with merged forced state
2263
+ */
2264
+ this.features = toSignal(this.features$, { initialValue: [] });
2265
+ this.loadForcedFeatures();
2101
2266
  }
2102
- setAppFlags(flags) {
2103
- this.appFlags$.next(flags);
2267
+ /**
2268
+ * Set available app features for the application.
2269
+ * Validates features, trims whitespace, and triggers validation of forced state.
2270
+ *
2271
+ * @param features - Array of app features to configure
2272
+ * @throws Error if duplicate feature IDs or empty IDs are detected
2273
+ */
2274
+ setAppFeatures(features) {
2275
+ // Validate for empty IDs
2276
+ const emptyIdFeature = features.find((f) => !f.id || f.id.trim() === '');
2277
+ if (emptyIdFeature) {
2278
+ throw new Error('Feature ID cannot be empty');
2279
+ }
2280
+ // Validate for duplicate IDs
2281
+ const ids = features.map((f) => f.id);
2282
+ const duplicateIds = ids.filter((id, index) => ids.indexOf(id) !== index);
2283
+ if (duplicateIds.length > 0) {
2284
+ throw new Error(`Duplicate feature IDs detected: ${duplicateIds.join(', ')}`);
2285
+ }
2286
+ // Trim whitespace from names and warn about empty names
2287
+ const processedFeatures = features.map((feature) => {
2288
+ const trimmedName = feature.name.trim();
2289
+ if (!trimmedName) {
2290
+ console.warn(`Feature '${feature.id}' has empty name`);
2291
+ }
2292
+ return {
2293
+ ...feature,
2294
+ name: trimmedName || feature.name,
2295
+ };
2296
+ });
2297
+ this.appFeaturesSubject.next(processedFeatures);
2298
+ this.validateAndCleanForcedState();
2104
2299
  }
2105
- getAppFlags() {
2106
- return this.appFlags$.asObservable();
2300
+ /**
2301
+ * Get observable stream of app features (natural state, no forced state merged)
2302
+ */
2303
+ getAppFeatures() {
2304
+ return this.appFeaturesSubject.asObservable();
2107
2305
  }
2108
- getForcedFlags() {
2109
- return this.flags$.pipe(map((flags) => flags.filter((flag) => flag.isForced)));
2306
+ /**
2307
+ * Get observable stream of features that have forced overrides
2308
+ */
2309
+ getForcedFeatures() {
2310
+ return this.features$.pipe(map((features) => features.filter((feature) => feature.isForced)));
2110
2311
  }
2111
- setFlag(flagId, isEnabled) {
2112
- const { enabled, disabled } = this.forcedFlagsSubject.value;
2113
- const newEnabled = enabled.filter((id) => id !== flagId);
2114
- const newDisabled = disabled.filter((id) => id !== flagId);
2312
+ /**
2313
+ * Force a feature to enabled or disabled state.
2314
+ * Persists the forced state to localStorage.
2315
+ *
2316
+ * @param featureId - ID of the feature to force
2317
+ * @param isEnabled - Whether to force feature to enabled (true) or disabled (false)
2318
+ */
2319
+ setFeature(featureId, isEnabled) {
2320
+ const { enabled, disabled } = this.forcedFeaturesSubject.value;
2321
+ // Remove feature from both arrays
2322
+ const newEnabled = enabled.filter((id) => id !== featureId);
2323
+ const newDisabled = disabled.filter((id) => id !== featureId);
2324
+ // Add to appropriate array
2115
2325
  if (isEnabled) {
2116
- newEnabled.push(flagId);
2326
+ newEnabled.push(featureId);
2117
2327
  }
2118
2328
  else {
2119
- newDisabled.push(flagId);
2329
+ newDisabled.push(featureId);
2120
2330
  }
2121
2331
  const newState = { enabled: newEnabled, disabled: newDisabled };
2122
- this.forcedFlagsSubject.next(newState);
2123
- this.storageService.set(this.STORAGE_KEY, newState);
2332
+ this.forcedFeaturesSubject.next(newState);
2333
+ this.saveForcedFeatures(newState);
2124
2334
  }
2125
- removeFlagOverride(flagId) {
2126
- const { enabled, disabled } = this.forcedFlagsSubject.value;
2335
+ /**
2336
+ * Remove forced override for a feature, returning it to natural state.
2337
+ * Persists the change to localStorage.
2338
+ *
2339
+ * @param featureId - ID of the feature to unforce
2340
+ */
2341
+ removeFeatureOverride(featureId) {
2342
+ const { enabled, disabled } = this.forcedFeaturesSubject.value;
2127
2343
  const newState = {
2128
- enabled: enabled.filter((id) => id !== flagId),
2129
- disabled: disabled.filter((id) => id !== flagId),
2344
+ enabled: enabled.filter((id) => id !== featureId),
2345
+ disabled: disabled.filter((id) => id !== featureId),
2130
2346
  };
2131
- this.forcedFlagsSubject.next(newState);
2132
- this.storageService.set(this.STORAGE_KEY, newState);
2347
+ this.forcedFeaturesSubject.next(newState);
2348
+ this.saveForcedFeatures(newState);
2133
2349
  }
2134
- loadForcedFlags() {
2135
- const savedFlags = this.storageService.get(this.STORAGE_KEY);
2136
- if (savedFlags) {
2137
- this.forcedFlagsSubject.next(savedFlags);
2350
+ /**
2351
+ * Apply a preset forced state (for preset integration).
2352
+ * Validates and cleans invalid feature IDs before applying.
2353
+ *
2354
+ * @param state - Forced features state from preset
2355
+ */
2356
+ applyForcedState(state) {
2357
+ const configuredFeatureIds = this.appFeaturesSubject.value.map((f) => f.id);
2358
+ // Validate and filter to only valid IDs
2359
+ const validEnabled = state.enabled.filter((id) => configuredFeatureIds.includes(id));
2360
+ const validDisabled = state.disabled.filter((id) => configuredFeatureIds.includes(id));
2361
+ const invalidIds = [
2362
+ ...state.enabled.filter((id) => !configuredFeatureIds.includes(id)),
2363
+ ...state.disabled.filter((id) => !configuredFeatureIds.includes(id)),
2364
+ ];
2365
+ if (invalidIds.length > 0) {
2366
+ console.warn(`Preset contains invalid feature IDs (ignored): ${invalidIds.join(', ')}`);
2138
2367
  }
2368
+ const cleanedState = { enabled: validEnabled, disabled: validDisabled };
2369
+ this.forcedFeaturesSubject.next(cleanedState);
2370
+ this.saveForcedFeatures(cleanedState);
2139
2371
  }
2140
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2141
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, providedIn: 'root' }); }
2372
+ /**
2373
+ * Get current forced state as a snapshot (defensive copy).
2374
+ * Useful for preset exports and debugging.
2375
+ *
2376
+ * @returns Current forced features state
2377
+ */
2378
+ getCurrentForcedState() {
2379
+ const state = this.forcedFeaturesSubject.value;
2380
+ return {
2381
+ enabled: [...state.enabled],
2382
+ disabled: [...state.disabled],
2383
+ };
2384
+ }
2385
+ /**
2386
+ * Merge natural app features with forced state.
2387
+ *
2388
+ * @param appFeatures - Natural feature configuration
2389
+ * @param forcedState - Forced overrides from localStorage/toolbar
2390
+ * @returns Features with merged forced state
2391
+ */
2392
+ mergeForcedState(appFeatures, forcedState) {
2393
+ return appFeatures.map((feature) => {
2394
+ const isInEnabled = forcedState.enabled.includes(feature.id);
2395
+ const isInDisabled = forcedState.disabled.includes(feature.id);
2396
+ const isForced = isInEnabled || isInDisabled;
2397
+ return {
2398
+ ...feature,
2399
+ isEnabled: isInEnabled ? true : isInDisabled ? false : feature.isEnabled,
2400
+ isForced,
2401
+ };
2402
+ });
2403
+ }
2404
+ /**
2405
+ * Load forced features state from localStorage on initialization.
2406
+ * Handles missing or corrupted data gracefully.
2407
+ */
2408
+ loadForcedFeatures() {
2409
+ try {
2410
+ const savedState = this.storageService.get(this.STORAGE_KEY);
2411
+ if (savedState) {
2412
+ this.forcedFeaturesSubject.next(savedState);
2413
+ }
2414
+ }
2415
+ catch (error) {
2416
+ console.error('Failed to load forced app features from localStorage:', error);
2417
+ // Use default empty state on error
2418
+ }
2419
+ }
2420
+ /**
2421
+ * Persist forced features state to localStorage.
2422
+ * Handles quota exceeded errors gracefully.
2423
+ *
2424
+ * @param state - Forced state to persist
2425
+ */
2426
+ saveForcedFeatures(state) {
2427
+ try {
2428
+ this.storageService.set(this.STORAGE_KEY, state);
2429
+ }
2430
+ catch (error) {
2431
+ console.error('Failed to persist app features to localStorage:', error);
2432
+ // Continue execution - state is still valid in memory for current session
2433
+ }
2434
+ }
2435
+ /**
2436
+ * Validate forced feature IDs against configured features and clean up invalid ones.
2437
+ * Called after setAppFeatures() to ensure forced state references valid features.
2438
+ */
2439
+ validateAndCleanForcedState() {
2440
+ const configuredFeatureIds = this.appFeaturesSubject.value.map((f) => f.id);
2441
+ const currentForcedState = this.forcedFeaturesSubject.value;
2442
+ const validEnabled = currentForcedState.enabled.filter((id) => configuredFeatureIds.includes(id));
2443
+ const validDisabled = currentForcedState.disabled.filter((id) => configuredFeatureIds.includes(id));
2444
+ const removedIds = [
2445
+ ...currentForcedState.enabled.filter((id) => !configuredFeatureIds.includes(id)),
2446
+ ...currentForcedState.disabled.filter((id) => !configuredFeatureIds.includes(id)),
2447
+ ];
2448
+ if (removedIds.length > 0) {
2449
+ console.warn(`Removed invalid feature IDs from forced state: ${removedIds.join(', ')}`);
2450
+ const cleanedState = { enabled: validEnabled, disabled: validDisabled };
2451
+ this.forcedFeaturesSubject.next(cleanedState);
2452
+ this.saveForcedFeatures(cleanedState);
2453
+ }
2454
+ }
2455
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalAppFeaturesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2456
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalAppFeaturesService, providedIn: 'root' }); }
2142
2457
  }
2143
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, decorators: [{
2458
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalAppFeaturesService, decorators: [{
2144
2459
  type: Injectable,
2145
2460
  args: [{ providedIn: 'root' }]
2146
2461
  }], ctorParameters: () => [] });
2147
2462
 
2148
- class DevToolbarFeatureFlagsToolComponent {
2463
+ /**
2464
+ * Component for managing app features in the dev toolbar.
2465
+ *
2466
+ * Provides UI for:
2467
+ * - Searching features by name and description
2468
+ * - Filtering features by state (all/forced/enabled/disabled)
2469
+ * - Forcing features to enabled/disabled state via 3-state dropdown
2470
+ * - Viewing feature descriptions and current state
2471
+ *
2472
+ * @example
2473
+ * ```html
2474
+ * <ndt-app-features-tool />
2475
+ * ```
2476
+ */
2477
+ class DevToolbarAppFeaturesToolComponent {
2149
2478
  constructor() {
2150
2479
  // Injects
2151
- this.featureFlags = inject(DevToolbarInternalFeatureFlagService);
2480
+ this.appFeaturesService = inject(DevToolbarInternalAppFeaturesService);
2152
2481
  // Signals
2153
2482
  this.activeFilter = signal('all');
2154
2483
  this.searchQuery = signal('');
2155
- this.flags = this.featureFlags.flags;
2156
- this.hasNoFlags = computed(() => this.flags().length === 0);
2157
- this.filteredFlags = computed(() => {
2158
- return this.flags().filter((flag) => {
2484
+ this.features = this.appFeaturesService.features;
2485
+ this.hasNoFeatures = computed(() => this.features().length === 0);
2486
+ this.filteredFeatures = computed(() => {
2487
+ return this.features().filter((feature) => {
2159
2488
  const searchTerm = this.searchQuery().toLowerCase();
2160
- const flagName = flag.name.toLowerCase();
2161
- const flagDescription = flag.description?.toLowerCase() ?? '';
2489
+ const featureName = feature.name.toLowerCase();
2490
+ const featureDescription = feature.description?.toLowerCase() ?? '';
2162
2491
  const matchesSearch = !this.searchQuery() ||
2163
- flagName.toLowerCase().includes(searchTerm.toLowerCase()) ||
2164
- flagDescription.toLowerCase().includes(searchTerm.toLowerCase());
2492
+ featureName.includes(searchTerm) ||
2493
+ featureDescription.includes(searchTerm);
2165
2494
  const matchesFilter = this.activeFilter() === 'all' ||
2166
- (this.activeFilter() === 'forced' && flag.isForced) ||
2167
- (this.activeFilter() === 'enabled' && flag.isEnabled) ||
2168
- (this.activeFilter() === 'disabled' && !flag.isEnabled);
2495
+ (this.activeFilter() === 'forced' && feature.isForced) ||
2496
+ (this.activeFilter() === 'enabled' && feature.isEnabled) ||
2497
+ (this.activeFilter() === 'disabled' && !feature.isEnabled);
2169
2498
  return matchesSearch && matchesFilter;
2170
2499
  });
2171
2500
  });
2172
- this.hasNoFilteredFlags = computed(() => this.filteredFlags().length === 0);
2501
+ this.hasNoFilteredFeatures = computed(() => this.filteredFeatures().length === 0);
2173
2502
  // Other properties
2174
2503
  this.options = {
2175
- title: 'Feature Flags',
2176
- description: 'Manage the feature flags for your current session',
2504
+ title: 'App Features',
2505
+ description: 'Override product features to test different tiers and configurations',
2177
2506
  isClosable: true,
2178
2507
  size: 'tall',
2179
- id: 'ndt-feature-flags',
2180
- isBeta: true,
2508
+ id: 'ndt-app-features',
2181
2509
  };
2182
2510
  this.filterOptions = [
2183
- { value: 'all', label: 'All Flags' },
2511
+ { value: 'all', label: 'All Features' },
2184
2512
  { value: 'forced', label: 'Forced' },
2185
2513
  { value: 'enabled', label: 'Enabled' },
2186
2514
  { value: 'disabled', label: 'Disabled' },
2187
2515
  ];
2188
- this.flagValueOptions = [
2189
- { value: 'not-forced', label: 'Not Forced' },
2190
- { value: 'off', label: 'Forced Off' },
2191
- { value: 'on', label: 'Forced On' },
2516
+ this.featureValueOptions = [
2517
+ { value: '', label: 'Not Forced' },
2518
+ { value: 'off', label: 'Disabled' },
2519
+ { value: 'on', label: 'Enabled' },
2192
2520
  ];
2193
2521
  }
2194
2522
  // Public methods
2523
+ /**
2524
+ * Handle filter dropdown change.
2525
+ * Updates the active filter to show all/forced/enabled/disabled features.
2526
+ */
2195
2527
  onFilterChange(value) {
2196
2528
  const filter = this.filterOptions.find((f) => f.value === value);
2197
2529
  if (filter) {
2198
2530
  this.activeFilter.set(filter.value);
2199
2531
  }
2200
2532
  }
2201
- onFlagChange(flagId, value) {
2533
+ /**
2534
+ * Handle feature value change from 3-state dropdown.
2535
+ * - 'not-forced' (empty string): Remove forced override
2536
+ * - 'on': Force feature to enabled
2537
+ * - 'off': Force feature to disabled
2538
+ */
2539
+ onFeatureChange(featureId, value) {
2202
2540
  switch (value) {
2203
- case 'not-forced':
2204
- this.featureFlags.removeFlagOverride(flagId);
2541
+ case '':
2542
+ this.appFeaturesService.removeFeatureOverride(featureId);
2205
2543
  break;
2206
2544
  case 'on':
2207
- this.featureFlags.setFlag(flagId, true);
2545
+ this.appFeaturesService.setFeature(featureId, true);
2208
2546
  break;
2209
2547
  case 'off':
2210
- this.featureFlags.setFlag(flagId, false);
2548
+ this.appFeaturesService.setFeature(featureId, false);
2211
2549
  break;
2212
2550
  }
2213
2551
  }
2552
+ /**
2553
+ * Handle search input change.
2554
+ * Updates the search query to filter features by name/description.
2555
+ */
2214
2556
  onSearchChange(query) {
2215
2557
  this.searchQuery.set(query);
2216
2558
  }
2217
2559
  // Protected methods
2218
- getFlagValue(flag) {
2219
- if (!flag.isForced)
2560
+ /**
2561
+ * Get the dropdown value for a feature's current state.
2562
+ * - Returns empty string if not forced (natural state)
2563
+ * - Returns 'on' if forced to enabled
2564
+ * - Returns 'off' if forced to disabled
2565
+ */
2566
+ getFeatureValue(feature) {
2567
+ if (!feature.isForced)
2220
2568
  return '';
2221
- return flag.isEnabled ? 'on' : 'off';
2569
+ return feature.isEnabled ? 'on' : 'off';
2222
2570
  }
2223
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarFeatureFlagsToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2224
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarFeatureFlagsToolComponent, isStandalone: true, selector: "ndt-feature-flags-tool", ngImport: i0, template: `
2571
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarAppFeaturesToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2572
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarAppFeaturesToolComponent, isStandalone: true, selector: "ndt-app-features-tool", ngImport: i0, template: `
2225
2573
  <ndt-toolbar-tool
2226
2574
  [options]="options"
2227
- title="Feature Flags"
2228
- icon="toggle-left"
2575
+ title="App Features"
2576
+ icon="puzzle"
2229
2577
  >
2230
2578
  <div class="container">
2231
2579
  <div class="header">
2232
2580
  <ndt-input
2233
2581
  [value]="searchQuery()"
2234
2582
  (valueChange)="onSearchChange($event)"
2235
- placeholder="Search..."
2236
- />
2237
- <ndt-select
2238
- [value]="activeFilter()"
2239
- [options]="filterOptions"
2240
- [size]="'medium'"
2241
- (valueChange)="onFilterChange($event)"
2583
+ placeholder="Search features..."
2242
2584
  />
2585
+ <div class="filter-wrapper">
2586
+ <ndt-icon name="filter" class="filter-icon" />
2587
+ <ndt-select
2588
+ [value]="activeFilter()"
2589
+ [options]="filterOptions"
2590
+ [size]="'medium'"
2591
+ (valueChange)="onFilterChange($event)"
2592
+ />
2593
+ </div>
2594
+ </div>
2595
+
2596
+ @if (hasNoFeatures()) {
2597
+ <div class="empty">
2598
+ <p>No app features found</p>
2599
+ <small>Call setAvailableOptions() to configure features</small>
2600
+ </div>
2601
+ } @else if (hasNoFilteredFeatures()) {
2602
+ <div class="empty">
2603
+ <p>No features match your filter</p>
2604
+ </div>
2605
+ } @else {
2606
+ <div class="feature-list">
2607
+ @for (feature of filteredFeatures(); track feature.id) {
2608
+ <div class="feature">
2609
+ <div class="info">
2610
+ <h3>{{ feature.name }}</h3>
2611
+ @if (feature.description) {
2612
+ <p>{{ feature.description }}</p>
2613
+ }
2614
+ </div>
2615
+
2616
+ <ndt-select
2617
+ [value]="getFeatureValue(feature)"
2618
+ [options]="featureValueOptions"
2619
+ [ariaLabel]="'Set value for ' + feature.name"
2620
+ (valueChange)="onFeatureChange(feature.id, $event ?? '')"
2621
+ size="small"
2622
+ />
2623
+ </div>
2624
+ }
2625
+ </div>
2626
+ }
2627
+ </div>
2628
+ </ndt-toolbar-tool>
2629
+ `, isInline: true, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.empty p{margin:0;font-size:var(--ndt-font-size-md)}.empty small{font-size:var(--ndt-font-size-xs);opacity:.8}.feature-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.feature-list::-webkit-scrollbar{width:8px}.feature-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.feature-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.feature{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium)}.feature .info{flex:0 0 65%}.feature .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.feature .info p{margin:var(--ndt-spacing-xs) 0 0 0;font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.feature ndt-select{flex:0 0 35%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "component", type: DevToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2630
+ }
2631
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarAppFeaturesToolComponent, decorators: [{
2632
+ type: Component,
2633
+ args: [{ selector: 'ndt-app-features-tool', standalone: true, imports: [
2634
+ FormsModule,
2635
+ DevToolbarToolComponent,
2636
+ DevToolbarInputComponent,
2637
+ DevToolbarSelectComponent,
2638
+ DevToolbarIconComponent,
2639
+ ], template: `
2640
+ <ndt-toolbar-tool
2641
+ [options]="options"
2642
+ title="App Features"
2643
+ icon="puzzle"
2644
+ >
2645
+ <div class="container">
2646
+ <div class="header">
2647
+ <ndt-input
2648
+ [value]="searchQuery()"
2649
+ (valueChange)="onSearchChange($event)"
2650
+ placeholder="Search features..."
2651
+ />
2652
+ <div class="filter-wrapper">
2653
+ <ndt-icon name="filter" class="filter-icon" />
2654
+ <ndt-select
2655
+ [value]="activeFilter()"
2656
+ [options]="filterOptions"
2657
+ [size]="'medium'"
2658
+ (valueChange)="onFilterChange($event)"
2659
+ />
2660
+ </div>
2661
+ </div>
2662
+
2663
+ @if (hasNoFeatures()) {
2664
+ <div class="empty">
2665
+ <p>No app features found</p>
2666
+ <small>Call setAvailableOptions() to configure features</small>
2667
+ </div>
2668
+ } @else if (hasNoFilteredFeatures()) {
2669
+ <div class="empty">
2670
+ <p>No features match your filter</p>
2671
+ </div>
2672
+ } @else {
2673
+ <div class="feature-list">
2674
+ @for (feature of filteredFeatures(); track feature.id) {
2675
+ <div class="feature">
2676
+ <div class="info">
2677
+ <h3>{{ feature.name }}</h3>
2678
+ @if (feature.description) {
2679
+ <p>{{ feature.description }}</p>
2680
+ }
2681
+ </div>
2682
+
2683
+ <ndt-select
2684
+ [value]="getFeatureValue(feature)"
2685
+ [options]="featureValueOptions"
2686
+ [ariaLabel]="'Set value for ' + feature.name"
2687
+ (valueChange)="onFeatureChange(feature.id, $event ?? '')"
2688
+ size="small"
2689
+ />
2690
+ </div>
2691
+ }
2692
+ </div>
2693
+ }
2694
+ </div>
2695
+ </ndt-toolbar-tool>
2696
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.empty p{margin:0;font-size:var(--ndt-font-size-md)}.empty small{font-size:var(--ndt-font-size-xs);opacity:.8}.feature-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.feature-list::-webkit-scrollbar{width:8px}.feature-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.feature-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.feature{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium)}.feature .info{flex:0 0 65%}.feature .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.feature .info p{margin:var(--ndt-spacing-xs) 0 0 0;font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.feature ndt-select{flex:0 0 35%}\n"] }]
2697
+ }] });
2698
+
2699
+ class DevToolbarInternalFeatureFlagService {
2700
+ constructor() {
2701
+ this.STORAGE_KEY = 'feature-flags';
2702
+ this.storageService = inject(DevToolsStorageService);
2703
+ this.appFlags$ = new BehaviorSubject([]);
2704
+ this.forcedFlagsSubject = new BehaviorSubject({
2705
+ enabled: [],
2706
+ disabled: [],
2707
+ });
2708
+ this.forcedFlags$ = this.forcedFlagsSubject.asObservable();
2709
+ this.flags$ = combineLatest([
2710
+ this.appFlags$,
2711
+ this.forcedFlags$,
2712
+ ]).pipe(map(([appFlags, { enabled, disabled }]) => {
2713
+ return appFlags.map((flag) => ({
2714
+ ...flag,
2715
+ isForced: enabled.includes(flag.id) || disabled.includes(flag.id),
2716
+ isEnabled: enabled.includes(flag.id)
2717
+ ? true
2718
+ : disabled.includes(flag.id)
2719
+ ? false
2720
+ : flag.isEnabled,
2721
+ }));
2722
+ }));
2723
+ this.flags = toSignal(this.flags$, { initialValue: [] });
2724
+ this.loadForcedFlags();
2725
+ }
2726
+ setAppFlags(flags) {
2727
+ this.appFlags$.next(flags);
2728
+ }
2729
+ getAppFlags() {
2730
+ return this.appFlags$.asObservable();
2731
+ }
2732
+ getForcedFlags() {
2733
+ return this.flags$.pipe(map((flags) => flags.filter((flag) => flag.isForced)));
2734
+ }
2735
+ setFlag(flagId, isEnabled) {
2736
+ const { enabled, disabled } = this.forcedFlagsSubject.value;
2737
+ const newEnabled = enabled.filter((id) => id !== flagId);
2738
+ const newDisabled = disabled.filter((id) => id !== flagId);
2739
+ if (isEnabled) {
2740
+ newEnabled.push(flagId);
2741
+ }
2742
+ else {
2743
+ newDisabled.push(flagId);
2744
+ }
2745
+ const newState = { enabled: newEnabled, disabled: newDisabled };
2746
+ this.forcedFlagsSubject.next(newState);
2747
+ this.storageService.set(this.STORAGE_KEY, newState);
2748
+ }
2749
+ removeFlagOverride(flagId) {
2750
+ const { enabled, disabled } = this.forcedFlagsSubject.value;
2751
+ const newState = {
2752
+ enabled: enabled.filter((id) => id !== flagId),
2753
+ disabled: disabled.filter((id) => id !== flagId),
2754
+ };
2755
+ this.forcedFlagsSubject.next(newState);
2756
+ this.storageService.set(this.STORAGE_KEY, newState);
2757
+ }
2758
+ loadForcedFlags() {
2759
+ const savedFlags = this.storageService.get(this.STORAGE_KEY);
2760
+ if (savedFlags) {
2761
+ this.forcedFlagsSubject.next(savedFlags);
2762
+ }
2763
+ }
2764
+ /**
2765
+ * Apply feature flags from a preset (used by Presets Tool)
2766
+ * This method directly sets the forced flags state without user interaction
2767
+ */
2768
+ applyPresetFlags(presetState) {
2769
+ this.forcedFlagsSubject.next(presetState);
2770
+ this.storageService.set(this.STORAGE_KEY, presetState);
2771
+ }
2772
+ /**
2773
+ * Get current forced state for saving to preset
2774
+ * Returns the raw state of enabled and disabled flag IDs
2775
+ */
2776
+ getCurrentForcedState() {
2777
+ return this.forcedFlagsSubject.value;
2778
+ }
2779
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2780
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, providedIn: 'root' }); }
2781
+ }
2782
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalFeatureFlagService, decorators: [{
2783
+ type: Injectable,
2784
+ args: [{ providedIn: 'root' }]
2785
+ }], ctorParameters: () => [] });
2786
+
2787
+ class DevToolbarFeatureFlagsToolComponent {
2788
+ constructor() {
2789
+ // Injects
2790
+ this.featureFlags = inject(DevToolbarInternalFeatureFlagService);
2791
+ // Signals
2792
+ this.activeFilter = signal('all');
2793
+ this.searchQuery = signal('');
2794
+ this.flags = this.featureFlags.flags;
2795
+ this.hasNoFlags = computed(() => this.flags().length === 0);
2796
+ this.filteredFlags = computed(() => {
2797
+ return this.flags().filter((flag) => {
2798
+ const searchTerm = this.searchQuery().toLowerCase();
2799
+ const flagName = flag.name.toLowerCase();
2800
+ const flagDescription = flag.description?.toLowerCase() ?? '';
2801
+ const matchesSearch = !this.searchQuery() ||
2802
+ flagName.toLowerCase().includes(searchTerm.toLowerCase()) ||
2803
+ flagDescription.toLowerCase().includes(searchTerm.toLowerCase());
2804
+ const matchesFilter = this.activeFilter() === 'all' ||
2805
+ (this.activeFilter() === 'forced' && flag.isForced) ||
2806
+ (this.activeFilter() === 'enabled' && flag.isEnabled) ||
2807
+ (this.activeFilter() === 'disabled' && !flag.isEnabled);
2808
+ return matchesSearch && matchesFilter;
2809
+ });
2810
+ });
2811
+ this.hasNoFilteredFlags = computed(() => this.filteredFlags().length === 0);
2812
+ // Other properties
2813
+ this.options = {
2814
+ title: 'Feature Flags',
2815
+ description: 'Manage the feature flags for your current session',
2816
+ isClosable: true,
2817
+ size: 'tall',
2818
+ id: 'ndt-feature-flags',
2819
+ isBeta: true,
2820
+ };
2821
+ this.filterOptions = [
2822
+ { value: 'all', label: 'All Flags' },
2823
+ { value: 'forced', label: 'Forced' },
2824
+ { value: 'enabled', label: 'Enabled' },
2825
+ { value: 'disabled', label: 'Disabled' },
2826
+ ];
2827
+ this.flagValueOptions = [
2828
+ { value: 'not-forced', label: 'Not Forced' },
2829
+ { value: 'off', label: 'Forced Off' },
2830
+ { value: 'on', label: 'Forced On' },
2831
+ ];
2832
+ }
2833
+ // Public methods
2834
+ onFilterChange(value) {
2835
+ const filter = this.filterOptions.find((f) => f.value === value);
2836
+ if (filter) {
2837
+ this.activeFilter.set(filter.value);
2838
+ }
2839
+ }
2840
+ onFlagChange(flagId, value) {
2841
+ switch (value) {
2842
+ case 'not-forced':
2843
+ this.featureFlags.removeFlagOverride(flagId);
2844
+ break;
2845
+ case 'on':
2846
+ this.featureFlags.setFlag(flagId, true);
2847
+ break;
2848
+ case 'off':
2849
+ this.featureFlags.setFlag(flagId, false);
2850
+ break;
2851
+ }
2852
+ }
2853
+ onSearchChange(query) {
2854
+ this.searchQuery.set(query);
2855
+ }
2856
+ // Protected methods
2857
+ getFlagValue(flag) {
2858
+ if (!flag.isForced)
2859
+ return '';
2860
+ return flag.isEnabled ? 'on' : 'off';
2861
+ }
2862
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarFeatureFlagsToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2863
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarFeatureFlagsToolComponent, isStandalone: true, selector: "ndt-feature-flags-tool", ngImport: i0, template: `
2864
+ <ndt-toolbar-tool
2865
+ [options]="options"
2866
+ title="Feature Flags"
2867
+ icon="toggle-left"
2868
+ >
2869
+ <div class="container">
2870
+ <div class="header">
2871
+ <ndt-input
2872
+ [value]="searchQuery()"
2873
+ (valueChange)="onSearchChange($event)"
2874
+ placeholder="Search..."
2875
+ />
2876
+ <div class="filter-wrapper">
2877
+ <ndt-icon name="filter" class="filter-icon" />
2878
+ <ndt-select
2879
+ [value]="activeFilter()"
2880
+ [options]="filterOptions"
2881
+ [size]="'medium'"
2882
+ (valueChange)="onFilterChange($event)"
2883
+ />
2884
+ </div>
2243
2885
  </div>
2244
2886
 
2245
2887
  @if (hasNoFlags()) {
@@ -2272,7 +2914,7 @@ class DevToolbarFeatureFlagsToolComponent {
2272
2914
  }
2273
2915
  </div>
2274
2916
  </ndt-toolbar-tool>
2275
- `, isInline: true, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:.65}.header ndt-select{flex:.35}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.flag-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.flag-list::-webkit-scrollbar{width:8px}.flag-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.flag-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.flag{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.flag .info{flex:0 0 65%}.flag .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.flag .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.flag ndt-select{flex:0 0 35%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "component", type: DevToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2917
+ `, isInline: true, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.flag-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.flag-list::-webkit-scrollbar{width:8px}.flag-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.flag-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.flag{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.flag .info{flex:0 0 65%}.flag .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.flag .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.flag ndt-select{flex:0 0 35%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "component", type: DevToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2276
2918
  }
2277
2919
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarFeatureFlagsToolComponent, decorators: [{
2278
2920
  type: Component,
@@ -2281,6 +2923,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2281
2923
  DevToolbarToolComponent,
2282
2924
  DevToolbarInputComponent,
2283
2925
  DevToolbarSelectComponent,
2926
+ DevToolbarIconComponent,
2284
2927
  ], template: `
2285
2928
  <ndt-toolbar-tool
2286
2929
  [options]="options"
@@ -2294,12 +2937,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2294
2937
  (valueChange)="onSearchChange($event)"
2295
2938
  placeholder="Search..."
2296
2939
  />
2297
- <ndt-select
2298
- [value]="activeFilter()"
2299
- [options]="filterOptions"
2300
- [size]="'medium'"
2301
- (valueChange)="onFilterChange($event)"
2302
- />
2940
+ <div class="filter-wrapper">
2941
+ <ndt-icon name="filter" class="filter-icon" />
2942
+ <ndt-select
2943
+ [value]="activeFilter()"
2944
+ [options]="filterOptions"
2945
+ [size]="'medium'"
2946
+ (valueChange)="onFilterChange($event)"
2947
+ />
2948
+ </div>
2303
2949
  </div>
2304
2950
 
2305
2951
  @if (hasNoFlags()) {
@@ -2332,7 +2978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2332
2978
  }
2333
2979
  </div>
2334
2980
  </ndt-toolbar-tool>
2335
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:.65}.header ndt-select{flex:.35}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.flag-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.flag-list::-webkit-scrollbar{width:8px}.flag-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.flag-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.flag{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.flag .info{flex:0 0 65%}.flag .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.flag .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.flag ndt-select{flex:0 0 35%}\n"] }]
2981
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.flag-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.flag-list::-webkit-scrollbar{width:8px}.flag-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.flag-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.flag{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.flag .info{flex:0 0 65%}.flag .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.flag .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.flag ndt-select{flex:0 0 35%}\n"] }]
2336
2982
  }] });
2337
2983
 
2338
2984
  class DevToolbarButtonComponent {
@@ -2361,7 +3007,7 @@ class DevToolbarButtonComponent {
2361
3007
  }
2362
3008
  <ng-content />
2363
3009
  </button>
2364
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.button{display:inline-flex;align-items:center;gap:var(--ndt-spacing-xs);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);cursor:pointer;transition:var(--ndt-transition-default);outline:none;font-family:inherit}.button:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.button:focus-visible{outline:none;background:var(--ndt-hover-bg);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.button.primary{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.button.primary:hover{background:var(--ndt-primary);border-color:var(--ndt-primary)}.button.icon-only{padding:var(--ndt-spacing-xs);width:32px;height:32px;justify-content:center}.button.small{font-size:var(--ndt-font-size-sm)}\n"], dependencies: [{ kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3010
+ `, isInline: true, styles: [".button{display:inline-flex;align-items:center;gap:var(--ndt-spacing-xs);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);min-height:36px;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);cursor:pointer;transition:var(--ndt-transition-default);outline:none;font-family:inherit}.button:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.button:focus-visible{outline:none;background:var(--ndt-hover-bg);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.button.primary{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.button.primary:hover{background:var(--ndt-primary);border-color:var(--ndt-primary)}.button.icon-only{padding:var(--ndt-spacing-xs);width:32px;height:32px;justify-content:center}.button.small{font-size:var(--ndt-font-size-sm)}\n"], dependencies: [{ kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2365
3011
  }
2366
3012
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarButtonComponent, decorators: [{
2367
3013
  type: Component,
@@ -2381,7 +3027,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2381
3027
  }
2382
3028
  <ng-content />
2383
3029
  </button>
2384
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.button{display:inline-flex;align-items:center;gap:var(--ndt-spacing-xs);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);cursor:pointer;transition:var(--ndt-transition-default);outline:none;font-family:inherit}.button:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.button:focus-visible{outline:none;background:var(--ndt-hover-bg);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.button.primary{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.button.primary:hover{background:var(--ndt-primary);border-color:var(--ndt-primary)}.button.icon-only{padding:var(--ndt-spacing-xs);width:32px;height:32px;justify-content:center}.button.small{font-size:var(--ndt-font-size-sm)}\n"] }]
3030
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".button{display:inline-flex;align-items:center;gap:var(--ndt-spacing-xs);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);min-height:36px;border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:var(--ndt-bg-primary);color:var(--ndt-text-primary);cursor:pointer;transition:var(--ndt-transition-default);outline:none;font-family:inherit}.button:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary)}.button:focus-visible{outline:none;background:var(--ndt-hover-bg);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2)}.button.primary{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.button.primary:hover{background:var(--ndt-primary);border-color:var(--ndt-primary)}.button.icon-only{padding:var(--ndt-spacing-xs);width:32px;height:32px;justify-content:center}.button.small{font-size:var(--ndt-font-size-sm)}\n"] }]
2385
3031
  }] });
2386
3032
 
2387
3033
  class DevToolbarCardComponent {
@@ -2451,7 +3097,7 @@ class DevToolbarClickableCardComponent {
2451
3097
  </div>
2452
3098
  </div>
2453
3099
  </ndt-card>
2454
- `, isInline: true, styles: [".clickable-card{display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);height:100%}.clickable-card__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.clickable-card__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.clickable-card__title{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.clickable-card__subtitle{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n"], dependencies: [{ kind: "component", type: DevToolbarCardComponent, selector: "ndt-card" }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }] }); }
3100
+ `, isInline: true, styles: [".clickable-card{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);height:100%}.clickable-card__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.clickable-card__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.clickable-card__title{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.clickable-card__subtitle{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n"], dependencies: [{ kind: "component", type: DevToolbarCardComponent, selector: "ndt-card" }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }] }); }
2455
3101
  }
2456
3102
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarClickableCardComponent, decorators: [{
2457
3103
  type: Component,
@@ -2467,7 +3113,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2467
3113
  </div>
2468
3114
  </div>
2469
3115
  </ndt-card>
2470
- `, styles: [".clickable-card{display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);height:100%}.clickable-card__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.clickable-card__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.clickable-card__title{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.clickable-card__subtitle{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n"] }]
3116
+ `, styles: [".clickable-card{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);height:100%}.clickable-card__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.clickable-card__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.clickable-card__title{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.clickable-card__subtitle{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n"] }]
2471
3117
  }] });
2472
3118
 
2473
3119
  class DevToolbarLinkButtonComponent {
@@ -2694,7 +3340,7 @@ class DevToolbarHomeToolComponent {
2694
3340
  </div>
2695
3341
  </section>
2696
3342
  </ndt-toolbar-tool>
2697
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.settings{display:flex;flex-direction:column;justify-content:space-between;min-height:100%}.instruction{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--ndt-spacing-md)}.instruction__label{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.instruction__label-text{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.instruction__label-description{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs)}.instruction__control{flex:1}.instruction__control-button{display:flex;gap:var(--ndt-spacing-xs);justify-content:flex-end}.settings-container{display:flex;flex-direction:column}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md);padding-block:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{border-top:1px solid var(--ndt-border-subtle);padding-top:1em;display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"], dependencies: [{ kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: DevToolbarClickableCardComponent, selector: "ndt-clickable-card", inputs: ["icon", "title", "subtitle"] }, { kind: "component", type: DevToolbarLinkButtonComponent, selector: "ndt-link-button", inputs: ["url", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3343
+ `, isInline: true, styles: [".settings{display:flex;flex-direction:column;justify-content:space-between;min-height:100%}.instruction{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--ndt-spacing-sm)}.instruction__label{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.instruction__label-text{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.instruction__label-description{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs)}.instruction__control{flex:1}.instruction__control-button{display:flex;gap:var(--ndt-spacing-xs);justify-content:flex-end}.settings-container{display:flex;flex-direction:column}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md);padding-block:var(--ndt-spacing-sm)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{border-top:1px solid var(--ndt-border-subtle);padding-top:1em;display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"], dependencies: [{ kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: DevToolbarClickableCardComponent, selector: "ndt-clickable-card", inputs: ["icon", "title", "subtitle"] }, { kind: "component", type: DevToolbarLinkButtonComponent, selector: "ndt-link-button", inputs: ["url", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2698
3344
  }
2699
3345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarHomeToolComponent, decorators: [{
2700
3346
  type: Component,
@@ -2775,7 +3421,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2775
3421
  </div>
2776
3422
  </section>
2777
3423
  </ndt-toolbar-tool>
2778
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.settings{display:flex;flex-direction:column;justify-content:space-between;min-height:100%}.instruction{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--ndt-spacing-md)}.instruction__label{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.instruction__label-text{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.instruction__label-description{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs)}.instruction__control{flex:1}.instruction__control-button{display:flex;gap:var(--ndt-spacing-xs);justify-content:flex-end}.settings-container{display:flex;flex-direction:column}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md);padding-block:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{border-top:1px solid var(--ndt-border-subtle);padding-top:1em;display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"] }]
3424
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".settings{display:flex;flex-direction:column;justify-content:space-between;min-height:100%}.instruction{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--ndt-spacing-sm)}.instruction__label{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.instruction__label-text{color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);font-weight:500}.instruction__label-description{color:var(--ndt-text-muted);font-size:var(--ndt-font-size-xs)}.instruction__control{flex:1}.instruction__control-button{display:flex;gap:var(--ndt-spacing-xs);justify-content:flex-end}.settings-container{display:flex;flex-direction:column}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md);padding-block:var(--ndt-spacing-sm)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{border-top:1px solid var(--ndt-border-subtle);padding-top:1em;display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"] }]
2779
3425
  }] });
2780
3426
 
2781
3427
  class DevToolbarInternalLanguageService {
@@ -2810,6 +3456,32 @@ class DevToolbarInternalLanguageService {
2810
3456
  this.forcedLanguage$.next(savedLanguage);
2811
3457
  }
2812
3458
  }
3459
+ /**
3460
+ * Apply language from a preset (used by Presets Tool)
3461
+ * Accepts a language ID and finds the corresponding Language object from available languages
3462
+ */
3463
+ async applyPresetLanguage(languageId) {
3464
+ if (languageId === null) {
3465
+ this.removeForcedLanguage();
3466
+ return;
3467
+ }
3468
+ // Get available languages and find matching one
3469
+ const languages = await firstValueFrom(this.languages$);
3470
+ const language = languages.find((lang) => lang.id === languageId);
3471
+ if (language) {
3472
+ this.setForcedLanguage(language);
3473
+ }
3474
+ else {
3475
+ console.warn(`Language ${languageId} not found in available languages. Skipping.`);
3476
+ }
3477
+ }
3478
+ /**
3479
+ * Get current forced language ID for saving to preset
3480
+ * Returns the language ID or null if no language is forced
3481
+ */
3482
+ getCurrentForcedLanguage() {
3483
+ return this.forcedLanguage$.value?.id ?? null;
3484
+ }
2813
3485
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalLanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2814
3486
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalLanguageService, providedIn: 'root' }); }
2815
3487
  }
@@ -2883,18 +3555,923 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2883
3555
  `, styles: [".language-select{display:flex;flex-direction:row;gap:.5rem;align-items:center;justify-content:space-between}\n"] }]
2884
3556
  }] });
2885
3557
 
2886
- class DevToolbarComponent {
3558
+ class DevToolbarInternalPermissionsService {
2887
3559
  constructor() {
2888
- this.state = inject(DevToolbarStateService);
2889
- this.destroyRef = inject(DestroyRef);
2890
- this.settingsService = inject(SettingsService);
2891
- this.isDevMode = isDevMode();
2892
- this.keyboardShortcut = fromEvent(window, 'keydown')
2893
- .pipe(filter((event) => event.ctrlKey && event.shiftKey && event.key === 'D'), takeUntilDestroyed(this.destroyRef))
2894
- .subscribe(() => this.toggleDevTools());
2895
- this.mouseLeave = fromEvent(document, 'mouseleave')
2896
- .pipe(throttleTime(3000), takeUntilDestroyed(this.destroyRef))
2897
- .subscribe(() => this.onMouseLeave());
3560
+ this.STORAGE_KEY = 'permissions';
3561
+ this.storageService = inject(DevToolsStorageService);
3562
+ this.appPermissions$ = new BehaviorSubject([]);
3563
+ this.forcedStateSubject = new BehaviorSubject({
3564
+ granted: [],
3565
+ denied: [],
3566
+ });
3567
+ this.forcedState$ = this.forcedStateSubject.asObservable();
3568
+ this.permissions$ = combineLatest([
3569
+ this.appPermissions$,
3570
+ this.forcedState$,
3571
+ ]).pipe(map(([appPermissions, { granted, denied }]) => {
3572
+ return appPermissions.map((permission) => ({
3573
+ ...permission,
3574
+ isForced: granted.includes(permission.id) || denied.includes(permission.id),
3575
+ isGranted: granted.includes(permission.id)
3576
+ ? true
3577
+ : denied.includes(permission.id)
3578
+ ? false
3579
+ : permission.isGranted,
3580
+ }));
3581
+ }));
3582
+ this.permissions = toSignal(this.permissions$, { initialValue: [] });
3583
+ this.loadForcedState();
3584
+ }
3585
+ setAppPermissions(permissions) {
3586
+ this.appPermissions$.next(permissions);
3587
+ this.validateAndCleanForcedState(permissions);
3588
+ }
3589
+ setPermission(id, granted) {
3590
+ const { granted: grantedIds, denied: deniedIds } = this.forcedStateSubject.value;
3591
+ const newGranted = grantedIds.filter((permId) => permId !== id);
3592
+ const newDenied = deniedIds.filter((permId) => permId !== id);
3593
+ if (granted) {
3594
+ newGranted.push(id);
3595
+ }
3596
+ else {
3597
+ newDenied.push(id);
3598
+ }
3599
+ const newState = { granted: newGranted, denied: newDenied };
3600
+ this.forcedStateSubject.next(newState);
3601
+ this.storageService.set(this.STORAGE_KEY, newState);
3602
+ }
3603
+ removePermissionOverride(id) {
3604
+ const { granted, denied } = this.forcedStateSubject.value;
3605
+ const newState = {
3606
+ granted: granted.filter((permId) => permId !== id),
3607
+ denied: denied.filter((permId) => permId !== id),
3608
+ };
3609
+ this.forcedStateSubject.next(newState);
3610
+ this.storageService.set(this.STORAGE_KEY, newState);
3611
+ }
3612
+ getForcedPermissions() {
3613
+ return this.permissions$.pipe(map((permissions) => permissions.filter((permission) => permission.isForced)));
3614
+ }
3615
+ /**
3616
+ * Apply a preset permissions state, replacing the current forced state.
3617
+ * Useful for automated testing or restoring saved configurations.
3618
+ * @param state The preset forced permissions state to apply
3619
+ */
3620
+ applyPresetPermissions(state) {
3621
+ this.forcedStateSubject.next(state);
3622
+ this.storageService.set(this.STORAGE_KEY, state);
3623
+ }
3624
+ /**
3625
+ * Get the current forced permissions state.
3626
+ * Returns a deep copy to prevent external mutations.
3627
+ * @returns Current forced permissions state
3628
+ */
3629
+ getCurrentForcedState() {
3630
+ const currentState = this.forcedStateSubject.value;
3631
+ return {
3632
+ granted: [...currentState.granted],
3633
+ denied: [...currentState.denied],
3634
+ };
3635
+ }
3636
+ loadForcedState() {
3637
+ try {
3638
+ const savedState = this.storageService.get(this.STORAGE_KEY);
3639
+ if (savedState && this.isValidForcedState(savedState)) {
3640
+ this.forcedStateSubject.next(savedState);
3641
+ }
3642
+ }
3643
+ catch (error) {
3644
+ console.warn('Error loading forced permissions state from localStorage:', error);
3645
+ }
3646
+ }
3647
+ isValidForcedState(state) {
3648
+ return (state &&
3649
+ typeof state === 'object' &&
3650
+ Array.isArray(state.granted) &&
3651
+ Array.isArray(state.denied));
3652
+ }
3653
+ validateAndCleanForcedState(permissions) {
3654
+ const currentState = this.forcedStateSubject.value;
3655
+ const validIds = new Set(permissions.map((p) => p.id));
3656
+ const cleanedGranted = currentState.granted.filter((id) => validIds.has(id));
3657
+ const cleanedDenied = currentState.denied.filter((id) => validIds.has(id));
3658
+ const hasInvalidIds = cleanedGranted.length !== currentState.granted.length ||
3659
+ cleanedDenied.length !== currentState.denied.length;
3660
+ if (hasInvalidIds) {
3661
+ const cleanedState = {
3662
+ granted: cleanedGranted,
3663
+ denied: cleanedDenied,
3664
+ };
3665
+ this.forcedStateSubject.next(cleanedState);
3666
+ this.storageService.set(this.STORAGE_KEY, cleanedState);
3667
+ const invalidIds = [
3668
+ ...currentState.granted.filter((id) => !validIds.has(id)),
3669
+ ...currentState.denied.filter((id) => !validIds.has(id)),
3670
+ ];
3671
+ if (invalidIds.length > 0) {
3672
+ console.warn('Removed invalid permission IDs from forced state:', invalidIds);
3673
+ }
3674
+ }
3675
+ }
3676
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3677
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPermissionsService, providedIn: 'root' }); }
3678
+ }
3679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPermissionsService, decorators: [{
3680
+ type: Injectable,
3681
+ args: [{ providedIn: 'root' }]
3682
+ }], ctorParameters: () => [] });
3683
+
3684
+ class DevToolbarPermissionsToolComponent {
3685
+ constructor() {
3686
+ // Injects
3687
+ this.permissionsService = inject(DevToolbarInternalPermissionsService);
3688
+ // Signals
3689
+ this.activeFilter = signal('all');
3690
+ this.searchQuery = signal('');
3691
+ this.permissions = this.permissionsService.permissions;
3692
+ this.hasNoPermissions = computed(() => this.permissions().length === 0);
3693
+ this.filteredPermissions = computed(() => {
3694
+ return this.permissions().filter((permission) => {
3695
+ const searchTerm = this.searchQuery().toLowerCase();
3696
+ const permissionName = permission.name.toLowerCase();
3697
+ const permissionDescription = permission.description?.toLowerCase() ?? '';
3698
+ const matchesSearch = !this.searchQuery() ||
3699
+ permissionName.includes(searchTerm) ||
3700
+ permissionDescription.includes(searchTerm);
3701
+ const matchesFilter = this.activeFilter() === 'all' ||
3702
+ (this.activeFilter() === 'forced' && permission.isForced) ||
3703
+ (this.activeFilter() === 'granted' && permission.isGranted) ||
3704
+ (this.activeFilter() === 'denied' && !permission.isGranted);
3705
+ return matchesSearch && matchesFilter;
3706
+ });
3707
+ });
3708
+ this.hasNoFilteredPermissions = computed(() => this.filteredPermissions().length === 0);
3709
+ // Other properties
3710
+ this.options = {
3711
+ title: 'Permissions',
3712
+ description: 'Manage permission overrides for your current session',
3713
+ isClosable: true,
3714
+ size: 'tall',
3715
+ id: 'ndt-permissions',
3716
+ isBeta: true,
3717
+ };
3718
+ this.filterOptions = [
3719
+ { value: 'all', label: 'All Permissions' },
3720
+ { value: 'forced', label: 'Forced' },
3721
+ { value: 'granted', label: 'Granted' },
3722
+ { value: 'denied', label: 'Denied' },
3723
+ ];
3724
+ this.permissionValueOptions = [
3725
+ { value: 'not-forced', label: 'Not Forced' },
3726
+ { value: 'denied', label: 'Forced Denied' },
3727
+ { value: 'granted', label: 'Forced Granted' },
3728
+ ];
3729
+ }
3730
+ // Public methods
3731
+ onFilterChange(value) {
3732
+ const filter = this.filterOptions.find((f) => f.value === value);
3733
+ if (filter) {
3734
+ this.activeFilter.set(filter.value);
3735
+ }
3736
+ }
3737
+ onPermissionChange(id, value) {
3738
+ switch (value) {
3739
+ case 'not-forced':
3740
+ this.permissionsService.removePermissionOverride(id);
3741
+ break;
3742
+ case 'granted':
3743
+ this.permissionsService.setPermission(id, true);
3744
+ break;
3745
+ case 'denied':
3746
+ this.permissionsService.setPermission(id, false);
3747
+ break;
3748
+ }
3749
+ }
3750
+ onSearchChange(query) {
3751
+ this.searchQuery.set(query);
3752
+ }
3753
+ // Protected methods
3754
+ getPermissionValue(permission) {
3755
+ if (!permission.isForced)
3756
+ return '';
3757
+ return permission.isGranted ? 'granted' : 'denied';
3758
+ }
3759
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPermissionsToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3760
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarPermissionsToolComponent, isStandalone: true, selector: "ndt-permissions-tool", ngImport: i0, template: `
3761
+ <ndt-toolbar-tool
3762
+ [options]="options"
3763
+ title="Permissions"
3764
+ icon="lock"
3765
+ >
3766
+ <div class="container">
3767
+ <div class="header">
3768
+ <ndt-input
3769
+ [value]="searchQuery()"
3770
+ (valueChange)="onSearchChange($event)"
3771
+ placeholder="Search permissions..."
3772
+ [ariaLabel]="'Search permissions'"
3773
+ />
3774
+ <div class="filter-wrapper">
3775
+ <ndt-icon name="filter" class="filter-icon" />
3776
+ <ndt-select
3777
+ [value]="activeFilter()"
3778
+ [options]="filterOptions"
3779
+ [size]="'medium'"
3780
+ (valueChange)="onFilterChange($event)"
3781
+ [ariaLabel]="'Filter permissions by state'"
3782
+ />
3783
+ </div>
3784
+ </div>
3785
+
3786
+ @if (hasNoPermissions()) {
3787
+ <div class="empty">
3788
+ <p>No permissions found</p>
3789
+ <p class="hint">Call setAvailableOptions() to configure permissions</p>
3790
+ </div>
3791
+ } @else if (hasNoFilteredPermissions()) {
3792
+ <div class="empty">
3793
+ <p>No permissions match your filter</p>
3794
+ </div>
3795
+ } @else {
3796
+ <div class="permission-list">
3797
+ @for (permission of filteredPermissions(); track permission.id) {
3798
+ <div class="permission">
3799
+ <div class="info">
3800
+ <h3>{{ permission.name }}</h3>
3801
+ <p>{{ permission?.description }}</p>
3802
+ </div>
3803
+
3804
+ <ndt-select
3805
+ [value]="getPermissionValue(permission)"
3806
+ [options]="permissionValueOptions"
3807
+ [ariaLabel]="'Override state for ' + permission.name"
3808
+ (valueChange)="onPermissionChange(permission.id, $event ?? '')"
3809
+ size="small"
3810
+ />
3811
+ </div>
3812
+ }
3813
+ </div>
3814
+ }
3815
+ </div>
3816
+ </ndt-toolbar-tool>
3817
+ `, isInline: true, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.empty p{margin:0}.empty .hint{font-size:var(--ndt-font-size-xs)}.permission-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.permission-list::-webkit-scrollbar{width:8px}.permission-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.permission-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.permission{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.permission .info{flex:0 0 65%}.permission .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.permission .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.permission ndt-select{flex:0 0 35%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "component", type: DevToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3818
+ }
3819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPermissionsToolComponent, decorators: [{
3820
+ type: Component,
3821
+ args: [{ selector: 'ndt-permissions-tool', standalone: true, imports: [
3822
+ FormsModule,
3823
+ DevToolbarToolComponent,
3824
+ DevToolbarInputComponent,
3825
+ DevToolbarSelectComponent,
3826
+ DevToolbarIconComponent,
3827
+ ], template: `
3828
+ <ndt-toolbar-tool
3829
+ [options]="options"
3830
+ title="Permissions"
3831
+ icon="lock"
3832
+ >
3833
+ <div class="container">
3834
+ <div class="header">
3835
+ <ndt-input
3836
+ [value]="searchQuery()"
3837
+ (valueChange)="onSearchChange($event)"
3838
+ placeholder="Search permissions..."
3839
+ [ariaLabel]="'Search permissions'"
3840
+ />
3841
+ <div class="filter-wrapper">
3842
+ <ndt-icon name="filter" class="filter-icon" />
3843
+ <ndt-select
3844
+ [value]="activeFilter()"
3845
+ [options]="filterOptions"
3846
+ [size]="'medium'"
3847
+ (valueChange)="onFilterChange($event)"
3848
+ [ariaLabel]="'Filter permissions by state'"
3849
+ />
3850
+ </div>
3851
+ </div>
3852
+
3853
+ @if (hasNoPermissions()) {
3854
+ <div class="empty">
3855
+ <p>No permissions found</p>
3856
+ <p class="hint">Call setAvailableOptions() to configure permissions</p>
3857
+ </div>
3858
+ } @else if (hasNoFilteredPermissions()) {
3859
+ <div class="empty">
3860
+ <p>No permissions match your filter</p>
3861
+ </div>
3862
+ } @else {
3863
+ <div class="permission-list">
3864
+ @for (permission of filteredPermissions(); track permission.id) {
3865
+ <div class="permission">
3866
+ <div class="info">
3867
+ <h3>{{ permission.name }}</h3>
3868
+ <p>{{ permission?.description }}</p>
3869
+ </div>
3870
+
3871
+ <ndt-select
3872
+ [value]="getPermissionValue(permission)"
3873
+ [options]="permissionValueOptions"
3874
+ [ariaLabel]="'Override state for ' + permission.name"
3875
+ (valueChange)="onPermissionChange(permission.id, $event ?? '')"
3876
+ size="small"
3877
+ />
3878
+ </div>
3879
+ }
3880
+ </div>
3881
+ }
3882
+ </div>
3883
+ </ndt-toolbar-tool>
3884
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header .filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md)}.header .filter-wrapper .filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}.header .filter-wrapper ndt-select{flex:0 0 auto;min-width:180px}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-warning-border);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-warning-background);color:var(--ndt-text-muted)}.empty p{margin:0}.empty .hint{font-size:var(--ndt-font-size-xs)}.permission-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.permission-list::-webkit-scrollbar{width:8px}.permission-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.permission-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.permission{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary)}.permission .info{flex:0 0 65%}.permission .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.permission .info p{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.permission ndt-select{flex:0 0 35%}\n"] }]
3885
+ }] });
3886
+
3887
+ /**
3888
+ * Internal service for managing presets state.
3889
+ * Handles CRUD operations, captures current toolbar config, and applies presets.
3890
+ */
3891
+ class DevToolbarInternalPresetsService {
3892
+ constructor() {
3893
+ this.STORAGE_KEY = 'presets';
3894
+ this.storageService = inject(DevToolsStorageService);
3895
+ // Inject all other tool internal services (for reading/writing state)
3896
+ this.featureFlagsService = inject(DevToolbarInternalFeatureFlagService);
3897
+ this.languageService = inject(DevToolbarInternalLanguageService);
3898
+ this.permissionsService = inject(DevToolbarInternalPermissionsService);
3899
+ this.appFeaturesService = inject(DevToolbarInternalAppFeaturesService);
3900
+ this.presetsSubject = new BehaviorSubject([]);
3901
+ this.presets$ = this.presetsSubject.asObservable();
3902
+ this.presets = toSignal(this.presets$, { initialValue: [] });
3903
+ this.loadPresets();
3904
+ }
3905
+ /**
3906
+ * Capture current toolbar state as a new preset
3907
+ */
3908
+ saveCurrentAsPreset(name, description) {
3909
+ const preset = {
3910
+ id: this.generateId(),
3911
+ name,
3912
+ description,
3913
+ createdAt: new Date().toISOString(),
3914
+ updatedAt: new Date().toISOString(),
3915
+ config: this.captureCurrentConfig(),
3916
+ };
3917
+ const presets = [...this.presetsSubject.value, preset];
3918
+ this.presetsSubject.next(presets);
3919
+ this.storageService.set(this.STORAGE_KEY, presets);
3920
+ return preset;
3921
+ }
3922
+ /**
3923
+ * Apply a preset to all tools (THIS IS THE KEY METHOD)
3924
+ */
3925
+ async applyPreset(presetId) {
3926
+ const preset = this.presetsSubject.value.find((p) => p.id === presetId);
3927
+ if (!preset)
3928
+ return;
3929
+ // Apply to each tool's internal service
3930
+ this.featureFlagsService.applyPresetFlags(preset.config.featureFlags);
3931
+ await this.languageService.applyPresetLanguage(preset.config.language);
3932
+ this.permissionsService.applyPresetPermissions(preset.config.permissions);
3933
+ this.appFeaturesService.applyForcedState(preset.config.appFeatures);
3934
+ }
3935
+ /**
3936
+ * Update an existing preset with current toolbar state
3937
+ */
3938
+ updatePreset(presetId) {
3939
+ const presets = this.presetsSubject.value.map((preset) => {
3940
+ if (preset.id === presetId) {
3941
+ return {
3942
+ ...preset,
3943
+ updatedAt: new Date().toISOString(),
3944
+ config: this.captureCurrentConfig(),
3945
+ };
3946
+ }
3947
+ return preset;
3948
+ });
3949
+ this.presetsSubject.next(presets);
3950
+ this.storageService.set(this.STORAGE_KEY, presets);
3951
+ }
3952
+ /**
3953
+ * Delete a preset
3954
+ */
3955
+ deletePreset(presetId) {
3956
+ const presets = this.presetsSubject.value.filter((p) => p.id !== presetId);
3957
+ this.presetsSubject.next(presets);
3958
+ this.storageService.set(this.STORAGE_KEY, presets);
3959
+ }
3960
+ /**
3961
+ * Add a preset (used for import)
3962
+ */
3963
+ addPreset(preset) {
3964
+ // Generate new ID to avoid conflicts
3965
+ const newPreset = {
3966
+ ...preset,
3967
+ id: this.generateId(),
3968
+ createdAt: new Date().toISOString(),
3969
+ updatedAt: new Date().toISOString(),
3970
+ };
3971
+ const presets = [...this.presetsSubject.value, newPreset];
3972
+ this.presetsSubject.next(presets);
3973
+ this.storageService.set(this.STORAGE_KEY, presets);
3974
+ return newPreset;
3975
+ }
3976
+ /**
3977
+ * Get a preset by ID
3978
+ */
3979
+ getPresetById(presetId) {
3980
+ return this.presetsSubject.value.find((p) => p.id === presetId);
3981
+ }
3982
+ /**
3983
+ * Capture current configuration from all tools
3984
+ */
3985
+ captureCurrentConfig() {
3986
+ return {
3987
+ featureFlags: this.featureFlagsService.getCurrentForcedState(),
3988
+ language: this.languageService.getCurrentForcedLanguage(),
3989
+ permissions: this.permissionsService.getCurrentForcedState(),
3990
+ appFeatures: this.appFeaturesService.getCurrentForcedState(),
3991
+ };
3992
+ }
3993
+ /**
3994
+ * Load presets from localStorage
3995
+ */
3996
+ loadPresets() {
3997
+ try {
3998
+ const saved = this.storageService.get(this.STORAGE_KEY);
3999
+ if (saved && Array.isArray(saved)) {
4000
+ this.presetsSubject.next(saved);
4001
+ }
4002
+ }
4003
+ catch (error) {
4004
+ console.error('Failed to load presets from localStorage:', error);
4005
+ }
4006
+ }
4007
+ /**
4008
+ * Generate unique preset ID
4009
+ */
4010
+ generateId() {
4011
+ return `preset-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4012
+ }
4013
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPresetsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4014
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPresetsService, providedIn: 'root' }); }
4015
+ }
4016
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarInternalPresetsService, decorators: [{
4017
+ type: Injectable,
4018
+ args: [{ providedIn: 'root' }]
4019
+ }], ctorParameters: () => [] });
4020
+
4021
+ class DevToolbarPresetsToolComponent {
4022
+ constructor() {
4023
+ // Injects
4024
+ this.presetsService = inject(DevToolbarInternalPresetsService);
4025
+ this.featureFlagsService = inject(DevToolbarInternalFeatureFlagService);
4026
+ this.permissionsService = inject(DevToolbarInternalPermissionsService);
4027
+ this.appFeaturesService = inject(DevToolbarInternalAppFeaturesService);
4028
+ this.languageService = inject(DevToolbarInternalLanguageService);
4029
+ // Signals
4030
+ this.viewMode = signal('list');
4031
+ this.searchQuery = signal('');
4032
+ this.presetName = signal('');
4033
+ this.presetDescription = signal('');
4034
+ this.presets = this.presetsService.presets;
4035
+ this.filteredPresets = computed(() => {
4036
+ const query = this.searchQuery().toLowerCase();
4037
+ return this.presets().filter((preset) => preset.name.toLowerCase().includes(query) ||
4038
+ preset.description?.toLowerCase().includes(query));
4039
+ });
4040
+ this.hasNoPresets = computed(() => this.presets().length === 0);
4041
+ this.hasNoFilteredPresets = computed(() => this.filteredPresets().length === 0);
4042
+ // Other properties
4043
+ this.options = {
4044
+ title: 'Presets',
4045
+ description: 'Save and load toolbar configurations',
4046
+ isClosable: true,
4047
+ size: 'tall',
4048
+ id: 'ndt-presets',
4049
+ isBeta: true,
4050
+ };
4051
+ }
4052
+ // Public methods
4053
+ onSearchChange(query) {
4054
+ this.searchQuery.set(query);
4055
+ }
4056
+ onSwitchToCreateMode() {
4057
+ this.viewMode.set('create');
4058
+ this.presetName.set('');
4059
+ this.presetDescription.set('');
4060
+ }
4061
+ onSwitchToListMode() {
4062
+ this.viewMode.set('list');
4063
+ }
4064
+ onSavePreset(event) {
4065
+ event.preventDefault();
4066
+ if (!this.presetName())
4067
+ return;
4068
+ this.presetsService.saveCurrentAsPreset(this.presetName(), this.presetDescription());
4069
+ this.onSwitchToListMode();
4070
+ }
4071
+ onApplyPreset(presetId) {
4072
+ this.presetsService.applyPreset(presetId);
4073
+ }
4074
+ onUpdatePreset(presetId) {
4075
+ this.presetsService.updatePreset(presetId);
4076
+ }
4077
+ onExportPreset(presetId) {
4078
+ const preset = this.presets().find((p) => p.id === presetId);
4079
+ if (!preset)
4080
+ return;
4081
+ const json = JSON.stringify(preset, null, 2);
4082
+ const blob = new Blob([json], { type: 'application/json' });
4083
+ const url = URL.createObjectURL(blob);
4084
+ const link = document.createElement('a');
4085
+ link.href = url;
4086
+ link.download = `preset-${preset.name.toLowerCase().replace(/\s+/g, '-')}.json`;
4087
+ link.click();
4088
+ URL.revokeObjectURL(url);
4089
+ }
4090
+ onDeletePreset(presetId) {
4091
+ if (confirm('Are you sure you want to delete this preset?')) {
4092
+ this.presetsService.deletePreset(presetId);
4093
+ }
4094
+ }
4095
+ // Protected methods
4096
+ getCurrentFlagsCount() {
4097
+ const state = this.featureFlagsService.getCurrentForcedState();
4098
+ return state.enabled.length + state.disabled.length;
4099
+ }
4100
+ getCurrentPermissionsCount() {
4101
+ const state = this.permissionsService.getCurrentForcedState();
4102
+ return state.granted.length + state.denied.length;
4103
+ }
4104
+ getCurrentAppFeaturesCount() {
4105
+ const state = this.appFeaturesService.getCurrentForcedState();
4106
+ return state.enabled.length + state.disabled.length;
4107
+ }
4108
+ getCurrentLanguage() {
4109
+ return this.languageService.getCurrentForcedLanguage() || 'Not Forced';
4110
+ }
4111
+ formatDate(isoString) {
4112
+ return new Date(isoString).toLocaleDateString();
4113
+ }
4114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPresetsToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarPresetsToolComponent, isStandalone: true, selector: "ndt-presets-tool", ngImport: i0, template: `
4116
+ <ndt-toolbar-tool [options]="options" title="Presets" icon="layout">
4117
+ <div class="container">
4118
+ <!-- Mode Toggle -->
4119
+ @if (!hasNoPresets() || viewMode() === 'create') {
4120
+ <div class="header">
4121
+ @if (viewMode() === 'list') {
4122
+ <ndt-input
4123
+ [value]="searchQuery()"
4124
+ (valueChange)="onSearchChange($event)"
4125
+ placeholder="Search presets..."
4126
+ [ariaLabel]="'Search presets'"
4127
+ />
4128
+ <ndt-button
4129
+ (click)="onSwitchToCreateMode()"
4130
+ [ariaLabel]="'Create new preset'"
4131
+ >
4132
+ New Preset
4133
+ </ndt-button>
4134
+ } @else {
4135
+ <ndt-button
4136
+ (click)="onSwitchToListMode()"
4137
+ [ariaLabel]="'Back to list'"
4138
+ >
4139
+ ← Back to List
4140
+ </ndt-button>
4141
+ }
4142
+ </div>
4143
+ }
4144
+
4145
+ <!-- Create Form -->
4146
+ @if (viewMode() === 'create') {
4147
+ <form (submit)="onSavePreset($event)" class="preset-form">
4148
+ <ndt-input
4149
+ label="Preset Name"
4150
+ [value]="presetName()"
4151
+ (valueChange)="presetName.set($event)"
4152
+ placeholder="e.g., Admin User - Full Access"
4153
+ [ariaLabel]="'Preset name'"
4154
+ />
4155
+ <ndt-input
4156
+ label="Description (optional)"
4157
+ [value]="presetDescription()"
4158
+ (valueChange)="presetDescription.set($event)"
4159
+ placeholder="Brief description of this preset"
4160
+ [ariaLabel]="'Preset description'"
4161
+ />
4162
+
4163
+ <!-- Summary of what will be saved -->
4164
+ <div class="preset-summary">
4165
+ <h4>Configuration to Save:</h4>
4166
+ <ul>
4167
+ <li>Feature Flags: {{ getCurrentFlagsCount() }} forced</li>
4168
+ <li>Permissions: {{ getCurrentPermissionsCount() }} forced</li>
4169
+ <li>App Features: {{ getCurrentAppFeaturesCount() }} forced</li>
4170
+ <li>Language: {{ getCurrentLanguage() }}</li>
4171
+ </ul>
4172
+ </div>
4173
+
4174
+ <div class="form-actions">
4175
+ <ndt-button type="submit">Save Preset</ndt-button>
4176
+ </div>
4177
+ </form>
4178
+ }
4179
+
4180
+ <!-- Empty State -->
4181
+ @if (viewMode() === 'list' && hasNoPresets()) {
4182
+ <div class="empty">
4183
+ <p>No presets saved yet</p>
4184
+ <p class="hint">
4185
+ Save the current toolbar configuration as a preset for quick access
4186
+ </p>
4187
+ <ndt-button (click)="onSwitchToCreateMode()">
4188
+ Create Your First Preset
4189
+ </ndt-button>
4190
+ </div>
4191
+ } @else if (viewMode() === 'list' && hasNoFilteredPresets()) {
4192
+ <div class="empty">
4193
+ <p>No presets match your search</p>
4194
+ </div>
4195
+ } @else if (viewMode() === 'list') {
4196
+ <!-- Preset List -->
4197
+ <div class="preset-list">
4198
+ @for (preset of filteredPresets(); track preset.id) {
4199
+ <div class="preset-card">
4200
+ <div class="preset-card__header">
4201
+ <h3>{{ preset.name }}</h3>
4202
+ <div class="preset-card__actions">
4203
+ <button
4204
+ class="icon-button"
4205
+ (click)="onApplyPreset(preset.id)"
4206
+ [attr.aria-label]="'Apply preset ' + preset.name"
4207
+ title="Apply preset"
4208
+ >
4209
+ <ndt-icon name="refresh" />
4210
+ </button>
4211
+ <button
4212
+ class="icon-button"
4213
+ (click)="onUpdatePreset(preset.id)"
4214
+ [attr.aria-label]="'Update preset ' + preset.name"
4215
+ title="Update with current state"
4216
+ >
4217
+ <ndt-icon name="gear" />
4218
+ </button>
4219
+ <button
4220
+ class="icon-button"
4221
+ (click)="onExportPreset(preset.id)"
4222
+ [attr.aria-label]="'Export preset ' + preset.name"
4223
+ title="Export as JSON"
4224
+ >
4225
+ <ndt-icon name="export" />
4226
+ </button>
4227
+ <button
4228
+ class="icon-button"
4229
+ (click)="onDeletePreset(preset.id)"
4230
+ [attr.aria-label]="'Delete preset ' + preset.name"
4231
+ title="Delete preset"
4232
+ >
4233
+ <ndt-icon name="trash" />
4234
+ </button>
4235
+ </div>
4236
+ </div>
4237
+ @if (preset.description) {
4238
+ <p class="preset-card__description">{{ preset.description }}</p>
4239
+ }
4240
+ <div class="preset-card__meta">
4241
+ <span>Updated: {{ formatDate(preset.updatedAt) }}</span>
4242
+ </div>
4243
+ <!-- Preview of preset config -->
4244
+ <div class="preset-card__preview">
4245
+ @if (preset.config.featureFlags.enabled.length > 0 ||
4246
+ preset.config.featureFlags.disabled.length > 0) {
4247
+ <span class="badge">
4248
+ {{
4249
+ preset.config.featureFlags.enabled.length +
4250
+ preset.config.featureFlags.disabled.length
4251
+ }}
4252
+ flags
4253
+ </span>
4254
+ } @if (preset.config.permissions.granted.length > 0 ||
4255
+ preset.config.permissions.denied.length > 0) {
4256
+ <span class="badge">
4257
+ {{
4258
+ preset.config.permissions.granted.length +
4259
+ preset.config.permissions.denied.length
4260
+ }}
4261
+ perms
4262
+ </span>
4263
+ } @if (preset.config.appFeatures.enabled.length > 0 ||
4264
+ preset.config.appFeatures.disabled.length > 0) {
4265
+ <span class="badge">
4266
+ {{
4267
+ preset.config.appFeatures.enabled.length +
4268
+ preset.config.appFeatures.disabled.length
4269
+ }}
4270
+ features
4271
+ </span>
4272
+ } @if (preset.config.language) {
4273
+ <span class="badge">{{ preset.config.language }}</span>
4274
+ }
4275
+ </div>
4276
+ </div>
4277
+ }
4278
+ </div>
4279
+ }
4280
+ </div>
4281
+ </ndt-toolbar-tool>
4282
+ `, isInline: true, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header ndt-button{flex-shrink:0}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-border-subtle);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:transparent;color:var(--ndt-text-muted);text-align:center}.empty p{margin:0}.empty .hint{font-size:var(--ndt-font-size-xs)}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-list::-webkit-scrollbar{width:8px}.preset-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.preset-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.preset-card{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-sm)}.preset-card__header{display:flex;justify-content:space-between;align-items:center;gap:var(--ndt-spacing-sm)}.preset-card__header h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary);flex:1}.preset-card__actions{display:flex;gap:var(--ndt-spacing-xs)}.icon-button{background:transparent;border:none;cursor:pointer;padding:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);display:flex;align-items:center;justify-content:center}.icon-button:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.icon-button ndt-icon{width:16px;height:16px}.preset-card__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary)}.preset-card__meta{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.preset-card__meta span{margin-right:var(--ndt-spacing-sm)}.preset-card__preview{display:flex;gap:var(--ndt-spacing-xs);flex-wrap:wrap}.badge{background:var(--ndt-primary-color);color:#fff;padding:2px 8px;border-radius:12px;font-size:var(--ndt-font-size-xs);font-weight:500}.preset-form{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-md);padding:var(--ndt-spacing-md)}.preset-form ndt-input{width:100%}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium)}.preset-summary h4{margin:0 0 var(--ndt-spacing-sm) 0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.preset-summary ul{margin:0;padding-left:var(--ndt-spacing-md);color:var(--ndt-text-secondary);font-size:var(--ndt-font-size-sm)}.preset-summary ul li{margin-bottom:var(--ndt-spacing-xs)}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DevToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title"] }, { kind: "component", type: DevToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: DevToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: DevToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4283
+ }
4284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPresetsToolComponent, decorators: [{
4285
+ type: Component,
4286
+ args: [{ selector: 'ndt-presets-tool', standalone: true, imports: [
4287
+ FormsModule,
4288
+ DevToolbarToolComponent,
4289
+ DevToolbarInputComponent,
4290
+ DevToolbarButtonComponent,
4291
+ DevToolbarIconComponent,
4292
+ DevToolbarWindowComponent,
4293
+ ], template: `
4294
+ <ndt-toolbar-tool [options]="options" title="Presets" icon="layout">
4295
+ <div class="container">
4296
+ <!-- Mode Toggle -->
4297
+ @if (!hasNoPresets() || viewMode() === 'create') {
4298
+ <div class="header">
4299
+ @if (viewMode() === 'list') {
4300
+ <ndt-input
4301
+ [value]="searchQuery()"
4302
+ (valueChange)="onSearchChange($event)"
4303
+ placeholder="Search presets..."
4304
+ [ariaLabel]="'Search presets'"
4305
+ />
4306
+ <ndt-button
4307
+ (click)="onSwitchToCreateMode()"
4308
+ [ariaLabel]="'Create new preset'"
4309
+ >
4310
+ New Preset
4311
+ </ndt-button>
4312
+ } @else {
4313
+ <ndt-button
4314
+ (click)="onSwitchToListMode()"
4315
+ [ariaLabel]="'Back to list'"
4316
+ >
4317
+ ← Back to List
4318
+ </ndt-button>
4319
+ }
4320
+ </div>
4321
+ }
4322
+
4323
+ <!-- Create Form -->
4324
+ @if (viewMode() === 'create') {
4325
+ <form (submit)="onSavePreset($event)" class="preset-form">
4326
+ <ndt-input
4327
+ label="Preset Name"
4328
+ [value]="presetName()"
4329
+ (valueChange)="presetName.set($event)"
4330
+ placeholder="e.g., Admin User - Full Access"
4331
+ [ariaLabel]="'Preset name'"
4332
+ />
4333
+ <ndt-input
4334
+ label="Description (optional)"
4335
+ [value]="presetDescription()"
4336
+ (valueChange)="presetDescription.set($event)"
4337
+ placeholder="Brief description of this preset"
4338
+ [ariaLabel]="'Preset description'"
4339
+ />
4340
+
4341
+ <!-- Summary of what will be saved -->
4342
+ <div class="preset-summary">
4343
+ <h4>Configuration to Save:</h4>
4344
+ <ul>
4345
+ <li>Feature Flags: {{ getCurrentFlagsCount() }} forced</li>
4346
+ <li>Permissions: {{ getCurrentPermissionsCount() }} forced</li>
4347
+ <li>App Features: {{ getCurrentAppFeaturesCount() }} forced</li>
4348
+ <li>Language: {{ getCurrentLanguage() }}</li>
4349
+ </ul>
4350
+ </div>
4351
+
4352
+ <div class="form-actions">
4353
+ <ndt-button type="submit">Save Preset</ndt-button>
4354
+ </div>
4355
+ </form>
4356
+ }
4357
+
4358
+ <!-- Empty State -->
4359
+ @if (viewMode() === 'list' && hasNoPresets()) {
4360
+ <div class="empty">
4361
+ <p>No presets saved yet</p>
4362
+ <p class="hint">
4363
+ Save the current toolbar configuration as a preset for quick access
4364
+ </p>
4365
+ <ndt-button (click)="onSwitchToCreateMode()">
4366
+ Create Your First Preset
4367
+ </ndt-button>
4368
+ </div>
4369
+ } @else if (viewMode() === 'list' && hasNoFilteredPresets()) {
4370
+ <div class="empty">
4371
+ <p>No presets match your search</p>
4372
+ </div>
4373
+ } @else if (viewMode() === 'list') {
4374
+ <!-- Preset List -->
4375
+ <div class="preset-list">
4376
+ @for (preset of filteredPresets(); track preset.id) {
4377
+ <div class="preset-card">
4378
+ <div class="preset-card__header">
4379
+ <h3>{{ preset.name }}</h3>
4380
+ <div class="preset-card__actions">
4381
+ <button
4382
+ class="icon-button"
4383
+ (click)="onApplyPreset(preset.id)"
4384
+ [attr.aria-label]="'Apply preset ' + preset.name"
4385
+ title="Apply preset"
4386
+ >
4387
+ <ndt-icon name="refresh" />
4388
+ </button>
4389
+ <button
4390
+ class="icon-button"
4391
+ (click)="onUpdatePreset(preset.id)"
4392
+ [attr.aria-label]="'Update preset ' + preset.name"
4393
+ title="Update with current state"
4394
+ >
4395
+ <ndt-icon name="gear" />
4396
+ </button>
4397
+ <button
4398
+ class="icon-button"
4399
+ (click)="onExportPreset(preset.id)"
4400
+ [attr.aria-label]="'Export preset ' + preset.name"
4401
+ title="Export as JSON"
4402
+ >
4403
+ <ndt-icon name="export" />
4404
+ </button>
4405
+ <button
4406
+ class="icon-button"
4407
+ (click)="onDeletePreset(preset.id)"
4408
+ [attr.aria-label]="'Delete preset ' + preset.name"
4409
+ title="Delete preset"
4410
+ >
4411
+ <ndt-icon name="trash" />
4412
+ </button>
4413
+ </div>
4414
+ </div>
4415
+ @if (preset.description) {
4416
+ <p class="preset-card__description">{{ preset.description }}</p>
4417
+ }
4418
+ <div class="preset-card__meta">
4419
+ <span>Updated: {{ formatDate(preset.updatedAt) }}</span>
4420
+ </div>
4421
+ <!-- Preview of preset config -->
4422
+ <div class="preset-card__preview">
4423
+ @if (preset.config.featureFlags.enabled.length > 0 ||
4424
+ preset.config.featureFlags.disabled.length > 0) {
4425
+ <span class="badge">
4426
+ {{
4427
+ preset.config.featureFlags.enabled.length +
4428
+ preset.config.featureFlags.disabled.length
4429
+ }}
4430
+ flags
4431
+ </span>
4432
+ } @if (preset.config.permissions.granted.length > 0 ||
4433
+ preset.config.permissions.denied.length > 0) {
4434
+ <span class="badge">
4435
+ {{
4436
+ preset.config.permissions.granted.length +
4437
+ preset.config.permissions.denied.length
4438
+ }}
4439
+ perms
4440
+ </span>
4441
+ } @if (preset.config.appFeatures.enabled.length > 0 ||
4442
+ preset.config.appFeatures.disabled.length > 0) {
4443
+ <span class="badge">
4444
+ {{
4445
+ preset.config.appFeatures.enabled.length +
4446
+ preset.config.appFeatures.disabled.length
4447
+ }}
4448
+ features
4449
+ </span>
4450
+ } @if (preset.config.language) {
4451
+ <span class="badge">{{ preset.config.language }}</span>
4452
+ }
4453
+ </div>
4454
+ </div>
4455
+ }
4456
+ </div>
4457
+ }
4458
+ </div>
4459
+ </ndt-toolbar-tool>
4460
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{display:flex;flex-direction:column;height:100%}.header{flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md)}.header ndt-input{flex:1}.header ndt-button{flex-shrink:0}.empty{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ndt-border-subtle);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:transparent;color:var(--ndt-text-muted);text-align:center}.empty p{margin:0}.empty .hint{font-size:var(--ndt-font-size-xs)}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-sm);scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-list::-webkit-scrollbar{width:8px}.preset-list::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}.preset-list::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px}:is():hover{background:var(--ndt-hover-bg)}.preset-card{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-sm)}.preset-card__header{display:flex;justify-content:space-between;align-items:center;gap:var(--ndt-spacing-sm)}.preset-card__header h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary);flex:1}.preset-card__actions{display:flex;gap:var(--ndt-spacing-xs)}.icon-button{background:transparent;border:none;cursor:pointer;padding:var(--ndt-spacing-xs);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);display:flex;align-items:center;justify-content:center}.icon-button:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.icon-button ndt-icon{width:16px;height:16px}.preset-card__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary)}.preset-card__meta{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted)}.preset-card__meta span{margin-right:var(--ndt-spacing-sm)}.preset-card__preview{display:flex;gap:var(--ndt-spacing-xs);flex-wrap:wrap}.badge{background:var(--ndt-primary-color);color:#fff;padding:2px 8px;border-radius:12px;font-size:var(--ndt-font-size-xs);font-weight:500}.preset-form{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-md);padding:var(--ndt-spacing-md)}.preset-form ndt-input{width:100%}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-medium)}.preset-summary h4{margin:0 0 var(--ndt-spacing-sm) 0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.preset-summary ul{margin:0;padding-left:var(--ndt-spacing-md);color:var(--ndt-text-secondary);font-size:var(--ndt-font-size-sm)}.preset-summary ul li{margin-bottom:var(--ndt-spacing-xs)}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm)}\n"] }]
4461
+ }] });
4462
+
4463
+ class DevToolbarComponent {
4464
+ constructor() {
4465
+ this.state = inject(DevToolbarStateService);
4466
+ this.destroyRef = inject(DestroyRef);
4467
+ this.settingsService = inject(SettingsService);
4468
+ this.config = input({});
4469
+ this.keyboardShortcut = fromEvent(window, 'keydown')
4470
+ .pipe(filter((event) => event.ctrlKey && event.shiftKey && event.key === 'D'), takeUntilDestroyed(this.destroyRef))
4471
+ .subscribe(() => this.toggleDevTools());
4472
+ this.mouseLeave = fromEvent(document, 'mouseleave')
4473
+ .pipe(throttleTime(3000), takeUntilDestroyed(this.destroyRef))
4474
+ .subscribe(() => this.onMouseLeave());
2898
4475
  }
2899
4476
  ngOnInit() {
2900
4477
  const settings = this.settingsService.getSettings();
@@ -2910,8 +4487,7 @@ class DevToolbarComponent {
2910
4487
  this.state.setVisibility(!this.state.isVisible());
2911
4488
  }
2912
4489
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2913
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarComponent, isStandalone: true, selector: "ndt-toolbar", ngImport: i0, template: `
2914
- @if (isDevMode) {
4490
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: DevToolbarComponent, isStandalone: true, selector: "ndt-toolbar", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2915
4491
  <div
2916
4492
  aria-label="Developer tools"
2917
4493
  role="toolbar"
@@ -2922,12 +4498,24 @@ class DevToolbarComponent {
2922
4498
  (mouseenter)="onMouseEnter()"
2923
4499
  >
2924
4500
  <ndt-home-tool />
2925
- <ndt-language-tool />
2926
- <ndt-feature-flags-tool />
4501
+ @if (config().showLanguageTool ?? true) {
4502
+ <ndt-language-tool />
4503
+ }
4504
+ @if (config().showFeatureFlagsTool ?? true) {
4505
+ <ndt-feature-flags-tool />
4506
+ }
4507
+ @if (config().showAppFeaturesTool ?? true) {
4508
+ <ndt-app-features-tool />
4509
+ }
4510
+ @if (config().showPermissionsTool ?? true) {
4511
+ <ndt-permissions-tool />
4512
+ }
4513
+ @if (config().showPresetsTool ?? true) {
4514
+ <ndt-presets-tool />
4515
+ }
2927
4516
  <ng-content />
2928
4517
  </div>
2929
- }
2930
- `, isInline: true, styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.dev-toolbar{position:fixed;bottom:0;left:50%;z-index:999999;transform:translate(-50%);display:flex;pointer-events:auto;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:9999px;box-shadow:var(--ndt-shadow-toolbar);height:40px;overflow:hidden}.dev-toolbar--active{opacity:1}\n"], dependencies: [{ kind: "component", type: DevToolbarHomeToolComponent, selector: "ndt-home-tool", inputs: ["badge"] }, { kind: "component", type: DevToolbarLanguageToolComponent, selector: "ndt-language-tool" }, { kind: "component", type: DevToolbarFeatureFlagsToolComponent, selector: "ndt-feature-flags-tool" }], animations: [
4518
+ `, isInline: true, styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:contents;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar{position:fixed;bottom:0;left:50%;z-index:999999;transform:translate(-50%);display:flex;pointer-events:auto;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:9999px;box-shadow:var(--ndt-shadow-toolbar);height:40px;overflow:hidden}.dev-toolbar--active{opacity:1}h1,h2,h3,h4,h5{font-weight:600;color:var(--ndt-text-primary);margin:0}h1{font-size:var(--ndt-font-size-xl)}h2{font-size:var(--ndt-font-size-lg)}h3{font-size:var(--ndt-font-size-md)}h4{font-size:var(--ndt-font-size-sm)}h5{font-size:var(--ndt-font-size-xs)}hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}p{line-height:1.5em;margin:0}\n"], dependencies: [{ kind: "component", type: DevToolbarHomeToolComponent, selector: "ndt-home-tool", inputs: ["badge"] }, { kind: "component", type: DevToolbarLanguageToolComponent, selector: "ndt-language-tool" }, { kind: "component", type: DevToolbarFeatureFlagsToolComponent, selector: "ndt-feature-flags-tool" }, { kind: "component", type: DevToolbarAppFeaturesToolComponent, selector: "ndt-app-features-tool" }, { kind: "component", type: DevToolbarPermissionsToolComponent, selector: "ndt-permissions-tool" }, { kind: "component", type: DevToolbarPresetsToolComponent, selector: "ndt-presets-tool" }], animations: [
2931
4519
  trigger('toolbarState', [
2932
4520
  state('hidden', style({
2933
4521
  transform: 'translate(-50%, calc(100% + -1.2rem))',
@@ -2939,16 +4527,18 @@ class DevToolbarComponent {
2939
4527
  animate('300ms cubic-bezier(0.4, 0, 0.2, 1)'),
2940
4528
  ]),
2941
4529
  ]),
2942
- ] }); }
4530
+ ], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
2943
4531
  }
2944
4532
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarComponent, decorators: [{
2945
4533
  type: Component,
2946
- args: [{ standalone: true, selector: 'ndt-toolbar', imports: [
4534
+ args: [{ standalone: true, selector: 'ndt-toolbar', encapsulation: ViewEncapsulation.ShadowDom, imports: [
2947
4535
  DevToolbarHomeToolComponent,
2948
4536
  DevToolbarLanguageToolComponent,
2949
4537
  DevToolbarFeatureFlagsToolComponent,
4538
+ DevToolbarAppFeaturesToolComponent,
4539
+ DevToolbarPermissionsToolComponent,
4540
+ DevToolbarPresetsToolComponent,
2950
4541
  ], template: `
2951
- @if (isDevMode) {
2952
4542
  <div
2953
4543
  aria-label="Developer tools"
2954
4544
  role="toolbar"
@@ -2959,11 +4549,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2959
4549
  (mouseenter)="onMouseEnter()"
2960
4550
  >
2961
4551
  <ndt-home-tool />
2962
- <ndt-language-tool />
2963
- <ndt-feature-flags-tool />
4552
+ @if (config().showLanguageTool ?? true) {
4553
+ <ndt-language-tool />
4554
+ }
4555
+ @if (config().showFeatureFlagsTool ?? true) {
4556
+ <ndt-feature-flags-tool />
4557
+ }
4558
+ @if (config().showAppFeaturesTool ?? true) {
4559
+ <ndt-app-features-tool />
4560
+ }
4561
+ @if (config().showPermissionsTool ?? true) {
4562
+ <ndt-permissions-tool />
4563
+ }
4564
+ @if (config().showPresetsTool ?? true) {
4565
+ <ndt-presets-tool />
4566
+ }
2964
4567
  <ng-content />
2965
4568
  </div>
2966
- }
2967
4569
  `, animations: [
2968
4570
  trigger('toolbarState', [
2969
4571
  state('hidden', style({
@@ -2976,7 +4578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2976
4578
  animate('300ms cubic-bezier(0.4, 0, 0.2, 1)'),
2977
4579
  ]),
2978
4580
  ]),
2979
- ], styles: [".dev-toolbar{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 8px;--ndt-spacing-md: 16px;--ndt-window-padding: 24px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2)}.dev-toolbar[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar h1,.dev-toolbar h2,.dev-toolbar h3,.dev-toolbar h4,.dev-toolbar h5{font-weight:600;color:var(--ndt-text-primary);margin:0}.dev-toolbar h1{font-size:var(--ndt-font-size-xl)}.dev-toolbar h2{font-size:var(--ndt-font-size-lg)}.dev-toolbar h3{font-size:var(--ndt-font-size-md)}.dev-toolbar h4{font-size:var(--ndt-font-size-sm)}.dev-toolbar h5{font-size:var(--ndt-font-size-xs)}.dev-toolbar hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}.dev-toolbar p{line-height:1.5em;margin:0}.dev-toolbar{position:fixed;bottom:0;left:50%;z-index:999999;transform:translate(-50%);display:flex;pointer-events:auto;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:9999px;box-shadow:var(--ndt-shadow-toolbar);height:40px;overflow:hidden}.dev-toolbar--active{opacity:1}\n"] }]
4581
+ ], styles: [":host{--ndt-border-radius-small: 4px;--ndt-border-radius-medium: 8px;--ndt-border-radius-large: 12px;--ndt-transition-default: all .2s ease-out;--ndt-transition-smooth: all .2s ease-in-out;--ndt-bg-primary: rgb(255, 255, 255);--ndt-bg-gradient: linear-gradient(180deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, .88) 100%);--ndt-text-primary: rgb(17, 24, 39);--ndt-text-secondary: rgb(55, 65, 81);--ndt-text-muted: rgb(107, 114, 128);--ndt-border-primary: #e5e7eb;--ndt-border-subtle: rgba(17, 24, 39, .1);--ndt-hover-bg: rgba(17, 24, 39, .05);--ndt-hover-danger: rgb(239, 68, 68);--ndt-shadow-toolbar: 0 2px 8px rgba(156, 163, 175, .2);--ndt-shadow-tooltip: 0 0 0 1px rgba(17, 24, 39, .05), 0 4px 8px rgba(107, 114, 128, .15), 0 2px 4px rgba(107, 114, 128, .1);--ndt-shadow-window: 0px 0px 0px 0px rgba(156, 163, 175, .1), 0px 1px 2px 0px rgba(156, 163, 175, .12), 0px 4px 4px 0px rgba(156, 163, 175, .1), 0px 10px 6px 0px rgba(156, 163, 175, .08), 0px 17px 7px 0px rgba(156, 163, 175, .05), 0px 26px 7px 0px rgba(156, 163, 175, .02);--ndt-spacing-xs: 4px;--ndt-spacing-sm: 6px;--ndt-spacing-md: 12px;--ndt-window-padding: 16px;--ndt-font-size-xs: .75rem;--ndt-font-size-sm: .875rem;--ndt-font-size-md: 1rem;--ndt-font-size-lg: 1.25rem;--ndt-font-size-xl: 2rem;--ndt-background-secondary: var(--ndt-bg-primary);--ndt-background-hover: var(--ndt-hover-bg);--ndt-primary: #df30d4;--ndt-primary-rgb: 223, 48, 212;--ndt-text-on-primary: rgb(255, 255, 255);--ndt-border-color: var(--ndt-border-primary);--ndt-note-background: rgb(219, 234, 254);--ndt-note-border: rgba(37, 99, 235, .2);--ndt-warning-background: rgb(254, 249, 195);--ndt-warning-border: rgba(202, 138, 4, .2);--ndt-error-background: rgb(254, 226, 226);--ndt-error-border: rgba(220, 38, 38, .2);display:contents;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}:host[data-theme=dark]{--ndt-bg-primary: rgb(17, 24, 39);--ndt-bg-gradient: linear-gradient(180deg, rgb(19, 21, 26) 0%, rgba(19, 21, 26, .88) 100%);--ndt-text-primary: rgb(255, 255, 255);--ndt-text-secondary: rgb(229, 231, 235);--ndt-text-muted: rgb(156, 163, 175);--ndt-border-primary: #343841;--ndt-border-subtle: rgba(255, 255, 255, .1);--ndt-hover-bg: rgba(255, 255, 255, .12);--ndt-hover-danger: rgb(220, 38, 38);--ndt-shadow-toolbar: 0 2px 8px rgba(19, 21, 26, .3);--ndt-shadow-tooltip: 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 8px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .3);--ndt-shadow-window: 0px 0px 0px 0px rgba(19, 21, 26, .3), 0px 1px 2px 0px rgba(19, 21, 26, .29), 0px 4px 4px 0px rgba(19, 21, 26, .26), 0px 10px 6px 0px rgba(19, 21, 26, .15), 0px 17px 7px 0px rgba(19, 21, 26, .04), 0px 26px 7px 0px rgba(19, 21, 26, .01);--ndt-note-background: rgba(37, 99, 235, .15);--ndt-note-border: rgba(37, 99, 235, .3);--ndt-warning-background: rgba(202, 138, 4, .15);--ndt-warning-border: rgba(202, 138, 4, .3);--ndt-error-background: rgba(220, 38, 38, .15);--ndt-error-border: rgba(220, 38, 38, .3)}.dev-toolbar{position:fixed;bottom:0;left:50%;z-index:999999;transform:translate(-50%);display:flex;pointer-events:auto;background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:9999px;box-shadow:var(--ndt-shadow-toolbar);height:40px;overflow:hidden}.dev-toolbar--active{opacity:1}h1,h2,h3,h4,h5{font-weight:600;color:var(--ndt-text-primary);margin:0}h1{font-size:var(--ndt-font-size-xl)}h2{font-size:var(--ndt-font-size-lg)}h3{font-size:var(--ndt-font-size-md)}h4{font-size:var(--ndt-font-size-sm)}h5{font-size:var(--ndt-font-size-xs)}hr{border:1px solid var(--ndt-border-subtle);margin:1em 0}p{line-height:1.5em;margin:0}\n"] }]
2980
4582
  }] });
2981
4583
 
2982
4584
  class DevToolbarFeatureFlagService {
@@ -3031,9 +4633,342 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
3031
4633
  args: [{ providedIn: 'root' }]
3032
4634
  }] });
3033
4635
 
4636
+ /**
4637
+ * Public service for managing app features in the dev toolbar.
4638
+ *
4639
+ * This service implements the DevToolsService interface and provides methods for:
4640
+ * - Configuring available product features
4641
+ * - Retrieving forced feature overrides
4642
+ * - Applying preset feature configurations
4643
+ * - Exporting current forced state for presets
4644
+ *
4645
+ * @example
4646
+ * ```typescript
4647
+ * import { DevToolbarAppFeaturesService } from 'ngx-dev-toolbar';
4648
+ *
4649
+ * @Component({...})
4650
+ * export class AppComponent implements OnInit {
4651
+ * private appFeaturesService = inject(DevToolbarAppFeaturesService);
4652
+ *
4653
+ * ngOnInit() {
4654
+ * // Configure available features based on current tier
4655
+ * const features: DevToolbarAppFeature[] = [
4656
+ * { id: 'analytics', name: 'Analytics Dashboard', isEnabled: true, isForced: false },
4657
+ * { id: 'multi-user', name: 'Multi-User Support', isEnabled: false, isForced: false }
4658
+ * ];
4659
+ * this.appFeaturesService.setAvailableOptions(features);
4660
+ *
4661
+ * // Subscribe to forced overrides
4662
+ * this.appFeaturesService.getForcedValues().subscribe(forcedFeatures => {
4663
+ * forcedFeatures.forEach(feature => {
4664
+ * // Apply forced feature state to application logic
4665
+ * this.applyFeatureState(feature.id, feature.isEnabled);
4666
+ * });
4667
+ * });
4668
+ * }
4669
+ * }
4670
+ * ```
4671
+ */
4672
+ class DevToolbarAppFeaturesService {
4673
+ constructor() {
4674
+ this.internalService = inject(DevToolbarInternalAppFeaturesService);
4675
+ }
4676
+ /**
4677
+ * Set available app features for the application.
4678
+ *
4679
+ * Configures the list of product features that can be toggled in the dev toolbar.
4680
+ * Features should represent product-level capabilities like license tiers,
4681
+ * deployment configurations, or environment flags.
4682
+ *
4683
+ * @param features - Array of app features to display in the toolbar
4684
+ * @throws Error if duplicate feature IDs or empty IDs are detected
4685
+ *
4686
+ * @example
4687
+ * ```typescript
4688
+ * const features: DevToolbarAppFeature[] = [
4689
+ * {
4690
+ * id: 'advanced-analytics',
4691
+ * name: 'Advanced Analytics Dashboard',
4692
+ * description: 'Access premium reporting and data visualization',
4693
+ * isEnabled: false, // Not available in current tier
4694
+ * isForced: false
4695
+ * },
4696
+ * {
4697
+ * id: 'multi-user-support',
4698
+ * name: 'Multi-User Collaboration',
4699
+ * description: 'Enable team features and user management',
4700
+ * isEnabled: true, // Available in current tier
4701
+ * isForced: false
4702
+ * }
4703
+ * ];
4704
+ * this.appFeaturesService.setAvailableOptions(features);
4705
+ * ```
4706
+ */
4707
+ setAvailableOptions(features) {
4708
+ this.internalService.setAppFeatures(features);
4709
+ }
4710
+ /**
4711
+ * Get observable stream of features that have forced overrides.
4712
+ *
4713
+ * Emits an array of features that have been forced via the dev toolbar.
4714
+ * Only features with `isForced = true` are included in the emissions.
4715
+ * Use this to react to feature override changes and update application behavior.
4716
+ *
4717
+ * @returns Observable that emits array of forced features whenever state changes
4718
+ *
4719
+ * @example
4720
+ * ```typescript
4721
+ * this.appFeaturesService.getForcedValues()
4722
+ * .pipe(takeUntilDestroyed())
4723
+ * .subscribe(forcedFeatures => {
4724
+ * forcedFeatures.forEach(feature => {
4725
+ * if (feature.isEnabled) {
4726
+ * this.enableFeature(feature.id);
4727
+ * } else {
4728
+ * this.disableFeature(feature.id);
4729
+ * }
4730
+ * });
4731
+ * });
4732
+ * ```
4733
+ */
4734
+ getForcedValues() {
4735
+ return this.internalService.getForcedFeatures();
4736
+ }
4737
+ /**
4738
+ * Apply a preset feature configuration (for preset tool integration).
4739
+ *
4740
+ * Accepts a forced features state object and applies it to the current configuration.
4741
+ * Invalid feature IDs (not in configured features) are filtered out with a warning.
4742
+ *
4743
+ * @param state - Forced features state containing enabled/disabled arrays
4744
+ *
4745
+ * @example
4746
+ * ```typescript
4747
+ * // Apply "Enterprise Tier" preset
4748
+ * const enterprisePreset: ForcedAppFeaturesState = {
4749
+ * enabled: ['analytics', 'multi-user', 'white-label', 'sso'],
4750
+ * disabled: []
4751
+ * };
4752
+ * this.appFeaturesService.applyPresetFeatures(enterprisePreset);
4753
+ *
4754
+ * // Apply "Basic Tier" preset
4755
+ * const basicPreset: ForcedAppFeaturesState = {
4756
+ * enabled: [],
4757
+ * disabled: ['analytics', 'multi-user', 'white-label', 'sso']
4758
+ * };
4759
+ * this.appFeaturesService.applyPresetFeatures(basicPreset);
4760
+ * ```
4761
+ */
4762
+ applyPresetFeatures(state) {
4763
+ this.internalService.applyForcedState(state);
4764
+ }
4765
+ /**
4766
+ * Get current forced feature state as a snapshot (for preset export).
4767
+ *
4768
+ * Returns the current forced features state with enabled/disabled arrays.
4769
+ * Useful for exporting toolbar state to save as a preset or for debugging.
4770
+ * Returns a defensive copy - mutations will not affect internal state.
4771
+ *
4772
+ * @returns Current forced features state
4773
+ *
4774
+ * @example
4775
+ * ```typescript
4776
+ * // Export current toolbar state to save as preset
4777
+ * const currentState = this.appFeaturesService.getCurrentForcedState();
4778
+ * this.presetsService.savePreset('my-config', {
4779
+ * appFeatures: currentState,
4780
+ * // ... other tool states
4781
+ * });
4782
+ *
4783
+ * console.log(currentState);
4784
+ * // { enabled: ['analytics'], disabled: ['white-label'] }
4785
+ * ```
4786
+ */
4787
+ getCurrentForcedState() {
4788
+ return this.internalService.getCurrentForcedState();
4789
+ }
4790
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarAppFeaturesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4791
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarAppFeaturesService, providedIn: 'root' }); }
4792
+ }
4793
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarAppFeaturesService, decorators: [{
4794
+ type: Injectable,
4795
+ args: [{ providedIn: 'root' }]
4796
+ }] });
4797
+
4798
+ /**
4799
+ * Public service for integrating the Permissions Tool with your application.
4800
+ * Use this service to:
4801
+ * 1. Register your application's permissions with setAvailableOptions()
4802
+ * 2. Listen for toolbar permission overrides with getForcedValues()
4803
+ * 3. Apply preset permission states for testing with applyPreset()
4804
+ *
4805
+ * @example
4806
+ * ```typescript
4807
+ * constructor(private permissionsService: DevToolbarPermissionsService) {
4808
+ * // Register permissions
4809
+ * this.permissionsService.setAvailableOptions([
4810
+ * { id: 'can-edit', name: 'Can Edit', isGranted: false, isForced: false }
4811
+ * ]);
4812
+ *
4813
+ * // Listen for overrides
4814
+ * this.permissionsService.getForcedValues().subscribe(forcedPermissions => {
4815
+ * // Update your app's permission state
4816
+ * });
4817
+ * }
4818
+ * ```
4819
+ */
4820
+ class DevToolbarPermissionsService {
4821
+ constructor() {
4822
+ this.internalService = inject(DevToolbarInternalPermissionsService);
4823
+ }
4824
+ /**
4825
+ * Sets the available permissions that will be displayed in the toolbar tool.
4826
+ * Call this in your app initialization to register permissions.
4827
+ *
4828
+ * @param permissions Array of permissions to display in the toolbar
4829
+ *
4830
+ * @example
4831
+ * ```typescript
4832
+ * this.permissionsService.setAvailableOptions([
4833
+ * {
4834
+ * id: 'can-edit-posts',
4835
+ * name: 'Edit Posts',
4836
+ * description: 'Can edit blog posts',
4837
+ * isGranted: false,
4838
+ * isForced: false
4839
+ * }
4840
+ * ]);
4841
+ * ```
4842
+ */
4843
+ setAvailableOptions(permissions) {
4844
+ this.internalService.setAppPermissions(permissions);
4845
+ }
4846
+ /**
4847
+ * Gets an observable of permissions that were forced/overridden through the toolbar.
4848
+ * Subscribe to this to update your application's permission state.
4849
+ *
4850
+ * @returns Observable emitting array of forced permissions whenever changes occur
4851
+ *
4852
+ * @example
4853
+ * ```typescript
4854
+ * this.permissionsService.getForcedValues().subscribe(forcedPermissions => {
4855
+ * forcedPermissions.forEach(permission => {
4856
+ * this.updatePermission(permission.id, permission.isGranted);
4857
+ * });
4858
+ * });
4859
+ * ```
4860
+ */
4861
+ getForcedValues() {
4862
+ return this.internalService.getForcedPermissions();
4863
+ }
4864
+ /**
4865
+ * Apply a preset permission state. Useful for automated testing scenarios.
4866
+ *
4867
+ * @param state The forced permissions state to apply
4868
+ *
4869
+ * @example
4870
+ * ```typescript
4871
+ * this.permissionsService.applyPreset({
4872
+ * granted: ['can-edit-posts'],
4873
+ * denied: ['can-delete-posts']
4874
+ * });
4875
+ * ```
4876
+ */
4877
+ applyPreset(state) {
4878
+ this.internalService.applyPresetPermissions(state);
4879
+ }
4880
+ /**
4881
+ * Get the current forced permission state.
4882
+ *
4883
+ * @returns Current forced permissions state
4884
+ */
4885
+ getCurrentState() {
4886
+ return this.internalService.getCurrentForcedState();
4887
+ }
4888
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4889
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPermissionsService, providedIn: 'root' }); }
4890
+ }
4891
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPermissionsService, decorators: [{
4892
+ type: Injectable,
4893
+ args: [{ providedIn: 'root' }]
4894
+ }] });
4895
+
4896
+ /**
4897
+ * Public service for managing dev toolbar presets.
4898
+ * Allows developers to programmatically save, load, and manage presets.
4899
+ */
4900
+ class DevToolbarPresetsService {
4901
+ constructor() {
4902
+ this.internalService = inject(DevToolbarInternalPresetsService);
4903
+ }
4904
+ /**
4905
+ * Get all saved presets as an Observable
4906
+ */
4907
+ getPresets() {
4908
+ return this.internalService.presets$;
4909
+ }
4910
+ /**
4911
+ * Save current toolbar state as a preset
4912
+ * @param name - Name for the preset
4913
+ * @param description - Optional description
4914
+ * @returns The created preset
4915
+ */
4916
+ savePreset(name, description) {
4917
+ return this.internalService.saveCurrentAsPreset(name, description);
4918
+ }
4919
+ /**
4920
+ * Apply a preset (load its configuration into all tools)
4921
+ * @param presetId - ID of the preset to apply
4922
+ */
4923
+ async applyPreset(presetId) {
4924
+ return this.internalService.applyPreset(presetId);
4925
+ }
4926
+ /**
4927
+ * Update a preset with current toolbar state
4928
+ * @param presetId - ID of the preset to update
4929
+ */
4930
+ updatePreset(presetId) {
4931
+ this.internalService.updatePreset(presetId);
4932
+ }
4933
+ /**
4934
+ * Delete a preset
4935
+ * @param presetId - ID of the preset to delete
4936
+ */
4937
+ deletePreset(presetId) {
4938
+ this.internalService.deletePreset(presetId);
4939
+ }
4940
+ /**
4941
+ * Export a preset as JSON string
4942
+ * @param presetId - ID of the preset to export
4943
+ * @returns JSON string representation of the preset
4944
+ */
4945
+ exportPreset(presetId) {
4946
+ const preset = this.internalService.getPresetById(presetId);
4947
+ if (!preset)
4948
+ return null;
4949
+ return JSON.stringify(preset, null, 2);
4950
+ }
4951
+ /**
4952
+ * Import a preset from JSON string
4953
+ * @param json - JSON string representation of a preset
4954
+ * @returns The imported preset
4955
+ * @throws Error if JSON is invalid
4956
+ */
4957
+ importPreset(json) {
4958
+ const preset = JSON.parse(json);
4959
+ return this.internalService.addPreset(preset);
4960
+ }
4961
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPresetsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4962
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPresetsService, providedIn: 'root' }); }
4963
+ }
4964
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: DevToolbarPresetsService, decorators: [{
4965
+ type: Injectable,
4966
+ args: [{ providedIn: 'root' }]
4967
+ }] });
4968
+
3034
4969
  /**
3035
4970
  * Generated bundle index. Do not edit.
3036
4971
  */
3037
4972
 
3038
- export { DevToolbarComponent, DevToolbarFeatureFlagService, DevToolbarIconComponent, DevToolbarLanguageService, DevToolbarToolComponent };
4973
+ export { DevToolbarAppFeaturesService, DevToolbarAppFeaturesToolComponent, DevToolbarComponent, DevToolbarFeatureFlagService, DevToolbarIconComponent, DevToolbarLanguageService, DevToolbarPermissionsService, DevToolbarPermissionsToolComponent, DevToolbarPresetsService, DevToolbarPresetsToolComponent, DevToolbarToolComponent };
3039
4974
  //# sourceMappingURL=ngx-dev-toolbar.mjs.map