ngx-dev-toolbar 4.0.0 → 4.2.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 (44) hide show
  1. package/README.md +5 -5
  2. package/components/icon-button/icon-button.component.d.ts +13 -0
  3. package/components/icons/globe-icon.component.d.ts +6 -0
  4. package/components/icons/icon.models.d.ts +1 -1
  5. package/components/icons/pin-icon.component.d.ts +6 -0
  6. package/components/list-item/list-item.component.d.ts +24 -1
  7. package/components/select/select.component.d.ts +1 -1
  8. package/components/tool-button/tool-button.component.d.ts +6 -5
  9. package/components/toolbar-tool/toolbar-tool.component.d.ts +6 -11
  10. package/components/window/window.component.d.ts +1 -1
  11. package/fesm2022/ngx-dev-toolbar.mjs +2229 -698
  12. package/fesm2022/ngx-dev-toolbar.mjs.map +1 -1
  13. package/index.d.ts +7 -3
  14. package/models/tool-view-state.models.d.ts +2 -0
  15. package/models/toolbar-config.interface.d.ts +32 -2
  16. package/models/toolbar-position.model.d.ts +3 -0
  17. package/models/toolbar.interface.d.ts +19 -0
  18. package/package.json +6 -7
  19. package/tokens.d.ts +0 -18
  20. package/toolbar-state.service.d.ts +10 -9
  21. package/toolbar.component.d.ts +1 -0
  22. package/tools/app-features-tool/app-features-internal.service.d.ts +6 -0
  23. package/tools/app-features-tool/app-features-tool.component.d.ts +5 -0
  24. package/tools/app-features-tool/app-features.service.d.ts +7 -0
  25. package/tools/feature-flags-tool/feature-flags-internal.service.d.ts +6 -0
  26. package/tools/feature-flags-tool/feature-flags-tool.component.d.ts +5 -0
  27. package/tools/feature-flags-tool/feature-flags.service.d.ts +7 -0
  28. package/tools/home-tool/home-tool.component.d.ts +3 -0
  29. package/tools/home-tool/settings.models.d.ts +3 -0
  30. package/tools/i18n-tool/i18n-formatting.utils.d.ts +10 -0
  31. package/tools/i18n-tool/i18n-internal.service.d.ts +86 -0
  32. package/tools/i18n-tool/i18n-tool.component.d.ts +66 -0
  33. package/tools/i18n-tool/i18n.models.d.ts +55 -0
  34. package/tools/i18n-tool/i18n.service.d.ts +70 -0
  35. package/tools/permissions-tool/permissions-internal.service.d.ts +6 -0
  36. package/tools/permissions-tool/permissions-tool.component.d.ts +5 -0
  37. package/tools/permissions-tool/permissions.service.d.ts +7 -0
  38. package/tools/presets-tool/presets-internal.service.d.ts +1 -1
  39. package/tools/presets-tool/presets-tool.component.d.ts +5 -5
  40. package/tools/presets-tool/presets.models.d.ts +10 -3
  41. package/tools/language-tool/language-internal.service.d.ts +0 -30
  42. package/tools/language-tool/language-tool.component.d.ts +0 -14
  43. package/tools/language-tool/language.models.d.ts +0 -4
  44. package/tools/language-tool/language.service.d.ts +0 -26
@@ -1,6 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, signal, computed, Injectable, ChangeDetectionStrategy, Component, input, inject, model, ElementRef, output, viewChild, contentChild, effect, DestroyRef, ViewEncapsulation, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, ApplicationRef, EnvironmentInjector, createComponent, TemplateRef, Directive, contentChildren } from '@angular/core';
3
- import { trigger, state, style, transition, animate } from '@angular/animations';
2
+ import { InjectionToken, Injectable, inject, signal, computed, model, input, ChangeDetectionStrategy, Component, output, viewChild, contentChild, effect, HostListener, DestroyRef, ViewEncapsulation, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, ApplicationRef, EnvironmentInjector, createComponent, TemplateRef, Directive, contentChildren } from '@angular/core';
4
3
  import { CommonModule, DOCUMENT, NgTemplateOutlet } from '@angular/common';
5
4
  import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
5
  import { BehaviorSubject, combineLatest, map, firstValueFrom, fromEvent } from 'rxjs';
@@ -53,23 +52,6 @@ const TOOLBAR_FEATURE_FLAGS = new InjectionToken('TOOLBAR_FEATURE_FLAGS');
53
52
  * ```
54
53
  */
55
54
  const TOOLBAR_PERMISSIONS = new InjectionToken('TOOLBAR_PERMISSIONS');
56
- /**
57
- * InjectionToken for the Language service.
58
- *
59
- * Use this token for tree-shakeable injection of the language service.
60
- * When using dynamic imports, this token enables complete tree-shaking of
61
- * the toolbar in production builds.
62
- *
63
- * @example
64
- * ```typescript
65
- * // In your service
66
- * private devToolbar = inject(TOOLBAR_LANGUAGE, { optional: true });
67
- *
68
- * // Safe to call - no-op if toolbar is not provided
69
- * this.devToolbar?.setAvailableOptions(languages);
70
- * ```
71
- */
72
- const TOOLBAR_LANGUAGE = new InjectionToken('TOOLBAR_LANGUAGE');
73
55
  /**
74
56
  * InjectionToken for the App Features service.
75
57
  *
@@ -88,11 +70,88 @@ const TOOLBAR_LANGUAGE = new InjectionToken('TOOLBAR_LANGUAGE');
88
70
  */
89
71
  const TOOLBAR_APP_FEATURES = new InjectionToken('TOOLBAR_APP_FEATURES');
90
72
 
73
+ class ToolbarStorageService {
74
+ constructor() {
75
+ this.PREFIX = 'AngularToolbar.';
76
+ this.TOOLS_KEY = `${this.PREFIX}keys`;
77
+ this.SETTINGS_KEY = `${this.PREFIX}settings`;
78
+ }
79
+ set(key, value) {
80
+ const toolKey = this.getToolKey(key);
81
+ this.addToolKey(toolKey);
82
+ localStorage.setItem(toolKey, JSON.stringify(value));
83
+ }
84
+ get(key) {
85
+ const toolKey = this.getToolKey(key);
86
+ const item = localStorage.getItem(toolKey);
87
+ return item ? JSON.parse(item) : null;
88
+ }
89
+ remove(key) {
90
+ const toolKey = this.getToolKey(key);
91
+ localStorage.removeItem(toolKey);
92
+ this.removeToolKey(toolKey);
93
+ }
94
+ getAllSettings() {
95
+ const settings = {};
96
+ const keys = this.getToolKeys();
97
+ keys.forEach((key) => {
98
+ const value = this.get(key);
99
+ if (value !== null) {
100
+ settings[key] = value;
101
+ }
102
+ });
103
+ return settings;
104
+ }
105
+ setAllSettings(settings) {
106
+ Object.entries(settings).forEach(([key, value]) => {
107
+ this.set(key, value);
108
+ });
109
+ }
110
+ clearAllSettings() {
111
+ const keys = this.getToolKeys();
112
+ keys.forEach((key) => {
113
+ this.remove(key);
114
+ });
115
+ }
116
+ getToolKeys() {
117
+ return JSON.parse(localStorage.getItem(this.TOOLS_KEY) ?? '[]');
118
+ }
119
+ addToolKey(key) {
120
+ const currentKeys = this.getToolKeys();
121
+ if (currentKeys.includes(key)) {
122
+ return;
123
+ }
124
+ currentKeys.push(key);
125
+ localStorage.setItem(this.TOOLS_KEY, JSON.stringify(currentKeys));
126
+ }
127
+ removeToolKey(key) {
128
+ const currentKeys = this.getToolKeys();
129
+ const index = currentKeys.indexOf(key);
130
+ if (index !== -1) {
131
+ currentKeys.splice(index, 1);
132
+ }
133
+ localStorage.setItem(this.TOOLS_KEY, JSON.stringify(currentKeys));
134
+ }
135
+ getToolKey(key) {
136
+ return key.includes(this.PREFIX) ? key : this.PREFIX + key;
137
+ }
138
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
139
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, providedIn: 'root' }); }
140
+ }
141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, decorators: [{
142
+ type: Injectable,
143
+ args: [{ providedIn: 'root' }]
144
+ }] });
145
+
146
+ const SETTINGS_KEY = 'settings';
91
147
  class ToolbarStateService {
92
148
  constructor() {
149
+ this.storageService = inject(ToolbarStorageService);
93
150
  // Initial state
94
151
  this.state = signal({
95
152
  isHidden: true,
153
+ isCompletelyHidden: false,
154
+ position: 'bottom',
96
155
  activeToolId: null,
97
156
  delay: 3000,
98
157
  error: null,
@@ -106,17 +165,12 @@ class ToolbarStateService {
106
165
  this.hasActiveTool = computed(() => this.state().activeToolId !== null);
107
166
  this.error = computed(() => this.state().error);
108
167
  this.theme = computed(() => this.state().theme);
109
- /**
110
- * The delay to hide the toolbar
111
- */
112
168
  this.delay = computed(() => this.state().delay);
113
169
  this.config = computed(() => this.state().config);
114
- /**
115
- * Indicates if the toolbar is enabled based on config.
116
- * When disabled, toolbar UI won't render and services won't return forced values.
117
- * @default true
118
- */
119
170
  this.isEnabled = computed(() => this.state().config.enabled ?? true);
171
+ this.position = computed(() => this.state().position);
172
+ this.isCompletelyHidden = computed(() => this.state().isCompletelyHidden);
173
+ this.loadPersistedState();
120
174
  }
121
175
  // State updates
122
176
  setVisibility(isVisible) {
@@ -171,6 +225,49 @@ class ToolbarStateService {
171
225
  ...state,
172
226
  config,
173
227
  }));
228
+ // If config specifies a position, it takes priority
229
+ if (config.position) {
230
+ this.setPosition(config.position);
231
+ }
232
+ }
233
+ setPosition(position) {
234
+ // Close any active tool so its overlay doesn't stay in the old position
235
+ this.setActiveTool(null);
236
+ this.state.update((state) => ({
237
+ ...state,
238
+ position,
239
+ }));
240
+ this.persistState();
241
+ }
242
+ toggleCompletelyHidden() {
243
+ this.state.update((state) => ({
244
+ ...state,
245
+ isCompletelyHidden: !state.isCompletelyHidden,
246
+ }));
247
+ this.persistState();
248
+ }
249
+ loadPersistedState() {
250
+ try {
251
+ const stored = this.storageService.get(SETTINGS_KEY);
252
+ if (stored) {
253
+ this.state.update((state) => ({
254
+ ...state,
255
+ position: stored.position ?? state.position,
256
+ isCompletelyHidden: stored.isCompletelyHidden ?? state.isCompletelyHidden,
257
+ }));
258
+ }
259
+ }
260
+ catch {
261
+ // Corrupted localStorage data — use defaults
262
+ }
263
+ }
264
+ persistState() {
265
+ const current = this.storageService.get(SETTINGS_KEY) ?? {};
266
+ this.storageService.set(SETTINGS_KEY, {
267
+ ...current,
268
+ position: this.state().position,
269
+ isCompletelyHidden: this.state().isCompletelyHidden,
270
+ });
174
271
  }
175
272
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
176
273
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStateService, providedIn: 'root' }); }
@@ -180,6 +277,128 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
180
277
  args: [{
181
278
  providedIn: 'root',
182
279
  }]
280
+ }], ctorParameters: () => [] });
281
+
282
+ class ToolbarInputComponent {
283
+ constructor() {
284
+ this.value = model.required();
285
+ this.type = input('text');
286
+ this.placeholder = input('');
287
+ this.ariaLabel = input('');
288
+ this.inputClass = input('input');
289
+ }
290
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
291
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: ToolbarInputComponent, isStandalone: true, selector: "ndt-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: `
292
+ <input
293
+ [attr.aria-label]="ariaLabel()"
294
+ [type]="type()"
295
+ [class]="inputClass()"
296
+ [ngModel]="value()"
297
+ [placeholder]="placeholder()"
298
+ (ngModelChange)="value.set($event)"
299
+ />
300
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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}.input{width:100%;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);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-xs);transition:var(--ndt-transition-default);box-sizing:border-box;min-height:28px}.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.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
301
+ }
302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInputComponent, decorators: [{
303
+ type: Component,
304
+ args: [{ selector: 'ndt-input', standalone: true, imports: [FormsModule], template: `
305
+ <input
306
+ [attr.aria-label]="ariaLabel()"
307
+ [type]="type()"
308
+ [class]="inputClass()"
309
+ [ngModel]="value()"
310
+ [placeholder]="placeholder()"
311
+ (ngModelChange)="value.set($event)"
312
+ />
313
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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}.input{width:100%;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);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-xs);transition:var(--ndt-transition-default);box-sizing:border-box;min-height:28px}.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"] }]
314
+ }] });
315
+
316
+ /**
317
+ * Container component for displaying lists of items with consistent scrolling,
318
+ * empty states, and layout across all tools.
319
+ *
320
+ * @example
321
+ * ```html
322
+ * <ndt-list
323
+ * [hasItems]="items().length > 0"
324
+ * [hasResults]="filteredItems().length > 0"
325
+ * emptyMessage="No items found"
326
+ * noResultsMessage="No items match your filter"
327
+ * >
328
+ * @for (item of filteredItems(); track item.id) {
329
+ * <ndt-list-item ... />
330
+ * }
331
+ * </ndt-list>
332
+ * ```
333
+ */
334
+ class ToolbarListComponent {
335
+ constructor() {
336
+ /**
337
+ * Whether the list has any items at all (before filtering).
338
+ * When false, shows the emptyMessage.
339
+ */
340
+ this.hasItems = input(true);
341
+ /**
342
+ * Whether the list has any results after filtering.
343
+ * When false (but hasItems is true), shows the noResultsMessage.
344
+ */
345
+ this.hasResults = input(true);
346
+ /**
347
+ * Message to display when there are no items at all.
348
+ * @example "No feature flags found"
349
+ */
350
+ this.emptyMessage = input('No items found');
351
+ /**
352
+ * Optional hint text to display below the empty message.
353
+ * @example "Call setAvailableOptions() to configure features"
354
+ */
355
+ this.emptyHint = input(undefined);
356
+ /**
357
+ * Message to display when items exist but none match the current filter.
358
+ * @example "No flags match your filter"
359
+ */
360
+ this.noResultsMessage = input('No results match your filter');
361
+ }
362
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
363
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarListComponent, isStandalone: true, selector: "ndt-list", inputs: { hasItems: { classPropertyName: "hasItems", publicName: "hasItems", isSignal: true, isRequired: false, transformFunction: null }, hasResults: { classPropertyName: "hasResults", publicName: "hasResults", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyHint: { classPropertyName: "emptyHint", publicName: "emptyHint", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
364
+ @if (!hasItems()) {
365
+ <div class="empty-state">
366
+ <p>{{ emptyMessage() }}</p>
367
+ @if (emptyHint()) {
368
+ <p class="hint">{{ emptyHint() }}</p>
369
+ }
370
+ </div>
371
+ } @else if (!hasResults()) {
372
+ <div class="empty-state">
373
+ <p>{{ noResultsMessage() }}</p>
374
+ </div>
375
+ } @else {
376
+ <div class="list-container">
377
+ <ng-content />
378
+ </div>
379
+ }
380
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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:flex;flex-direction:column;flex:1;min-height:0}.empty-state{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-background-secondary);color:var(--ndt-text-muted)}.empty-state p{margin:0}.empty-state .hint{font-size:var(--ndt-font-size-xs)}.list-container{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;position:relative;scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.list-container::-webkit-scrollbar{width:8px;height:8px}.list-container::-webkit-scrollbar-track{background:transparent}.list-container::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.list-container::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
381
+ }
382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListComponent, decorators: [{
383
+ type: Component,
384
+ args: [{ selector: 'ndt-list', standalone: true, imports: [CommonModule], template: `
385
+ @if (!hasItems()) {
386
+ <div class="empty-state">
387
+ <p>{{ emptyMessage() }}</p>
388
+ @if (emptyHint()) {
389
+ <p class="hint">{{ emptyHint() }}</p>
390
+ }
391
+ </div>
392
+ } @else if (!hasResults()) {
393
+ <div class="empty-state">
394
+ <p>{{ noResultsMessage() }}</p>
395
+ </div>
396
+ } @else {
397
+ <div class="list-container">
398
+ <ng-content />
399
+ </div>
400
+ }
401
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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:flex;flex-direction:column;flex:1;min-height:0}.empty-state{display:flex;flex-direction:column;gap:var(--ndt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);padding:var(--ndt-spacing-md);background:var(--ndt-background-secondary);color:var(--ndt-text-muted)}.empty-state p{margin:0}.empty-state .hint{font-size:var(--ndt-font-size-xs)}.list-container{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;position:relative;scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.list-container::-webkit-scrollbar{width:8px;height:8px}.list-container::-webkit-scrollbar-track{background:transparent}.list-container::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.list-container::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}\n"] }]
183
402
  }] });
184
403
 
185
404
  class AngularIconComponent {
@@ -798,6 +1017,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
798
1017
  }]
799
1018
  }] });
800
1019
 
1020
+ class GlobeIconComponent {
1021
+ constructor() {
1022
+ this.fill = input('#FFFF');
1023
+ }
1024
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: GlobeIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1025
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: GlobeIconComponent, isStandalone: true, selector: "ndt-globe-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1026
+ <svg
1027
+ [attr.fill]="fill()"
1028
+ xmlns="http://www.w3.org/2000/svg"
1029
+ width="24"
1030
+ height="24"
1031
+ viewBox="0 0 24 24"
1032
+ >
1033
+ <path
1034
+ d="M1 16V8h2v8H1Zm3 0V8h2l2.225 4.45L8 12.5V8h2v8H8l-2.225-4.45L6 11.5V16H4Zm9 0v-6h-2V8h6v2h-2v6h-2Zm5 0V8h2v6h3v2h-5Z"
1035
+ ></path>
1036
+ </svg>
1037
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1038
+ }
1039
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: GlobeIconComponent, decorators: [{
1040
+ type: Component,
1041
+ args: [{
1042
+ selector: 'ndt-globe-icon',
1043
+ standalone: true,
1044
+ changeDetection: ChangeDetectionStrategy.OnPush,
1045
+ template: `
1046
+ <svg
1047
+ [attr.fill]="fill()"
1048
+ xmlns="http://www.w3.org/2000/svg"
1049
+ width="24"
1050
+ height="24"
1051
+ viewBox="0 0 24 24"
1052
+ >
1053
+ <path
1054
+ d="M1 16V8h2v8H1Zm3 0V8h2l2.225 4.45L8 12.5V8h2v8H8l-2.225-4.45L6 11.5V16H4Zm9 0v-6h-2V8h6v2h-2v6h-2Zm5 0V8h2v6h3v2h-5Z"
1055
+ ></path>
1056
+ </svg>
1057
+ `,
1058
+ }]
1059
+ }] });
1060
+
801
1061
  class ImportIconComponent {
802
1062
  constructor() {
803
1063
  this.fill = input('#FFFF');
@@ -1060,29 +1320,78 @@ class NetworkIconComponent {
1060
1320
  constructor() {
1061
1321
  this.fill = input('#FFFF');
1062
1322
  }
1063
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: NetworkIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1064
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: NetworkIconComponent, isStandalone: true, selector: "ndt-network-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1323
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: NetworkIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1324
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: NetworkIconComponent, isStandalone: true, selector: "ndt-network-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1325
+ <svg
1326
+ [attr.fill]="fill()"
1327
+ xmlns="http://www.w3.org/2000/svg"
1328
+ width="24"
1329
+ height="24"
1330
+ viewBox="0 0 256 256"
1331
+ >
1332
+ <path
1333
+ d="M152,40V72a8,8,0,0,1-8,8H112a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h32A8,8,0,0,1,152,40ZM80,168H48a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V176A8,8,0,0,0,80,168Zm128,0H176a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8h32a8,8,0,0,0,8-8V176A8,8,0,0,0,208,168Z"
1334
+ opacity="0.2"
1335
+ ></path>
1336
+ <path
1337
+ d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"
1338
+ ></path>
1339
+ </svg>
1340
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1341
+ }
1342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: NetworkIconComponent, decorators: [{
1343
+ type: Component,
1344
+ args: [{
1345
+ selector: 'ndt-network-icon',
1346
+ standalone: true,
1347
+ changeDetection: ChangeDetectionStrategy.OnPush,
1348
+ template: `
1349
+ <svg
1350
+ [attr.fill]="fill()"
1351
+ xmlns="http://www.w3.org/2000/svg"
1352
+ width="24"
1353
+ height="24"
1354
+ viewBox="0 0 256 256"
1355
+ >
1356
+ <path
1357
+ d="M152,40V72a8,8,0,0,1-8,8H112a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h32A8,8,0,0,1,152,40ZM80,168H48a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V176A8,8,0,0,0,80,168Zm128,0H176a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8h32a8,8,0,0,0,8-8V176A8,8,0,0,0,208,168Z"
1358
+ opacity="0.2"
1359
+ ></path>
1360
+ <path
1361
+ d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"
1362
+ ></path>
1363
+ </svg>
1364
+ `,
1365
+ }]
1366
+ }] });
1367
+
1368
+ class PinIconComponent {
1369
+ constructor() {
1370
+ this.fill = input('#FFFF');
1371
+ }
1372
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: PinIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1373
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: PinIconComponent, isStandalone: true, selector: "ndt-pin-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1065
1374
  <svg
1066
1375
  [attr.fill]="fill()"
1067
1376
  xmlns="http://www.w3.org/2000/svg"
1068
1377
  width="24"
1069
1378
  height="24"
1070
- viewBox="0 0 256 256"
1379
+ viewBox="0 0 24 24"
1071
1380
  >
1072
1381
  <path
1073
- d="M152,40V72a8,8,0,0,1-8,8H112a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h32A8,8,0,0,1,152,40ZM80,168H48a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V176A8,8,0,0,0,80,168Zm128,0H176a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8h32a8,8,0,0,0,8-8V176A8,8,0,0,0,208,168Z"
1382
+ d="M14 12.41V5h1V4H8v1h1v7.41l-2 2V15h9v-.59l-2-2"
1074
1383
  opacity="0.2"
1075
1384
  ></path>
1076
1385
  <path
1077
- d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"
1386
+ d="M17 14v2h-5v4.5l-.5 1.5l-.5-1.5V16H6v-2l2-2V6H7V3h9v3h-1v6l2 2Z"
1078
1387
  ></path>
1079
1388
  </svg>
1080
1389
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1081
1390
  }
1082
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: NetworkIconComponent, decorators: [{
1391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: PinIconComponent, decorators: [{
1083
1392
  type: Component,
1084
1393
  args: [{
1085
- selector: 'ndt-network-icon',
1394
+ selector: 'ndt-pin-icon',
1086
1395
  standalone: true,
1087
1396
  changeDetection: ChangeDetectionStrategy.OnPush,
1088
1397
  template: `
@@ -1091,14 +1400,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1091
1400
  xmlns="http://www.w3.org/2000/svg"
1092
1401
  width="24"
1093
1402
  height="24"
1094
- viewBox="0 0 256 256"
1403
+ viewBox="0 0 24 24"
1095
1404
  >
1096
1405
  <path
1097
- d="M152,40V72a8,8,0,0,1-8,8H112a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h32A8,8,0,0,1,152,40ZM80,168H48a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V176A8,8,0,0,0,80,168Zm128,0H176a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8h32a8,8,0,0,0,8-8V176A8,8,0,0,0,208,168Z"
1406
+ d="M14 12.41V5h1V4H8v1h1v7.41l-2 2V15h9v-.59l-2-2"
1098
1407
  opacity="0.2"
1099
1408
  ></path>
1100
1409
  <path
1101
- d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"
1410
+ d="M17 14v2h-5v4.5l-.5 1.5l-.5-1.5V16H6v-2l2-2V6H7V3h9v3h-1v6l2 2Z"
1102
1411
  ></path>
1103
1412
  </svg>
1104
1413
  `,
@@ -1562,6 +1871,8 @@ class ToolbarIconComponent {
1562
1871
  <ndt-gear-icon [fill]="fill()" />
1563
1872
  } @case ('git-branch') {
1564
1873
  <ndt-git-branch-icon [fill]="fill()" />
1874
+ } @case ('globe') {
1875
+ <ndt-globe-icon [fill]="fill()" />
1565
1876
  } @case ('import') {
1566
1877
  <ndt-import-icon [fill]="fill()" />
1567
1878
  } @case ('layout') {
@@ -1574,6 +1885,8 @@ class ToolbarIconComponent {
1574
1885
  <ndt-lock-icon [fill]="fill()" />
1575
1886
  } @case ('network') {
1576
1887
  <ndt-network-icon [fill]="fill()" />
1888
+ } @case ('pin') {
1889
+ <ndt-pin-icon [fill]="fill()" />
1577
1890
  } @case ('puzzle') {
1578
1891
  <ndt-puzzle-icon [fill]="fill()" />
1579
1892
  } @case ('refresh') {
@@ -1597,7 +1910,7 @@ class ToolbarIconComponent {
1597
1910
  } @case ('trash') {
1598
1911
  <ndt-trash-icon [fill]="fill()" />
1599
1912
  } }
1600
- `, 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: EditIconComponent, selector: "ndt-edit-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 }); }
1913
+ `, 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: EditIconComponent, selector: "ndt-edit-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: GlobeIconComponent, selector: "ndt-globe-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: PinIconComponent, selector: "ndt-pin-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 }); }
1601
1914
  }
1602
1915
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarIconComponent, decorators: [{
1603
1916
  type: Component,
@@ -1618,12 +1931,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1618
1931
  GaugeIconComponent,
1619
1932
  GearIconComponent,
1620
1933
  GitBranchIconComponent,
1934
+ GlobeIconComponent,
1621
1935
  ImportIconComponent,
1622
1936
  LayoutIconComponent,
1623
1937
  LightbulbIconComponent,
1624
1938
  LightingIconComponent,
1625
1939
  LockIconComponent,
1626
1940
  NetworkIconComponent,
1941
+ PinIconComponent,
1627
1942
  PuzzleIconComponent,
1628
1943
  RefreshIconComponent,
1629
1944
  StarIconComponent,
@@ -1661,6 +1976,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1661
1976
  <ndt-gear-icon [fill]="fill()" />
1662
1977
  } @case ('git-branch') {
1663
1978
  <ndt-git-branch-icon [fill]="fill()" />
1979
+ } @case ('globe') {
1980
+ <ndt-globe-icon [fill]="fill()" />
1664
1981
  } @case ('import') {
1665
1982
  <ndt-import-icon [fill]="fill()" />
1666
1983
  } @case ('layout') {
@@ -1673,6 +1990,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1673
1990
  <ndt-lock-icon [fill]="fill()" />
1674
1991
  } @case ('network') {
1675
1992
  <ndt-network-icon [fill]="fill()" />
1993
+ } @case ('pin') {
1994
+ <ndt-pin-icon [fill]="fill()" />
1676
1995
  } @case ('puzzle') {
1677
1996
  <ndt-puzzle-icon [fill]="fill()" />
1678
1997
  } @case ('refresh') {
@@ -1700,126 +2019,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1700
2019
  }]
1701
2020
  }] });
1702
2021
 
1703
- class ToolbarInputComponent {
1704
- constructor() {
1705
- this.value = model.required();
1706
- this.type = input('text');
1707
- this.placeholder = input('');
1708
- this.ariaLabel = input('');
1709
- this.inputClass = input('input');
1710
- }
1711
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1712
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: ToolbarInputComponent, isStandalone: true, selector: "ndt-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: `
1713
- <input
1714
- [attr.aria-label]="ariaLabel()"
1715
- [type]="type()"
1716
- [class]="inputClass()"
1717
- [ngModel]="value()"
1718
- [placeholder]="placeholder()"
1719
- (ngModelChange)="value.set($event)"
1720
- />
1721
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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}.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.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1722
- }
1723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInputComponent, decorators: [{
1724
- type: Component,
1725
- args: [{ selector: 'ndt-input', standalone: true, imports: [FormsModule], template: `
1726
- <input
1727
- [attr.aria-label]="ariaLabel()"
1728
- [type]="type()"
1729
- [class]="inputClass()"
1730
- [ngModel]="value()"
1731
- [placeholder]="placeholder()"
1732
- (ngModelChange)="value.set($event)"
1733
- />
1734
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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}.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"] }]
1735
- }] });
1736
-
1737
- /**
1738
- * Container component for displaying lists of items with consistent scrolling,
1739
- * empty states, and layout across all tools.
1740
- *
1741
- * @example
1742
- * ```html
1743
- * <ndt-list
1744
- * [hasItems]="items().length > 0"
1745
- * [hasResults]="filteredItems().length > 0"
1746
- * emptyMessage="No items found"
1747
- * noResultsMessage="No items match your filter"
1748
- * >
1749
- * @for (item of filteredItems(); track item.id) {
1750
- * <ndt-list-item ... />
1751
- * }
1752
- * </ndt-list>
1753
- * ```
1754
- */
1755
- class ToolbarListComponent {
2022
+ class ToolbarIconButtonComponent {
1756
2023
  constructor() {
1757
- /**
1758
- * Whether the list has any items at all (before filtering).
1759
- * When false, shows the emptyMessage.
1760
- */
1761
- this.hasItems = input(true);
1762
- /**
1763
- * Whether the list has any results after filtering.
1764
- * When false (but hasItems is true), shows the noResultsMessage.
1765
- */
1766
- this.hasResults = input(true);
1767
- /**
1768
- * Message to display when there are no items at all.
1769
- * @example "No feature flags found"
1770
- */
1771
- this.emptyMessage = input('No items found');
1772
- /**
1773
- * Optional hint text to display below the empty message.
1774
- * @example "Call setAvailableOptions() to configure features"
1775
- */
1776
- this.emptyHint = input(undefined);
1777
- /**
1778
- * Message to display when items exist but none match the current filter.
1779
- * @example "No flags match your filter"
1780
- */
1781
- this.noResultsMessage = input('No results match your filter');
1782
- }
1783
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1784
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarListComponent, isStandalone: true, selector: "ndt-list", inputs: { hasItems: { classPropertyName: "hasItems", publicName: "hasItems", isSignal: true, isRequired: false, transformFunction: null }, hasResults: { classPropertyName: "hasResults", publicName: "hasResults", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyHint: { classPropertyName: "emptyHint", publicName: "emptyHint", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1785
- @if (!hasItems()) {
1786
- <div class="empty-state">
1787
- <p>{{ emptyMessage() }}</p>
1788
- @if (emptyHint()) {
1789
- <p class="hint">{{ emptyHint() }}</p>
1790
- }
1791
- </div>
1792
- } @else if (!hasResults()) {
1793
- <div class="empty-state">
1794
- <p>{{ noResultsMessage() }}</p>
1795
- </div>
1796
- } @else {
1797
- <div class="list-container">
1798
- <ng-content />
1799
- </div>
2024
+ this.icon = input();
2025
+ this.tooltip = input();
2026
+ this.ariaLabel = input();
2027
+ this.size = input('sm');
2028
+ this.variant = input('ghost');
2029
+ this.isHovered = signal(false);
2030
+ this.isTooltipVisible = computed(() => !!this.tooltip() && this.isHovered());
1800
2031
  }
1801
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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:flex;flex-direction:column;flex:1;min-height:0}.empty-state{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-state p{margin:0}.empty-state .hint{font-size:var(--ndt-font-size-xs)}.list-container{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;position:relative;scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.list-container::-webkit-scrollbar{width:8px;height:8px}.list-container::-webkit-scrollbar-track{background:transparent}.list-container::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.list-container::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2032
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarIconButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2033
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarIconButtonComponent, isStandalone: true, selector: "ndt-icon-button", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2034
+ <button
2035
+ class="icon-button"
2036
+ [class.icon-button--sm]="size() === 'sm'"
2037
+ [class.icon-button--md]="size() === 'md'"
2038
+ [class.icon-button--outlined]="variant() === 'outlined'"
2039
+ [attr.aria-label]="ariaLabel() || tooltip()"
2040
+ (mouseenter)="isHovered.set(true)"
2041
+ (mouseleave)="isHovered.set(false)"
2042
+ >
2043
+ @if (isTooltipVisible()) {
2044
+ <span class="tooltip" [class.tooltip--visible]="isHovered()">
2045
+ {{ tooltip() }}
2046
+ </span>
2047
+ }
2048
+ @if (icon()) {
2049
+ <ndt-icon [name]="icon()!" />
2050
+ }
2051
+ <ng-content />
2052
+ </button>
2053
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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-flex}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:0;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-muted);display:flex;align-items:center;justify-content:center;opacity:.6;transition:opacity .15s ease-out,color .15s ease-out,background .15s ease-out,border-color .15s ease-out;line-height:0;flex-shrink:0;position:relative}.icon-button--sm{width:22px;height:22px}.icon-button--sm ::ng-deep svg{width:12px;height:12px;display:block}.icon-button--md{width:28px;height:28px}.icon-button--md ::ng-deep svg{width:16px;height:16px;display:block}.icon-button--outlined{border:1px solid var(--ndt-border-primary)}.icon-button:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}.tooltip{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-text);padding:3px 8px;border-radius:var(--ndt-border-radius-small);font-size:10px;font-weight:500;line-height:normal;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease-out;z-index:9999;box-shadow:var(--ndt-shadow-tooltip)}.tooltip--visible{opacity:1}.tooltip:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:4px solid transparent;border-top-color:var(--ndt-tooltip-bg)}\n"], dependencies: [{ kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1802
2054
  }
1803
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListComponent, decorators: [{
2055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarIconButtonComponent, decorators: [{
1804
2056
  type: Component,
1805
- args: [{ selector: 'ndt-list', standalone: true, imports: [CommonModule], template: `
1806
- @if (!hasItems()) {
1807
- <div class="empty-state">
1808
- <p>{{ emptyMessage() }}</p>
1809
- @if (emptyHint()) {
1810
- <p class="hint">{{ emptyHint() }}</p>
1811
- }
1812
- </div>
1813
- } @else if (!hasResults()) {
1814
- <div class="empty-state">
1815
- <p>{{ noResultsMessage() }}</p>
1816
- </div>
1817
- } @else {
1818
- <div class="list-container">
1819
- <ng-content />
1820
- </div>
1821
- }
1822
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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:flex;flex-direction:column;flex:1;min-height:0}.empty-state{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-state p{margin:0}.empty-state .hint{font-size:var(--ndt-font-size-xs)}.list-container{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;position:relative;scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.list-container::-webkit-scrollbar{width:8px;height:8px}.list-container::-webkit-scrollbar-track{background:transparent}.list-container::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.list-container::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}\n"] }]
2057
+ args: [{ selector: 'ndt-icon-button', standalone: true, imports: [ToolbarIconComponent], template: `
2058
+ <button
2059
+ class="icon-button"
2060
+ [class.icon-button--sm]="size() === 'sm'"
2061
+ [class.icon-button--md]="size() === 'md'"
2062
+ [class.icon-button--outlined]="variant() === 'outlined'"
2063
+ [attr.aria-label]="ariaLabel() || tooltip()"
2064
+ (mouseenter)="isHovered.set(true)"
2065
+ (mouseleave)="isHovered.set(false)"
2066
+ >
2067
+ @if (isTooltipVisible()) {
2068
+ <span class="tooltip" [class.tooltip--visible]="isHovered()">
2069
+ {{ tooltip() }}
2070
+ </span>
2071
+ }
2072
+ @if (icon()) {
2073
+ <ndt-icon [name]="icon()!" />
2074
+ }
2075
+ <ng-content />
2076
+ </button>
2077
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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-flex}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:0;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-muted);display:flex;align-items:center;justify-content:center;opacity:.6;transition:opacity .15s ease-out,color .15s ease-out,background .15s ease-out,border-color .15s ease-out;line-height:0;flex-shrink:0;position:relative}.icon-button--sm{width:22px;height:22px}.icon-button--sm ::ng-deep svg{width:12px;height:12px;display:block}.icon-button--md{width:28px;height:28px}.icon-button--md ::ng-deep svg{width:16px;height:16px;display:block}.icon-button--outlined{border:1px solid var(--ndt-border-primary)}.icon-button:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}.tooltip{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-text);padding:3px 8px;border-radius:var(--ndt-border-radius-small);font-size:10px;font-weight:500;line-height:normal;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease-out;z-index:9999;box-shadow:var(--ndt-shadow-tooltip)}.tooltip--visible{opacity:1}.tooltip:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:4px solid transparent;border-top-color:var(--ndt-tooltip-bg)}\n"] }]
1823
2078
  }] });
1824
2079
 
1825
2080
  /**
@@ -1863,6 +2118,28 @@ class ToolbarListItemComponent {
1863
2118
  * Original value before forcing (only present when isForced is true)
1864
2119
  */
1865
2120
  this.originalValue = input(undefined);
2121
+ /**
2122
+ * Whether to show the "Apply to source" button
2123
+ */
2124
+ this.showApply = input(false);
2125
+ /**
2126
+ * Current state of the apply operation
2127
+ */
2128
+ this.applyState = input('idle');
2129
+ /**
2130
+ * Whether this item is pinned to the top of the list
2131
+ */
2132
+ this.isPinned = input(false);
2133
+ /**
2134
+ * Emits when the user clicks the pin/unpin button
2135
+ */
2136
+ this.pinToggle = output();
2137
+ /**
2138
+ * Emits when the user clicks "Apply to source"
2139
+ */
2140
+ this.applyToSource = output();
2141
+ this.pinIcon = computed(() => 'pin');
2142
+ this.pinAriaLabel = computed(() => this.isPinned() ? 'Unpin item' : 'Pin item');
1866
2143
  /**
1867
2144
  * Value to display in the dot indicator.
1868
2145
  * For forced items: shows originalValue
@@ -1887,8 +2164,16 @@ class ToolbarListItemComponent {
1887
2164
  });
1888
2165
  }
1889
2166
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1890
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarListItemComponent, isStandalone: true, selector: "ndt-list-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, isForced: { classPropertyName: "isForced", publicName: "isForced", isSignal: true, isRequired: false, transformFunction: null }, currentValue: { classPropertyName: "currentValue", publicName: "currentValue", isSignal: true, isRequired: true, transformFunction: null }, originalValue: { classPropertyName: "originalValue", publicName: "originalValue", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2167
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarListItemComponent, isStandalone: true, selector: "ndt-list-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, isForced: { classPropertyName: "isForced", publicName: "isForced", isSignal: true, isRequired: false, transformFunction: null }, currentValue: { classPropertyName: "currentValue", publicName: "currentValue", isSignal: true, isRequired: true, transformFunction: null }, originalValue: { classPropertyName: "originalValue", publicName: "originalValue", isSignal: true, isRequired: false, transformFunction: null }, showApply: { classPropertyName: "showApply", publicName: "showApply", isSignal: true, isRequired: false, transformFunction: null }, applyState: { classPropertyName: "applyState", publicName: "applyState", isSignal: true, isRequired: false, transformFunction: null }, isPinned: { classPropertyName: "isPinned", publicName: "isPinned", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pinToggle: "pinToggle", applyToSource: "applyToSource" }, ngImport: i0, template: `
1891
2168
  <div class="list-item" [class.list-item--forced]="isForced()">
2169
+ <ndt-icon-button
2170
+ [icon]="pinIcon()"
2171
+ [ariaLabel]="pinAriaLabel()"
2172
+ variant="ghost"
2173
+ class="pin-button"
2174
+ [class.pin-button--pinned]="isPinned()"
2175
+ (click)="pinToggle.emit(); $event.stopPropagation()"
2176
+ />
1892
2177
  <div class="info">
1893
2178
  <h3>{{ title() }}</h3>
1894
2179
  @if (description()) {
@@ -1904,15 +2189,47 @@ class ToolbarListItemComponent {
1904
2189
  }
1905
2190
  </div>
1906
2191
  <div class="actions">
2192
+ @if (showApply() && isForced()) {
2193
+ <ndt-icon-button
2194
+ [icon]="applyState() === 'idle' ? 'export' : undefined"
2195
+ tooltip="Apply to source"
2196
+ variant="outlined"
2197
+ class="apply-button"
2198
+ [class.apply-button--loading]="applyState() === 'loading'"
2199
+ [class.apply-button--success]="applyState() === 'success'"
2200
+ [class.apply-button--error]="applyState() === 'error'"
2201
+ (click)="applyToSource.emit()"
2202
+ >
2203
+ @switch (applyState()) {
2204
+ @case ('loading') {
2205
+ <span class="apply-spinner"></span>
2206
+ }
2207
+ @case ('success') {
2208
+ <span class="apply-icon">✓</span>
2209
+ }
2210
+ @case ('error') {
2211
+ <span class="apply-icon">✕</span>
2212
+ }
2213
+ }
2214
+ </ndt-icon-button>
2215
+ }
1907
2216
  <ng-content />
1908
2217
  </div>
1909
2218
  </div>
1910
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.list-item{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);transition:background-color .2s ease;position:relative;z-index:1;flex-shrink:0}.list-item.list-item--forced{background:#3b82f60d}.list-item .info{flex:0 0 65%}.list-item .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.list-item .info .description-wrapper{display:flex;align-items:center;gap:8px;margin-top:4px}.list-item .info .dot-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0;cursor:help;transition:all .2s ease}.list-item .info .dot-indicator.dot-indicator--on{background:#22c55e;box-shadow:0 0 0 2px #22c55e33}.list-item .info .dot-indicator.dot-indicator--off{background:#ef4444;box-shadow:0 0 0 2px #ef444433}.list-item .info p{margin:0;font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);flex:1}.list-item .actions{flex:0 0 35%;display:flex;align-items:flex-start}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2219
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.list-item{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);transition:background-color .2s ease;position:relative;z-index:1;flex-shrink:0;overflow:visible}.list-item.list-item--forced{background:#3b82f60d}.list-item .info{flex:1 1 auto;min-width:0}.list-item .info h3{margin:0;font-size:var(--ndt-font-size-xs);font-weight:500;color:var(--ndt-text-primary)}.list-item .info .description-wrapper{display:flex;align-items:flex-start;gap:4px;margin-top:1px}.list-item .info .dot-indicator{display:inline-block;width:6px;height:6px;border-radius:50%;flex-shrink:0;cursor:help;transition:all .2s ease;margin-top:5px}.list-item .info .dot-indicator.dot-indicator--on{background:#22c55e;box-shadow:0 0 0 2px #22c55e33}.list-item .info .dot-indicator.dot-indicator--off{background:#ef4444;box-shadow:0 0 0 2px #ef444433}.list-item .info p{margin:0;font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-muted);flex:1;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.list-item .actions{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;overflow:visible}.pin-button{flex-shrink:0;align-self:flex-start;opacity:0;transition:opacity .2s ease}.list-item:hover .pin-button{opacity:.4}.list-item:hover .pin-button:hover{opacity:.7}.pin-button--pinned{opacity:1}.pin-button--pinned ::ng-deep .icon-button{opacity:1;color:var(--ndt-text-primary)}.apply-button--loading ::ng-deep .icon-button{opacity:1;animation:apply-pulse 1s ease-in-out infinite}.apply-button--success ::ng-deep .icon-button{opacity:1;color:#22c55e;border-color:#22c55e4d;background:#22c55e0d}.apply-button--error ::ng-deep .icon-button{opacity:1;color:#ef4444;border-color:#ef44444d;background:#ef44440d}.apply-icon{font-size:10px;line-height:1}.apply-spinner{display:block;width:10px;height:10px;border:1.5px solid var(--ndt-border-primary);border-top-color:var(--ndt-text-primary);border-radius:50%;animation:apply-spin .6s linear infinite}@keyframes apply-pulse{0%,to{opacity:.5}50%{opacity:1}}@keyframes apply-spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarIconButtonComponent, selector: "ndt-icon-button", inputs: ["icon", "tooltip", "ariaLabel", "size", "variant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1911
2220
  }
1912
2221
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarListItemComponent, decorators: [{
1913
2222
  type: Component,
1914
- args: [{ selector: 'ndt-list-item', standalone: true, imports: [CommonModule], template: `
2223
+ args: [{ selector: 'ndt-list-item', standalone: true, imports: [CommonModule, ToolbarIconComponent, ToolbarIconButtonComponent], template: `
1915
2224
  <div class="list-item" [class.list-item--forced]="isForced()">
2225
+ <ndt-icon-button
2226
+ [icon]="pinIcon()"
2227
+ [ariaLabel]="pinAriaLabel()"
2228
+ variant="ghost"
2229
+ class="pin-button"
2230
+ [class.pin-button--pinned]="isPinned()"
2231
+ (click)="pinToggle.emit(); $event.stopPropagation()"
2232
+ />
1916
2233
  <div class="info">
1917
2234
  <h3>{{ title() }}</h3>
1918
2235
  @if (description()) {
@@ -1928,10 +2245,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
1928
2245
  }
1929
2246
  </div>
1930
2247
  <div class="actions">
2248
+ @if (showApply() && isForced()) {
2249
+ <ndt-icon-button
2250
+ [icon]="applyState() === 'idle' ? 'export' : undefined"
2251
+ tooltip="Apply to source"
2252
+ variant="outlined"
2253
+ class="apply-button"
2254
+ [class.apply-button--loading]="applyState() === 'loading'"
2255
+ [class.apply-button--success]="applyState() === 'success'"
2256
+ [class.apply-button--error]="applyState() === 'error'"
2257
+ (click)="applyToSource.emit()"
2258
+ >
2259
+ @switch (applyState()) {
2260
+ @case ('loading') {
2261
+ <span class="apply-spinner"></span>
2262
+ }
2263
+ @case ('success') {
2264
+ <span class="apply-icon">✓</span>
2265
+ }
2266
+ @case ('error') {
2267
+ <span class="apply-icon">✕</span>
2268
+ }
2269
+ }
2270
+ </ndt-icon-button>
2271
+ }
1931
2272
  <ng-content />
1932
2273
  </div>
1933
2274
  </div>
1934
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.list-item{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);transition:background-color .2s ease;position:relative;z-index:1;flex-shrink:0}.list-item.list-item--forced{background:#3b82f60d}.list-item .info{flex:0 0 65%}.list-item .info h3{margin:0;font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.list-item .info .description-wrapper{display:flex;align-items:center;gap:8px;margin-top:4px}.list-item .info .dot-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0;cursor:help;transition:all .2s ease}.list-item .info .dot-indicator.dot-indicator--on{background:#22c55e;box-shadow:0 0 0 2px #22c55e33}.list-item .info .dot-indicator.dot-indicator--off{background:#ef4444;box-shadow:0 0 0 2px #ef444433}.list-item .info p{margin:0;font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);flex:1}.list-item .actions{flex:0 0 35%;display:flex;align-items:flex-start}\n"] }]
2275
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.list-item{display:flex;flex-direction:row;gap:var(--ndt-spacing-sm);background:var(--ndt-background-secondary);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);transition:background-color .2s ease;position:relative;z-index:1;flex-shrink:0;overflow:visible}.list-item.list-item--forced{background:#3b82f60d}.list-item .info{flex:1 1 auto;min-width:0}.list-item .info h3{margin:0;font-size:var(--ndt-font-size-xs);font-weight:500;color:var(--ndt-text-primary)}.list-item .info .description-wrapper{display:flex;align-items:flex-start;gap:4px;margin-top:1px}.list-item .info .dot-indicator{display:inline-block;width:6px;height:6px;border-radius:50%;flex-shrink:0;cursor:help;transition:all .2s ease;margin-top:5px}.list-item .info .dot-indicator.dot-indicator--on{background:#22c55e;box-shadow:0 0 0 2px #22c55e33}.list-item .info .dot-indicator.dot-indicator--off{background:#ef4444;box-shadow:0 0 0 2px #ef444433}.list-item .info p{margin:0;font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-muted);flex:1;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.list-item .actions{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;overflow:visible}.pin-button{flex-shrink:0;align-self:flex-start;opacity:0;transition:opacity .2s ease}.list-item:hover .pin-button{opacity:.4}.list-item:hover .pin-button:hover{opacity:.7}.pin-button--pinned{opacity:1}.pin-button--pinned ::ng-deep .icon-button{opacity:1;color:var(--ndt-text-primary)}.apply-button--loading ::ng-deep .icon-button{opacity:1;animation:apply-pulse 1s ease-in-out infinite}.apply-button--success ::ng-deep .icon-button{opacity:1;color:#22c55e;border-color:#22c55e4d;background:#22c55e0d}.apply-button--error ::ng-deep .icon-button{opacity:1;color:#ef4444;border-color:#ef44444d;background:#ef44440d}.apply-icon{font-size:10px;line-height:1}.apply-spinner{display:block;width:10px;height:10px;border:1.5px solid var(--ndt-border-primary);border-top-color:var(--ndt-text-primary);border-radius:50%;animation:apply-spin .6s linear infinite}@keyframes apply-pulse{0%,to{opacity:.5}50%{opacity:1}}@keyframes apply-spin{to{transform:rotate(360deg)}}\n"] }]
1935
2276
  }] });
1936
2277
 
1937
2278
  class ToolbarSelectComponent {
@@ -2035,7 +2376,7 @@ class ToolbarSelectComponent {
2035
2376
  }
2036
2377
  </div>
2037
2378
  </ng-template>
2038
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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\"}.ndt-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;box-shadow:0 1px 2px #0000000d}.ndt-select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 1px 3px #0000001a}.ndt-select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.ndt-select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.open .select__arrow{transform:rotate(180deg)}.ndt-select.placeholder{color:var(--ndt-text-muted)}.ndt-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}.ndt-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}.ndt-select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-sm) 0;border:2px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);box-shadow:0 4px 12px #00000026,0 2px 4px #0000001a;color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;backdrop-filter:blur(8px);z-index:1000}.ndt-select-menu::-webkit-scrollbar{width:8px;height:8px}.ndt-select-menu::-webkit-scrollbar-track{background:transparent}.ndt-select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.ndt-select-menu::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:var(--ndt-text-primary);-webkit-user-select:none;user-select:none;min-width:64px;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md) var(--ndt-spacing-sm) var(--ndt-spacing-lg);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-xs);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-weight:400;line-height:1.5;transition:background-color .15s ease}.select-menu-item:hover{background-color:#0000000f}.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),.08);font-weight:400}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.12)}.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:#0000000f}.select-menu-item:first-child{margin-top:var(--ndt-spacing-xs)}.select-menu-item:last-child{margin-bottom:var(--ndt-spacing-xs)}.select-overlay{backdrop-filter:blur(8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$1.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$1.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 }); }
2379
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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\"}.ndt-select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);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-xs);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;min-height:28px;box-sizing:border-box;box-shadow:0 1px 2px #0000000d}.ndt-select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 1px 3px #0000001a}.ndt-select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-xs);height:22px}.ndt-select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.open .select__arrow{transform:rotate(180deg)}.ndt-select.placeholder{color:var(--ndt-text-muted)}.ndt-select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;margin-right:4px;min-width:0;display:flex;align-items:center}.ndt-select__arrow{width:12px;height:12px;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}.ndt-select-menu{display:inline-flex;flex-direction:column;min-width:120px;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-medium);box-shadow:0 4px 12px #00000026,0 2px 4px #0000001a;color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;backdrop-filter:blur(8px);z-index:1000}.ndt-select-menu::-webkit-scrollbar{width:8px;height:8px}.ndt-select-menu::-webkit-scrollbar-track{background:transparent}.ndt-select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.ndt-select-menu::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:var(--ndt-text-primary);-webkit-user-select:none;user-select:none;min-width:64px;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm) var(--ndt-spacing-xs) var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-xs);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-weight:400;line-height:1.3;transition:background-color .15s ease}.select-menu-item:hover{background-color:#0000000f}.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),.08);font-weight:400}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.12)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:4px;width:3px;height:calc(100% - 8px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:#0000000f}.select-menu-item:first-child{margin-top:0}.select-menu-item:last-child{margin-bottom:0}.select-overlay{backdrop-filter:blur(8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$1.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$1.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 }); }
2039
2380
  }
2040
2381
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarSelectComponent, decorators: [{
2041
2382
  type: Component,
@@ -2090,26 +2431,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2090
2431
  }
2091
2432
  </div>
2092
2433
  </ng-template>
2093
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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\"}.ndt-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;box-shadow:0 1px 2px #0000000d}.ndt-select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 1px 3px #0000001a}.ndt-select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-sm);height:24px}.ndt-select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.open .select__arrow{transform:rotate(180deg)}.ndt-select.placeholder{color:var(--ndt-text-muted)}.ndt-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}.ndt-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}.ndt-select-menu{display:inline-flex;flex-direction:column;min-width:180px;background-color:var(--ndt-bg-primary);padding:var(--ndt-spacing-sm) 0;border:2px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-large);box-shadow:0 4px 12px #00000026,0 2px 4px #0000001a;color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;backdrop-filter:blur(8px);z-index:1000}.ndt-select-menu::-webkit-scrollbar{width:8px;height:8px}.ndt-select-menu::-webkit-scrollbar-track{background:transparent}.ndt-select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.ndt-select-menu::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:var(--ndt-text-primary);-webkit-user-select:none;user-select:none;min-width:64px;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md) var(--ndt-spacing-sm) var(--ndt-spacing-lg);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-xs);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-weight:400;line-height:1.5;transition:background-color .15s ease}.select-menu-item:hover{background-color:#0000000f}.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),.08);font-weight:400}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.12)}.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:#0000000f}.select-menu-item:first-child{margin-top:var(--ndt-spacing-xs)}.select-menu-item:last-child{margin-bottom:var(--ndt-spacing-xs)}.select-overlay{backdrop-filter:blur(8px)}\n"] }]
2434
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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\"}.ndt-select{position:relative;width:100%;min-width:120px;display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);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-xs);cursor:pointer;-webkit-user-select:none;user-select:none;transition:var(--ndt-transition-default);outline:none;min-height:28px;box-sizing:border-box;box-shadow:0 1px 2px #0000000d}.ndt-select:hover{background-color:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 1px 3px #0000001a}.ndt-select:focus-visible{outline:none;border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.small{padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);font-size:var(--ndt-font-size-xs);height:22px}.ndt-select.open{border-color:var(--ndt-primary);box-shadow:0 0 0 2px rgba(var(--ndt-primary-rgb),.2),0 1px 3px #0000001a}.ndt-select.open .select__arrow{transform:rotate(180deg)}.ndt-select.placeholder{color:var(--ndt-text-muted)}.ndt-select__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;margin-right:4px;min-width:0;display:flex;align-items:center}.ndt-select__arrow{width:12px;height:12px;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}.ndt-select-menu{display:inline-flex;flex-direction:column;min-width:120px;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-medium);box-shadow:0 4px 12px #00000026,0 2px 4px #0000001a;color:var(--ndt-text-primary);max-height:min(400px,70vh);overflow-y:auto;backdrop-filter:blur(8px);z-index:1000}.ndt-select-menu::-webkit-scrollbar{width:8px;height:8px}.ndt-select-menu::-webkit-scrollbar-track{background:transparent}.ndt-select-menu::-webkit-scrollbar-thumb{background-color:var(--ndt-border-primary);border-radius:4px;border:2px solid var(--ndt-bg-primary)}.ndt-select-menu::-webkit-scrollbar-thumb:hover{background-color:var(--ndt-text-secondary)}.select-menu-item{background-color:transparent;cursor:pointer;border:none;color:var(--ndt-text-primary);-webkit-user-select:none;user-select:none;min-width:64px;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm) var(--ndt-spacing-xs) var(--ndt-spacing-md);display:flex;align-items:center;flex-direction:row;flex:1;font-size:var(--ndt-font-size-xs);font-family:inherit;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-weight:400;line-height:1.3;transition:background-color .15s ease}.select-menu-item:hover{background-color:#0000000f}.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),.08);font-weight:400}.select-menu-item.selected:hover{background-color:rgba(var(--ndt-primary-rgb),.12)}.select-menu-item.selected:before{content:\"\";position:absolute;left:0;top:4px;width:3px;height:calc(100% - 8px);background-color:var(--ndt-primary);border-radius:2px}.select-menu-item:focus-visible{outline:none;background-color:#0000000f}.select-menu-item:first-child{margin-top:0}.select-menu-item:last-child{margin-bottom:0}.select-overlay{backdrop-filter:blur(8px)}\n"] }]
2094
2435
  }] });
2095
2436
 
2096
2437
  class ToolbarToolButtonComponent {
2097
2438
  constructor() {
2098
2439
  // Injects
2099
2440
  this.state = inject(ToolbarStateService);
2100
- this.elementRef = inject(ElementRef);
2101
2441
  // Inputs
2102
- this.title = input.required();
2442
+ this.toolLabel = input.required();
2103
2443
  this.toolId = input.required();
2104
2444
  this.badge = input();
2445
+ this.position = input('bottom');
2105
2446
  // Outputs
2106
2447
  this.open = output();
2107
2448
  // Signals
2108
2449
  this.isActive = computed(() => this.state.activeToolId() === this.toolId());
2109
2450
  this.isToolbarVisible = this.state.isVisible;
2110
2451
  this.isFocused = signal(false);
2111
- this.tooltip = computed(() => this.elementRef.nativeElement.parentElement?.getAttribute('data-tooltip') ?? '');
2112
- this.isTooltipVisible = computed(() => this.tooltip() && !this.isActive());
2452
+ this.tooltip = computed(() => this.toolLabel());
2453
+ this.isTooltipVisible = computed(() => this.tooltip() && !this.isActive() && this.isToolbarVisible());
2113
2454
  // Properties
2114
2455
  this.tooltipState = false;
2115
2456
  this.hideDelay = 3000;
@@ -2135,7 +2476,7 @@ class ToolbarToolButtonComponent {
2135
2476
  this.isFocused.set(false);
2136
2477
  }
2137
2478
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarToolButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2138
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarToolButtonComponent, isStandalone: true, selector: "ndt-tool-button", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, toolId: { classPropertyName: "toolId", publicName: "toolId", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "open" }, ngImport: i0, template: `
2479
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarToolButtonComponent, isStandalone: true, selector: "ndt-tool-button", inputs: { toolLabel: { classPropertyName: "toolLabel", publicName: "toolLabel", isSignal: true, isRequired: true, transformFunction: null }, toolId: { classPropertyName: "toolId", publicName: "toolId", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "open" }, host: { properties: { "class": "\"tooltip-position-\" + position()" } }, ngImport: i0, template: `
2139
2480
  <button
2140
2481
  class="tool-button"
2141
2482
  [class.tool-button--active]="isActive()"
@@ -2149,7 +2490,7 @@ class ToolbarToolButtonComponent {
2149
2490
  @if (isTooltipVisible()) {
2150
2491
  <span
2151
2492
  class="tooltip"
2152
- [@tooltipAnimation]="tooltipState ? 'visible' : 'hidden'"
2493
+ [class.tooltip--visible]="tooltipState"
2153
2494
  >
2154
2495
  {{ tooltip() }}
2155
2496
  </span>
@@ -2159,24 +2500,13 @@ class ToolbarToolButtonComponent {
2159
2500
  <span class="tool-button__badge">{{ badge() }}</span>
2160
2501
  }
2161
2502
  </button>
2162
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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:.125rem;right:-.0625rem;background:linear-gradient(135deg,#fca5a5,#ef4444);color:#fff;border-radius:50%;width:.875rem;height:.875rem;font-size:.5rem;font-weight:600;display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 1px 2px #0003;line-height:1}.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: [
2163
- trigger('tooltipAnimation', [
2164
- state('hidden', style({
2165
- opacity: 0,
2166
- transform: 'translateX(-50%) translateY(1rem)',
2167
- })),
2168
- state('visible', style({
2169
- opacity: 1,
2170
- transform: 'translateX(-50%) translateY(0)',
2171
- })),
2172
- transition('hidden => visible', [animate('200ms ease-out')]),
2173
- transition('visible => hidden', [animate('150ms ease-in')]),
2174
- ]),
2175
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2503
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.tool-button{display:flex;justify-content:center;align-items:center;width:30px;height:30px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative;border-radius:var(--ndt-border-radius-medium)}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:16px;height:16px;display:block;margin:auto}.tool-button__badge{position:absolute;top:.1875rem;right:.125rem;background:linear-gradient(135deg,#fca5a5,#ef4444);color:#fff;border-radius:50%;width:.6875rem;height:.6875rem;font-size:.4375rem;font-weight:600;display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 1px 2px #0003;line-height:1}.tooltip{position:absolute;background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-text);padding:.375rem .625rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;font-weight:500;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip);opacity:0;transition:opacity .15s ease-out}.tooltip--visible{opacity:1}.tooltip:after{content:\"\";position:absolute;border:5px solid transparent}:host(.tooltip-position-bottom) .tooltip{bottom:calc(100% + 9px);left:50%;transform:translate(-50%)}:host(.tooltip-position-bottom) .tooltip:after{top:100%;left:50%;transform:translate(-50%);border-top-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-top) .tooltip{top:calc(100% + 9px);left:50%;transform:translate(-50%)}:host(.tooltip-position-top) .tooltip:after{bottom:100%;left:50%;transform:translate(-50%);border-bottom-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-left) .tooltip{left:calc(100% + 9px);top:50%;transform:translateY(-50%)}:host(.tooltip-position-left) .tooltip:after{right:100%;top:50%;transform:translateY(-50%);border-right-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-right) .tooltip{right:calc(100% + 9px);top:50%;transform:translateY(-50%)}:host(.tooltip-position-right) .tooltip:after{left:100%;top:50%;transform:translateY(-50%);border-left-color:var(--ndt-tooltip-bg)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2176
2504
  }
2177
2505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarToolButtonComponent, decorators: [{
2178
2506
  type: Component,
2179
- args: [{ selector: 'ndt-tool-button', standalone: true, template: `
2507
+ args: [{ selector: 'ndt-tool-button', standalone: true, host: {
2508
+ '[class]': '"tooltip-position-" + position()',
2509
+ }, template: `
2180
2510
  <button
2181
2511
  class="tool-button"
2182
2512
  [class.tool-button--active]="isActive()"
@@ -2190,7 +2520,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2190
2520
  @if (isTooltipVisible()) {
2191
2521
  <span
2192
2522
  class="tooltip"
2193
- [@tooltipAnimation]="tooltipState ? 'visible' : 'hidden'"
2523
+ [class.tooltip--visible]="tooltipState"
2194
2524
  >
2195
2525
  {{ tooltip() }}
2196
2526
  </span>
@@ -2200,20 +2530,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2200
2530
  <span class="tool-button__badge">{{ badge() }}</span>
2201
2531
  }
2202
2532
  </button>
2203
- `, animations: [
2204
- trigger('tooltipAnimation', [
2205
- state('hidden', style({
2206
- opacity: 0,
2207
- transform: 'translateX(-50%) translateY(1rem)',
2208
- })),
2209
- state('visible', style({
2210
- opacity: 1,
2211
- transform: 'translateX(-50%) translateY(0)',
2212
- })),
2213
- transition('hidden => visible', [animate('200ms ease-out')]),
2214
- transition('visible => hidden', [animate('150ms ease-in')]),
2215
- ]),
2216
- ], 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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:.125rem;right:-.0625rem;background:linear-gradient(135deg,#fca5a5,#ef4444);color:#fff;border-radius:50%;width:.875rem;height:.875rem;font-size:.5rem;font-weight:600;display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 1px 2px #0003;line-height:1}.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"] }]
2533
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.tool-button{display:flex;justify-content:center;align-items:center;width:30px;height:30px;border:0;background:transparent;color:var(--ndt-text-primary);transition:var(--ndt-transition-default);cursor:pointer;opacity:.5;position:relative;border-radius:var(--ndt-border-radius-medium)}.tool-button--active,.tool-button:hover{background:var(--ndt-hover-bg);opacity:1}.tool-button ::ng-deep svg{width:16px;height:16px;display:block;margin:auto}.tool-button__badge{position:absolute;top:.1875rem;right:.125rem;background:linear-gradient(135deg,#fca5a5,#ef4444);color:#fff;border-radius:50%;width:.6875rem;height:.6875rem;font-size:.4375rem;font-weight:600;display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 1px 2px #0003;line-height:1}.tooltip{position:absolute;background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-text);padding:.375rem .625rem;border-radius:var(--ndt-border-radius-medium);font-size:.75rem;font-weight:500;white-space:nowrap;pointer-events:none;z-index:1000;box-shadow:var(--ndt-shadow-tooltip);opacity:0;transition:opacity .15s ease-out}.tooltip--visible{opacity:1}.tooltip:after{content:\"\";position:absolute;border:5px solid transparent}:host(.tooltip-position-bottom) .tooltip{bottom:calc(100% + 9px);left:50%;transform:translate(-50%)}:host(.tooltip-position-bottom) .tooltip:after{top:100%;left:50%;transform:translate(-50%);border-top-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-top) .tooltip{top:calc(100% + 9px);left:50%;transform:translate(-50%)}:host(.tooltip-position-top) .tooltip:after{bottom:100%;left:50%;transform:translate(-50%);border-bottom-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-left) .tooltip{left:calc(100% + 9px);top:50%;transform:translateY(-50%)}:host(.tooltip-position-left) .tooltip:after{right:100%;top:50%;transform:translateY(-50%);border-right-color:var(--ndt-tooltip-bg)}:host(.tooltip-position-right) .tooltip{right:calc(100% + 9px);top:50%;transform:translateY(-50%)}:host(.tooltip-position-right) .tooltip:after{left:100%;top:50%;transform:translateY(-50%);border-left-color:var(--ndt-tooltip-bg)}\n"] }]
2217
2534
  }] });
2218
2535
 
2219
2536
  class ToolbarWindowComponent {
@@ -2275,7 +2592,7 @@ class ToolbarWindowComponent {
2275
2592
  <ng-content></ng-content>
2276
2593
  </div>
2277
2594
  </div>
2278
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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\"}.ndt-window{box-sizing:border-box;display:flex;flex-direction:column;position:relative;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) var(--ndt-window-padding) var(--ndt-spacing-xs);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);contain:layout style}.ndt-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;position:relative;z-index:10;flex-shrink:0}.ndt-header h1{font-size:var(--ndt-font-size-lg);line-height:1.2;margin:0;color:var(--ndt-text-primary)}.ndt-header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm);flex-wrap:wrap;margin-bottom:var(--ndt-spacing-xs)}.ndt-header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:2px 6px;border-radius:var(--ndt-border-radius-small);font-weight:600;text-transform:uppercase;letter-spacing:.5px;line-height:1;white-space:nowrap}.ndt-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}.ndt-header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-width:0}.ndt-header__controls{display:flex;gap:var(--ndt-spacing-sm);flex-shrink:0;align-items:flex-start}.ndt-content{position:relative;flex:1;overflow:auto;min-height:0}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md);flex-shrink:0;position:relative;z-index:5}.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"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2595
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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\"}.ndt-window{box-sizing:border-box;display:flex;flex-direction:column;position:relative;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-spacing-md) var(--ndt-spacing-md) var(--ndt-spacing-xs);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);contain:layout style}.ndt-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;position:relative;z-index:10;flex-shrink:0}.ndt-header h1{font-size:var(--ndt-font-size-md);line-height:1.2;margin:0;color:var(--ndt-text-primary)}.ndt-header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm);flex-wrap:wrap;margin-bottom:var(--ndt-spacing-xs)}.ndt-header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:2px 6px;border-radius:var(--ndt-border-radius-small);font-weight:600;text-transform:uppercase;letter-spacing:.5px;line-height:1;white-space:nowrap}.ndt-header__description{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;line-height:1.4;margin:0}.ndt-header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-width:0}.ndt-header__controls{display:flex;gap:var(--ndt-spacing-sm);flex-shrink:0;align-items:flex-start}.ndt-content{position:relative;flex:1;overflow:auto;min-height:0}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-sm);flex-shrink:0;position:relative;z-index:5}.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"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2279
2596
  }
2280
2597
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarWindowComponent, decorators: [{
2281
2598
  type: Component,
@@ -2319,7 +2636,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2319
2636
  <ng-content></ng-content>
2320
2637
  </div>
2321
2638
  </div>
2322
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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\"}.ndt-window{box-sizing:border-box;display:flex;flex-direction:column;position:relative;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) var(--ndt-window-padding) var(--ndt-spacing-xs);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);contain:layout style}.ndt-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;position:relative;z-index:10;flex-shrink:0}.ndt-header h1{font-size:var(--ndt-font-size-lg);line-height:1.2;margin:0;color:var(--ndt-text-primary)}.ndt-header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm);flex-wrap:wrap;margin-bottom:var(--ndt-spacing-xs)}.ndt-header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:2px 6px;border-radius:var(--ndt-border-radius-small);font-weight:600;text-transform:uppercase;letter-spacing:.5px;line-height:1;white-space:nowrap}.ndt-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}.ndt-header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-width:0}.ndt-header__controls{display:flex;gap:var(--ndt-spacing-sm);flex-shrink:0;align-items:flex-start}.ndt-content{position:relative;flex:1;overflow:auto;min-height:0}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-md);margin-top:var(--ndt-spacing-md);flex-shrink:0;position:relative;z-index:5}.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"] }]
2639
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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\"}.ndt-window{box-sizing:border-box;display:flex;flex-direction:column;position:relative;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-spacing-md) var(--ndt-spacing-md) var(--ndt-spacing-xs);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);contain:layout style}.ndt-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;position:relative;z-index:10;flex-shrink:0}.ndt-header h1{font-size:var(--ndt-font-size-md);line-height:1.2;margin:0;color:var(--ndt-text-primary)}.ndt-header__title{display:flex;align-items:center;gap:var(--ndt-spacing-sm);flex-wrap:wrap;margin-bottom:var(--ndt-spacing-xs)}.ndt-header__title .beta-tag{font-size:var(--ndt-font-size-xxs, .65rem);background:var(--ndt-purple, #8b5cf6);color:var(--ndt-text-on-primary);padding:2px 6px;border-radius:var(--ndt-border-radius-small);font-weight:600;text-transform:uppercase;letter-spacing:.5px;line-height:1;white-space:nowrap}.ndt-header__description{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;line-height:1.4;margin:0}.ndt-header__content{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-width:0}.ndt-header__controls{display:flex;gap:var(--ndt-spacing-sm);flex-shrink:0;align-items:flex-start}.ndt-content{position:relative;flex:1;overflow:auto;min-height:0}.divider{height:1px;background-color:var(--ndt-border-primary);margin-bottom:var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-sm);flex-shrink:0;position:relative;z-index:5}.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"] }]
2323
2640
  }] });
2324
2641
 
2325
2642
  class ToolbarToolComponent {
@@ -2329,9 +2646,17 @@ class ToolbarToolComponent {
2329
2646
  this.buttonComponent = contentChild(ToolbarToolButtonComponent);
2330
2647
  this.options = input.required();
2331
2648
  this.icon = input.required();
2332
- this.title = input.required();
2649
+ this.toolTitle = input.required();
2333
2650
  this.badge = input();
2334
2651
  this.isActive = computed(() => this.state.activeToolId() === this.options().id);
2652
+ this.slideDirection = computed(() => {
2653
+ switch (this.state.position()) {
2654
+ case 'bottom': return 'up';
2655
+ case 'top': return 'down';
2656
+ case 'left': return 'right';
2657
+ case 'right': return 'left';
2658
+ }
2659
+ });
2335
2660
  this.height = computed(() => {
2336
2661
  switch (this.options().size) {
2337
2662
  case 'small':
@@ -2361,19 +2686,62 @@ class ToolbarToolComponent {
2361
2686
  }
2362
2687
  });
2363
2688
  this.positions = computed(() => {
2364
- const triggerXPosition = this.getButtonContainerXPosition();
2365
- const windowCenter = window.innerWidth / 2;
2366
- const offsetX = windowCenter - triggerXPosition - 22;
2367
- return [
2368
- {
2369
- originX: 'center',
2370
- originY: 'center',
2371
- overlayX: 'center',
2372
- overlayY: 'center',
2373
- offsetY: -(Math.ceil(this.height() / 2) + 36),
2374
- offsetX,
2375
- },
2376
- ];
2689
+ const position = this.state.position();
2690
+ const triggerRect = this.getButtonContainerRect();
2691
+ switch (position) {
2692
+ case 'bottom': {
2693
+ // Original logic: overlay centered above toolbar
2694
+ const windowCenter = window.innerWidth / 2;
2695
+ const offsetX = windowCenter - (triggerRect?.left ?? 0) - 22;
2696
+ return [{
2697
+ originX: 'center',
2698
+ originY: 'center',
2699
+ overlayX: 'center',
2700
+ overlayY: 'center',
2701
+ offsetY: -(Math.ceil(this.height() / 2) + 36),
2702
+ offsetX,
2703
+ }];
2704
+ }
2705
+ case 'top': {
2706
+ // Overlay centered below toolbar
2707
+ const windowCenter = window.innerWidth / 2;
2708
+ const offsetX = windowCenter - (triggerRect?.left ?? 0) - 22;
2709
+ return [{
2710
+ originX: 'center',
2711
+ originY: 'center',
2712
+ overlayX: 'center',
2713
+ overlayY: 'center',
2714
+ offsetY: Math.ceil(this.height() / 2) + 36,
2715
+ offsetX,
2716
+ }];
2717
+ }
2718
+ case 'left': {
2719
+ // Overlay centered to the right of toolbar
2720
+ const windowMiddle = window.innerHeight / 2;
2721
+ const offsetY = windowMiddle - (triggerRect?.top ?? 0) - 22;
2722
+ return [{
2723
+ originX: 'center',
2724
+ originY: 'center',
2725
+ overlayX: 'center',
2726
+ overlayY: 'center',
2727
+ offsetX: Math.ceil(this.width() / 2) + 36,
2728
+ offsetY,
2729
+ }];
2730
+ }
2731
+ case 'right': {
2732
+ // Overlay centered to the left of toolbar
2733
+ const windowMiddle = window.innerHeight / 2;
2734
+ const offsetY = windowMiddle - (triggerRect?.top ?? 0) - 22;
2735
+ return [{
2736
+ originX: 'center',
2737
+ originY: 'center',
2738
+ overlayX: 'center',
2739
+ overlayY: 'center',
2740
+ offsetX: -(Math.ceil(this.width() / 2) + 36),
2741
+ offsetY,
2742
+ }];
2743
+ }
2744
+ }
2377
2745
  });
2378
2746
  }
2379
2747
  onOpen() {
@@ -2382,12 +2750,11 @@ class ToolbarToolComponent {
2382
2750
  onClose() {
2383
2751
  this.state.setActiveTool(null);
2384
2752
  }
2385
- getButtonContainerXPosition() {
2386
- const buttonContainerRect = this.buttonContainer()?.nativeElement?.getBoundingClientRect();
2387
- return buttonContainerRect?.left ?? 0;
2753
+ getButtonContainerRect() {
2754
+ return this.buttonContainer()?.nativeElement?.getBoundingClientRect();
2388
2755
  }
2389
2756
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2390
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarToolComponent, isStandalone: true, selector: "ndt-toolbar-tool", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "buttonComponent", first: true, predicate: ToolbarToolButtonComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "buttonContainer", first: true, predicate: ["buttonContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
2757
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarToolComponent, isStandalone: true, selector: "ndt-toolbar-tool", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, toolTitle: { classPropertyName: "toolTitle", publicName: "toolTitle", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "buttonComponent", first: true, predicate: ToolbarToolButtonComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "buttonContainer", first: true, predicate: ["buttonContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
2391
2758
  <div #trigger="cdkOverlayOrigin" class="ndt-toolbar-tool" cdkOverlayOrigin>
2392
2759
  <div
2393
2760
  class="ndt-toolbar-tool__icon"
@@ -2396,9 +2763,9 @@ class ToolbarToolComponent {
2396
2763
  (keydown.space)="onOpen()"
2397
2764
  tabindex="0"
2398
2765
  >
2399
- <div #buttonContainer [attr.data-tooltip]="title()">
2766
+ <div #buttonContainer>
2400
2767
  @if (icon()) {
2401
- <ndt-tool-button [title]="title()" [toolId]="options().id" [badge]="badge()">
2768
+ <ndt-tool-button [toolLabel]="toolTitle()" [toolId]="options().id" [badge]="badge()" [position]="state.position()">
2402
2769
  <ndt-icon [name]="icon()" />
2403
2770
  </ndt-tool-button>
2404
2771
  } @else {
@@ -2418,36 +2785,13 @@ class ToolbarToolComponent {
2418
2785
  [cdkConnectedOverlayPanelClass]="['ndt-overlay-panel', 'ndt-tool-overlay']"
2419
2786
  cdkConnectedOverlay
2420
2787
  >
2421
- <ndt-window [@slideAnimation] [config]="options()" (closed)="onClose()">
2788
+ <ndt-window [class]="'ndt-slide-' + slideDirection()" [config]="options()" (closed)="onClose()">
2422
2789
  <ng-content />
2423
2790
  </ndt-window>
2424
2791
  </ng-template>
2425
2792
  }
2426
2793
  </div>
2427
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ToolbarWindowComponent, selector: "ndt-window", inputs: ["config"], outputs: ["closed", "maximize", "minimize"] }, { kind: "component", type: ToolbarToolButtonComponent, selector: "ndt-tool-button", inputs: ["title", "toolId", "badge"], outputs: ["open"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], animations: [
2428
- trigger('slideAnimation', [
2429
- transition(':enter', [
2430
- style({
2431
- transform: 'translateY(20px)',
2432
- opacity: 0,
2433
- }),
2434
- animate('400ms cubic-bezier(0.4, 0, 0.2, 1)', style({
2435
- transform: 'translateY(0)',
2436
- opacity: 1,
2437
- })),
2438
- ]),
2439
- transition(':leave', [
2440
- style({
2441
- transform: 'translateY(0)',
2442
- opacity: 1,
2443
- }),
2444
- animate('400ms cubic-bezier(0.4, 0, 0.2, 1)', style({
2445
- transform: 'translateY(20px)',
2446
- opacity: 0,
2447
- })),
2448
- ]),
2449
- ]),
2450
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2794
+ `, isInline: true, styles: [":host{display:flex;--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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.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$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ToolbarWindowComponent, selector: "ndt-window", inputs: ["config"], outputs: ["closed", "maximize", "minimize"] }, { kind: "component", type: ToolbarToolButtonComponent, selector: "ndt-tool-button", inputs: ["toolLabel", "toolId", "badge", "position"], outputs: ["open"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2451
2795
  }
2452
2796
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarToolComponent, decorators: [{
2453
2797
  type: Component,
@@ -2466,9 +2810,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2466
2810
  (keydown.space)="onOpen()"
2467
2811
  tabindex="0"
2468
2812
  >
2469
- <div #buttonContainer [attr.data-tooltip]="title()">
2813
+ <div #buttonContainer>
2470
2814
  @if (icon()) {
2471
- <ndt-tool-button [title]="title()" [toolId]="options().id" [badge]="badge()">
2815
+ <ndt-tool-button [toolLabel]="toolTitle()" [toolId]="options().id" [badge]="badge()" [position]="state.position()">
2472
2816
  <ndt-icon [name]="icon()" />
2473
2817
  </ndt-tool-button>
2474
2818
  } @else {
@@ -2488,109 +2832,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
2488
2832
  [cdkConnectedOverlayPanelClass]="['ndt-overlay-panel', 'ndt-tool-overlay']"
2489
2833
  cdkConnectedOverlay
2490
2834
  >
2491
- <ndt-window [@slideAnimation] [config]="options()" (closed)="onClose()">
2835
+ <ndt-window [class]="'ndt-slide-' + slideDirection()" [config]="options()" (closed)="onClose()">
2492
2836
  <ng-content />
2493
- </ndt-window>
2494
- </ng-template>
2495
- }
2496
- </div>
2497
- `, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
2498
- trigger('slideAnimation', [
2499
- transition(':enter', [
2500
- style({
2501
- transform: 'translateY(20px)',
2502
- opacity: 0,
2503
- }),
2504
- animate('400ms cubic-bezier(0.4, 0, 0.2, 1)', style({
2505
- transform: 'translateY(0)',
2506
- opacity: 1,
2507
- })),
2508
- ]),
2509
- transition(':leave', [
2510
- style({
2511
- transform: 'translateY(0)',
2512
- opacity: 1,
2513
- }),
2514
- animate('400ms cubic-bezier(0.4, 0, 0.2, 1)', style({
2515
- transform: 'translateY(20px)',
2516
- opacity: 0,
2517
- })),
2518
- ]),
2519
- ]),
2520
- ], 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.tool{position:relative}.trigger{cursor:pointer}\n"] }]
2521
- }] });
2522
-
2523
- class ToolbarStorageService {
2524
- constructor() {
2525
- this.PREFIX = 'AngularToolbar.';
2526
- this.TOOLS_KEY = `${this.PREFIX}keys`;
2527
- this.SETTINGS_KEY = `${this.PREFIX}settings`;
2528
- }
2529
- set(key, value) {
2530
- const toolKey = this.getToolKey(key);
2531
- this.addToolKey(toolKey);
2532
- localStorage.setItem(toolKey, JSON.stringify(value));
2533
- }
2534
- get(key) {
2535
- const toolKey = this.getToolKey(key);
2536
- const item = localStorage.getItem(toolKey);
2537
- return item ? JSON.parse(item) : null;
2538
- }
2539
- remove(key) {
2540
- const toolKey = this.getToolKey(key);
2541
- localStorage.removeItem(toolKey);
2542
- this.removeToolKey(toolKey);
2543
- }
2544
- getAllSettings() {
2545
- const settings = {};
2546
- const keys = this.getToolKeys();
2547
- keys.forEach((key) => {
2548
- const value = this.get(key);
2549
- if (value !== null) {
2550
- settings[key] = value;
2551
- }
2552
- });
2553
- return settings;
2554
- }
2555
- setAllSettings(settings) {
2556
- Object.entries(settings).forEach(([key, value]) => {
2557
- this.set(key, value);
2558
- });
2559
- }
2560
- clearAllSettings() {
2561
- const keys = this.getToolKeys();
2562
- keys.forEach((key) => {
2563
- this.remove(key);
2564
- });
2565
- }
2566
- getToolKeys() {
2567
- return JSON.parse(localStorage.getItem(this.TOOLS_KEY) ?? '[]');
2568
- }
2569
- addToolKey(key) {
2570
- const currentKeys = this.getToolKeys();
2571
- if (currentKeys.includes(key)) {
2572
- return;
2573
- }
2574
- currentKeys.push(key);
2575
- localStorage.setItem(this.TOOLS_KEY, JSON.stringify(currentKeys));
2576
- }
2577
- removeToolKey(key) {
2578
- const currentKeys = this.getToolKeys();
2579
- const index = currentKeys.indexOf(key);
2580
- if (index !== -1) {
2581
- currentKeys.splice(index, 1);
2582
- }
2583
- localStorage.setItem(this.TOOLS_KEY, JSON.stringify(currentKeys));
2584
- }
2585
- getToolKey(key) {
2586
- return key.includes(this.PREFIX) ? key : this.PREFIX + key;
2587
- }
2588
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2589
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, providedIn: 'root' }); }
2590
- }
2591
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStorageService, decorators: [{
2592
- type: Injectable,
2593
- args: [{ providedIn: 'root' }]
2837
+ </ndt-window>
2838
+ </ng-template>
2839
+ }
2840
+ </div>
2841
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;--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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.tool{position:relative}.trigger{cursor:pointer}\n"] }]
2594
2842
  }] });
2595
2843
 
2596
2844
  /**
@@ -2626,6 +2874,10 @@ class ToolbarInternalAppFeaturesService {
2626
2874
  * Signal containing current features with merged forced state
2627
2875
  */
2628
2876
  this.features = toSignal(this.features$, { initialValue: [] });
2877
+ // Apply to source
2878
+ this.applyCallback = signal(null);
2879
+ this.applyStates = signal({});
2880
+ this.hasApplyCallback = computed(() => this.applyCallback() !== null);
2629
2881
  this.loadForcedFeatures();
2630
2882
  }
2631
2883
  /**
@@ -2752,6 +3004,24 @@ class ToolbarInternalAppFeaturesService {
2752
3004
  disabled: [...state.disabled],
2753
3005
  };
2754
3006
  }
3007
+ setApplyToSource(callback) {
3008
+ this.applyCallback.set(callback);
3009
+ }
3010
+ async applyToSource(id, value) {
3011
+ const callback = this.applyCallback();
3012
+ if (!callback)
3013
+ return;
3014
+ this.applyStates.update((s) => ({ ...s, [id]: 'loading' }));
3015
+ try {
3016
+ await callback(id, value);
3017
+ this.applyStates.update((s) => ({ ...s, [id]: 'success' }));
3018
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
3019
+ }
3020
+ catch {
3021
+ this.applyStates.update((s) => ({ ...s, [id]: 'error' }));
3022
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
3023
+ }
3024
+ }
2755
3025
  /**
2756
3026
  * Merge natural app features with forced state.
2757
3027
  *
@@ -2859,6 +3129,7 @@ class ToolbarAppFeaturesToolComponent {
2859
3129
  // Signals
2860
3130
  this.activeFilter = signal('all');
2861
3131
  this.searchQuery = signal('');
3132
+ this.pinnedIds = signal(new Set());
2862
3133
  this.features = this.appFeaturesService.features;
2863
3134
  // Computed badge count for forced values
2864
3135
  this.badgeCount = computed(() => {
@@ -2884,8 +3155,15 @@ class ToolbarAppFeaturesToolComponent {
2884
3155
  (this.activeFilter() === 'disabled' && !feature.isEnabled);
2885
3156
  return matchesSearch && matchesFilter;
2886
3157
  });
2887
- // Sort alphabetically by name
2888
- return filtered.sort((a, b) => a.name.localeCompare(b.name));
3158
+ const pinned = this.pinnedIds();
3159
+ // Sort pinned first, then alphabetically within each group
3160
+ return filtered.sort((a, b) => {
3161
+ const aPinned = pinned.has(a.id);
3162
+ const bPinned = pinned.has(b.id);
3163
+ if (aPinned !== bPinned)
3164
+ return aPinned ? -1 : 1;
3165
+ return a.name.localeCompare(b.name);
3166
+ });
2889
3167
  });
2890
3168
  this.hasNoFilteredFeatures = computed(() => this.filteredFeatures().length === 0);
2891
3169
  // Other properties
@@ -2907,6 +3185,8 @@ class ToolbarAppFeaturesToolComponent {
2907
3185
  { value: 'off', label: 'Disabled' },
2908
3186
  { value: 'on', label: 'Enabled' },
2909
3187
  ];
3188
+ // Apply to source (delegated to internal service)
3189
+ this.hasApplyCallback = this.appFeaturesService.hasApplyCallback;
2910
3190
  this.loadViewState();
2911
3191
  // Save view state on changes
2912
3192
  effect(() => {
@@ -2914,6 +3194,7 @@ class ToolbarAppFeaturesToolComponent {
2914
3194
  searchQuery: this.searchQuery(),
2915
3195
  filter: this.activeFilter(),
2916
3196
  sortOrder: 'asc',
3197
+ pinnedIds: [...this.pinnedIds()],
2917
3198
  };
2918
3199
  this.storageService.set(this.VIEW_STATE_KEY, state);
2919
3200
  });
@@ -2927,12 +3208,21 @@ class ToolbarAppFeaturesToolComponent {
2927
3208
  if (['all', 'forced', 'enabled', 'disabled'].includes(filter)) {
2928
3209
  this.activeFilter.set(filter);
2929
3210
  }
3211
+ if (saved.pinnedIds?.length) {
3212
+ this.pinnedIds.set(new Set(saved.pinnedIds));
3213
+ }
2930
3214
  }
2931
3215
  }
2932
3216
  catch {
2933
3217
  // Use defaults on error
2934
3218
  }
2935
3219
  }
3220
+ getApplyState(featureId) {
3221
+ return this.appFeaturesService.applyStates()[featureId] ?? 'idle';
3222
+ }
3223
+ onApplyToSource(featureId, value) {
3224
+ this.appFeaturesService.applyToSource(featureId, value);
3225
+ }
2936
3226
  // Public methods
2937
3227
  /**
2938
3228
  * Handle filter dropdown change.
@@ -2970,6 +3260,18 @@ class ToolbarAppFeaturesToolComponent {
2970
3260
  onSearchChange(query) {
2971
3261
  this.searchQuery.set(query);
2972
3262
  }
3263
+ togglePin(featureId) {
3264
+ this.pinnedIds.update((ids) => {
3265
+ const next = new Set(ids);
3266
+ if (next.has(featureId)) {
3267
+ next.delete(featureId);
3268
+ }
3269
+ else {
3270
+ next.add(featureId);
3271
+ }
3272
+ return next;
3273
+ });
3274
+ }
2973
3275
  // Protected methods
2974
3276
  /**
2975
3277
  * Get the dropdown value for a feature's current state.
@@ -2986,7 +3288,7 @@ class ToolbarAppFeaturesToolComponent {
2986
3288
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarAppFeaturesToolComponent, isStandalone: true, selector: "ndt-app-features-tool", ngImport: i0, template: `
2987
3289
  <ndt-toolbar-tool
2988
3290
  [options]="options"
2989
- title="App Features"
3291
+ toolTitle="App Features"
2990
3292
  icon="puzzle"
2991
3293
  [badge]="badgeCount()"
2992
3294
  >
@@ -2998,7 +3300,6 @@ class ToolbarAppFeaturesToolComponent {
2998
3300
  placeholder="Search features..."
2999
3301
  />
3000
3302
  <div class="filter-wrapper">
3001
- <ndt-icon name="filter" class="filter-icon" />
3002
3303
  <ndt-select
3003
3304
  [value]="activeFilter()"
3004
3305
  [options]="filterOptions"
@@ -3022,6 +3323,11 @@ class ToolbarAppFeaturesToolComponent {
3022
3323
  [isForced]="feature.isForced"
3023
3324
  [currentValue]="feature.isEnabled"
3024
3325
  [originalValue]="feature.originalValue"
3326
+ [isPinned]="pinnedIds().has(feature.id)"
3327
+ (pinToggle)="togglePin(feature.id)"
3328
+ [showApply]="hasApplyCallback()"
3329
+ [applyState]="getApplyState(feature.id)"
3330
+ (applyToSource)="onApplyToSource(feature.id, feature.isEnabled)"
3025
3331
  >
3026
3332
  <ndt-select
3027
3333
  [value]="getFeatureValue(feature)"
@@ -3035,7 +3341,7 @@ class ToolbarAppFeaturesToolComponent {
3035
3341
  </ndt-list>
3036
3342
  </div>
3037
3343
  </ndt-toolbar-tool>
3038
- `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3344
+ `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue", "showApply", "applyState", "isPinned"], outputs: ["pinToggle", "applyToSource"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3039
3345
  }
3040
3346
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarAppFeaturesToolComponent, decorators: [{
3041
3347
  type: Component,
@@ -3044,13 +3350,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3044
3350
  ToolbarToolComponent,
3045
3351
  ToolbarInputComponent,
3046
3352
  ToolbarSelectComponent,
3047
- ToolbarIconComponent,
3048
3353
  ToolbarListComponent,
3049
3354
  ToolbarListItemComponent,
3050
3355
  ], template: `
3051
3356
  <ndt-toolbar-tool
3052
3357
  [options]="options"
3053
- title="App Features"
3358
+ toolTitle="App Features"
3054
3359
  icon="puzzle"
3055
3360
  [badge]="badgeCount()"
3056
3361
  >
@@ -3062,7 +3367,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3062
3367
  placeholder="Search features..."
3063
3368
  />
3064
3369
  <div class="filter-wrapper">
3065
- <ndt-icon name="filter" class="filter-icon" />
3066
3370
  <ndt-select
3067
3371
  [value]="activeFilter()"
3068
3372
  [options]="filterOptions"
@@ -3086,6 +3390,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3086
3390
  [isForced]="feature.isForced"
3087
3391
  [currentValue]="feature.isEnabled"
3088
3392
  [originalValue]="feature.originalValue"
3393
+ [isPinned]="pinnedIds().has(feature.id)"
3394
+ (pinToggle)="togglePin(feature.id)"
3395
+ [showApply]="hasApplyCallback()"
3396
+ [applyState]="getApplyState(feature.id)"
3397
+ (applyToSource)="onApplyToSource(feature.id, feature.isEnabled)"
3089
3398
  >
3090
3399
  <ndt-select
3091
3400
  [value]="getFeatureValue(feature)"
@@ -3099,7 +3408,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3099
3408
  </ndt-list>
3100
3409
  </div>
3101
3410
  </ndt-toolbar-tool>
3102
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"] }]
3411
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"] }]
3103
3412
  }], ctorParameters: () => [] });
3104
3413
 
3105
3414
  class ToolbarInternalFeatureFlagService {
@@ -3136,6 +3445,10 @@ class ToolbarInternalFeatureFlagService {
3136
3445
  });
3137
3446
  }));
3138
3447
  this.flags = toSignal(this.flags$, { initialValue: [] });
3448
+ // Apply to source
3449
+ this.applyCallback = signal(null);
3450
+ this.applyStates = signal({});
3451
+ this.hasApplyCallback = computed(() => this.applyCallback() !== null);
3139
3452
  this.loadForcedFlags();
3140
3453
  }
3141
3454
  setAppFlags(flags) {
@@ -3197,6 +3510,24 @@ class ToolbarInternalFeatureFlagService {
3197
3510
  getCurrentForcedState() {
3198
3511
  return this.forcedFlagsSubject.value;
3199
3512
  }
3513
+ setApplyToSource(callback) {
3514
+ this.applyCallback.set(callback);
3515
+ }
3516
+ async applyToSource(id, value) {
3517
+ const callback = this.applyCallback();
3518
+ if (!callback)
3519
+ return;
3520
+ this.applyStates.update((s) => ({ ...s, [id]: 'loading' }));
3521
+ try {
3522
+ await callback(id, value);
3523
+ this.applyStates.update((s) => ({ ...s, [id]: 'success' }));
3524
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
3525
+ }
3526
+ catch {
3527
+ this.applyStates.update((s) => ({ ...s, [id]: 'error' }));
3528
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
3529
+ }
3530
+ }
3200
3531
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalFeatureFlagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3201
3532
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalFeatureFlagService, providedIn: 'root' }); }
3202
3533
  }
@@ -3215,6 +3546,7 @@ class ToolbarFeatureFlagsToolComponent {
3215
3546
  // Signals
3216
3547
  this.activeFilter = signal('all');
3217
3548
  this.searchQuery = signal('');
3549
+ this.pinnedIds = signal(new Set());
3218
3550
  this.flags = this.featureFlags.flags;
3219
3551
  // Computed badge count for forced values
3220
3552
  this.badgeCount = computed(() => {
@@ -3240,8 +3572,15 @@ class ToolbarFeatureFlagsToolComponent {
3240
3572
  (this.activeFilter() === 'disabled' && !flag.isEnabled);
3241
3573
  return matchesSearch && matchesFilter;
3242
3574
  });
3243
- // Sort alphabetically by name
3244
- return filtered.sort((a, b) => a.name.localeCompare(b.name));
3575
+ const pinned = this.pinnedIds();
3576
+ // Sort pinned first, then alphabetically within each group
3577
+ return filtered.sort((a, b) => {
3578
+ const aPinned = pinned.has(a.id);
3579
+ const bPinned = pinned.has(b.id);
3580
+ if (aPinned !== bPinned)
3581
+ return aPinned ? -1 : 1;
3582
+ return a.name.localeCompare(b.name);
3583
+ });
3245
3584
  });
3246
3585
  this.hasNoFilteredFlags = computed(() => this.filteredFlags().length === 0);
3247
3586
  // Other properties
@@ -3251,7 +3590,6 @@ class ToolbarFeatureFlagsToolComponent {
3251
3590
  isClosable: true,
3252
3591
  size: 'tall',
3253
3592
  id: 'ndt-feature-flags',
3254
- isBeta: true,
3255
3593
  };
3256
3594
  this.filterOptions = [
3257
3595
  { value: 'all', label: 'All Flags' },
@@ -3264,6 +3602,8 @@ class ToolbarFeatureFlagsToolComponent {
3264
3602
  { value: 'off', label: 'Forced Off' },
3265
3603
  { value: 'on', label: 'Forced On' },
3266
3604
  ];
3605
+ // Apply to source (delegated to internal service)
3606
+ this.hasApplyCallback = this.featureFlags.hasApplyCallback;
3267
3607
  this.loadViewState();
3268
3608
  // Save view state on changes
3269
3609
  effect(() => {
@@ -3271,6 +3611,7 @@ class ToolbarFeatureFlagsToolComponent {
3271
3611
  searchQuery: this.searchQuery(),
3272
3612
  filter: this.activeFilter(),
3273
3613
  sortOrder: 'asc',
3614
+ pinnedIds: [...this.pinnedIds()],
3274
3615
  };
3275
3616
  this.storageService.set(this.VIEW_STATE_KEY, state);
3276
3617
  });
@@ -3284,12 +3625,21 @@ class ToolbarFeatureFlagsToolComponent {
3284
3625
  if (['all', 'forced', 'enabled', 'disabled'].includes(filter)) {
3285
3626
  this.activeFilter.set(filter);
3286
3627
  }
3628
+ if (saved.pinnedIds?.length) {
3629
+ this.pinnedIds.set(new Set(saved.pinnedIds));
3630
+ }
3287
3631
  }
3288
3632
  }
3289
3633
  catch {
3290
3634
  // Use defaults on error
3291
3635
  }
3292
3636
  }
3637
+ getApplyState(flagId) {
3638
+ return this.featureFlags.applyStates()[flagId] ?? 'idle';
3639
+ }
3640
+ onApplyToSource(flagId, value) {
3641
+ this.featureFlags.applyToSource(flagId, value);
3642
+ }
3293
3643
  // Public methods
3294
3644
  onFilterChange(value) {
3295
3645
  const filter = this.filterOptions.find((f) => f.value === value);
@@ -3313,6 +3663,18 @@ class ToolbarFeatureFlagsToolComponent {
3313
3663
  onSearchChange(query) {
3314
3664
  this.searchQuery.set(query);
3315
3665
  }
3666
+ togglePin(flagId) {
3667
+ this.pinnedIds.update((ids) => {
3668
+ const next = new Set(ids);
3669
+ if (next.has(flagId)) {
3670
+ next.delete(flagId);
3671
+ }
3672
+ else {
3673
+ next.add(flagId);
3674
+ }
3675
+ return next;
3676
+ });
3677
+ }
3316
3678
  // Protected methods
3317
3679
  getFlagValue(flag) {
3318
3680
  if (!flag.isForced)
@@ -3326,7 +3688,7 @@ class ToolbarFeatureFlagsToolComponent {
3326
3688
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarFeatureFlagsToolComponent, isStandalone: true, selector: "ndt-feature-flags-tool", ngImport: i0, template: `
3327
3689
  <ndt-toolbar-tool
3328
3690
  [options]="options"
3329
- title="Feature Flags"
3691
+ toolTitle="Feature Flags"
3330
3692
  icon="toggle-left"
3331
3693
  [badge]="badgeCount()"
3332
3694
  >
@@ -3338,7 +3700,6 @@ class ToolbarFeatureFlagsToolComponent {
3338
3700
  placeholder="Search..."
3339
3701
  />
3340
3702
  <div class="filter-wrapper">
3341
- <ndt-icon name="filter" class="filter-icon" />
3342
3703
  <ndt-select
3343
3704
  [value]="activeFilter()"
3344
3705
  [options]="filterOptions"
@@ -3361,6 +3722,11 @@ class ToolbarFeatureFlagsToolComponent {
3361
3722
  [isForced]="flag.isForced"
3362
3723
  [currentValue]="flag.isEnabled"
3363
3724
  [originalValue]="flag.originalValue"
3725
+ [isPinned]="pinnedIds().has(flag.id)"
3726
+ (pinToggle)="togglePin(flag.id)"
3727
+ [showApply]="hasApplyCallback()"
3728
+ [applyState]="getApplyState(flag.id)"
3729
+ (applyToSource)="onApplyToSource(flag.id, flag.isEnabled)"
3364
3730
  >
3365
3731
  <ndt-select
3366
3732
  [value]="getFlagValue(flag)"
@@ -3375,7 +3741,7 @@ class ToolbarFeatureFlagsToolComponent {
3375
3741
  </ndt-list>
3376
3742
  </div>
3377
3743
  </ndt-toolbar-tool>
3378
- `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3744
+ `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue", "showApply", "applyState", "isPinned"], outputs: ["pinToggle", "applyToSource"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3379
3745
  }
3380
3746
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarFeatureFlagsToolComponent, decorators: [{
3381
3747
  type: Component,
@@ -3384,13 +3750,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3384
3750
  ToolbarToolComponent,
3385
3751
  ToolbarInputComponent,
3386
3752
  ToolbarSelectComponent,
3387
- ToolbarIconComponent,
3388
3753
  ToolbarListComponent,
3389
3754
  ToolbarListItemComponent,
3390
3755
  ], template: `
3391
3756
  <ndt-toolbar-tool
3392
3757
  [options]="options"
3393
- title="Feature Flags"
3758
+ toolTitle="Feature Flags"
3394
3759
  icon="toggle-left"
3395
3760
  [badge]="badgeCount()"
3396
3761
  >
@@ -3402,7 +3767,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3402
3767
  placeholder="Search..."
3403
3768
  />
3404
3769
  <div class="filter-wrapper">
3405
- <ndt-icon name="filter" class="filter-icon" />
3406
3770
  <ndt-select
3407
3771
  [value]="activeFilter()"
3408
3772
  [options]="filterOptions"
@@ -3425,6 +3789,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3425
3789
  [isForced]="flag.isForced"
3426
3790
  [currentValue]="flag.isEnabled"
3427
3791
  [originalValue]="flag.originalValue"
3792
+ [isPinned]="pinnedIds().has(flag.id)"
3793
+ (pinToggle)="togglePin(flag.id)"
3794
+ [showApply]="hasApplyCallback()"
3795
+ [applyState]="getApplyState(flag.id)"
3796
+ (applyToSource)="onApplyToSource(flag.id, flag.isEnabled)"
3428
3797
  >
3429
3798
  <ndt-select
3430
3799
  [value]="getFlagValue(flag)"
@@ -3439,7 +3808,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3439
3808
  </ndt-list>
3440
3809
  </div>
3441
3810
  </ndt-toolbar-tool>
3442
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"] }]
3811
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"] }]
3443
3812
  }], ctorParameters: () => [] });
3444
3813
 
3445
3814
  class ToolbarButtonComponent {
@@ -3468,7 +3837,7 @@ class ToolbarButtonComponent {
3468
3837
  }
3469
3838
  <ng-content />
3470
3839
  </button>
3471
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3840
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.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: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3472
3841
  }
3473
3842
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarButtonComponent, decorators: [{
3474
3843
  type: Component,
@@ -3488,7 +3857,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3488
3857
  }
3489
3858
  <ng-content />
3490
3859
  </button>
3491
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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"] }]
3860
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.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"] }]
3492
3861
  }] });
3493
3862
 
3494
3863
  class ToolbarCardComponent {
@@ -3514,7 +3883,7 @@ class ToolbarCardComponent {
3514
3883
  >
3515
3884
  <ng-content></ng-content>
3516
3885
  </div>
3517
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.card{background:var(--ndt-bg-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-spacing-md);cursor:pointer;transition:var(--ndt-transition-default);border:1px solid var(--ndt-border-subtle);position:relative;flex:1;height:120px;display:flex}.card:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 0 0 1px rgba(var(--ndt-primary-rgb),.3)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3886
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.card{background:var(--ndt-bg-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-spacing-md);cursor:pointer;transition:var(--ndt-transition-default);border:1px solid var(--ndt-border-subtle);position:relative;flex:1;height:120px;display:flex}.card:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 0 0 1px rgba(var(--ndt-primary-rgb),.3)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3518
3887
  }
3519
3888
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarCardComponent, decorators: [{
3520
3889
  type: Component,
@@ -3532,7 +3901,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3532
3901
  >
3533
3902
  <ng-content></ng-content>
3534
3903
  </div>
3535
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.card{background:var(--ndt-bg-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-spacing-md);cursor:pointer;transition:var(--ndt-transition-default);border:1px solid var(--ndt-border-subtle);position:relative;flex:1;height:120px;display:flex}.card:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 0 0 1px rgba(var(--ndt-primary-rgb),.3)}\n"] }]
3904
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.card{background:var(--ndt-bg-primary);border-radius:var(--ndt-border-radius-large);padding:var(--ndt-spacing-md);cursor:pointer;transition:var(--ndt-transition-default);border:1px solid var(--ndt-border-subtle);position:relative;flex:1;height:120px;display:flex}.card:hover{background:var(--ndt-hover-bg);border-color:var(--ndt-primary);box-shadow:0 0 0 1px rgba(var(--ndt-primary-rgb),.3)}\n"] }]
3536
3905
  }] });
3537
3906
 
3538
3907
  class ToolbarClickableCardComponent {
@@ -3558,7 +3927,7 @@ class ToolbarClickableCardComponent {
3558
3927
  </div>
3559
3928
  </div>
3560
3929
  </ndt-card>
3561
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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: ToolbarCardComponent, selector: "ndt-card" }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3930
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.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: ToolbarCardComponent, selector: "ndt-card" }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3562
3931
  }
3563
3932
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarClickableCardComponent, decorators: [{
3564
3933
  type: Component,
@@ -3574,7 +3943,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3574
3943
  </div>
3575
3944
  </div>
3576
3945
  </ndt-card>
3577
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.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"] }]
3946
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.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"] }]
3578
3947
  }] });
3579
3948
 
3580
3949
  class ToolbarLinkButtonComponent {
@@ -3597,7 +3966,7 @@ class ToolbarLinkButtonComponent {
3597
3966
  <ng-content></ng-content>
3598
3967
  </span>
3599
3968
  </a>
3600
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.link-button{display:flex;flex-direction:column;align-items:center;gap:var(--ndt-spacing-xs);text-decoration:none;color:var(--ndt-text-muted);transition:var(--ndt-transition-default)}.link-button:hover{color:var(--ndt-text-primary)}.link-button:hover .link-button__icon{outline:2px solid var(--ndt-primary);outline-offset:2px;box-shadow:0 0 8px var(--ndt-primary)}.link-button__icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);transition:all .2s ease-in-out}.link-button__text{font-size:var(--ndt-font-size-xs);text-align:center;white-space:nowrap}\n"], dependencies: [{ kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3969
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.link-button{display:flex;flex-direction:column;align-items:center;gap:var(--ndt-spacing-xs);text-decoration:none;color:var(--ndt-text-muted);transition:var(--ndt-transition-default)}.link-button:hover{color:var(--ndt-text-primary)}.link-button:hover .link-button__icon{outline:2px solid var(--ndt-primary);outline-offset:2px;box-shadow:0 0 8px var(--ndt-primary)}.link-button__icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);transition:all .2s ease-in-out}.link-button__text{font-size:var(--ndt-font-size-xs);text-align:center;white-space:nowrap}\n"], dependencies: [{ kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3601
3970
  }
3602
3971
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLinkButtonComponent, decorators: [{
3603
3972
  type: Component,
@@ -3615,9 +3984,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3615
3984
  <ng-content></ng-content>
3616
3985
  </span>
3617
3986
  </a>
3618
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.link-button{display:flex;flex-direction:column;align-items:center;gap:var(--ndt-spacing-xs);text-decoration:none;color:var(--ndt-text-muted);transition:var(--ndt-transition-default)}.link-button:hover{color:var(--ndt-text-primary)}.link-button:hover .link-button__icon{outline:2px solid var(--ndt-primary);outline-offset:2px;box-shadow:0 0 8px var(--ndt-primary)}.link-button__icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);transition:all .2s ease-in-out}.link-button__text{font-size:var(--ndt-font-size-xs);text-align:center;white-space:nowrap}\n"] }]
3987
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.link-button{display:flex;flex-direction:column;align-items:center;gap:var(--ndt-spacing-xs);text-decoration:none;color:var(--ndt-text-muted);transition:var(--ndt-transition-default)}.link-button:hover{color:var(--ndt-text-primary)}.link-button:hover .link-button__icon{outline:2px solid var(--ndt-primary);outline-offset:2px;box-shadow:0 0 8px var(--ndt-primary)}.link-button__icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--ndt-border-radius-medium);background:var(--ndt-hover-bg);transition:all .2s ease-in-out}.link-button__text{font-size:var(--ndt-font-size-xs);text-align:center;white-space:nowrap}\n"] }]
3619
3988
  }] });
3620
3989
 
3990
+ const TOOLBAR_POSITIONS = [
3991
+ 'top',
3992
+ 'right',
3993
+ 'bottom',
3994
+ 'left',
3995
+ ];
3996
+ function isHorizontalPosition(position) {
3997
+ return position === 'top' || position === 'bottom';
3998
+ }
3999
+
3621
4000
  class SettingsService {
3622
4001
  constructor() {
3623
4002
  this.STORAGE_KEY = 'settings';
@@ -3626,6 +4005,8 @@ class SettingsService {
3626
4005
  getSettings() {
3627
4006
  return (this.storageService.get(this.STORAGE_KEY) || {
3628
4007
  isDarkMode: false,
4008
+ position: 'bottom',
4009
+ isCompletelyHidden: false,
3629
4010
  });
3630
4011
  }
3631
4012
  setSettings(settings) {
@@ -3646,13 +4027,13 @@ class ToolbarHomeToolComponent {
3646
4027
  this.storageService = inject(ToolbarStorageService);
3647
4028
  this.badge = input();
3648
4029
  this.title = `Angular Toolbar`;
4030
+ this.positions = TOOLBAR_POSITIONS;
3649
4031
  this.options = {
3650
4032
  title: this.title,
3651
4033
  isClosable: true,
3652
4034
  id: 'ndt-home',
3653
4035
  size: 'medium',
3654
4036
  description: '',
3655
- isBeta: true,
3656
4037
  };
3657
4038
  this.links = [
3658
4039
  {
@@ -3682,6 +4063,9 @@ class ToolbarHomeToolComponent {
3682
4063
  },
3683
4064
  ];
3684
4065
  }
4066
+ onPositionChange(position) {
4067
+ this.state.setPosition(position);
4068
+ }
3685
4069
  onExportSettings() {
3686
4070
  const settings = this.storageService.getAllSettings();
3687
4071
  const blob = new Blob([JSON.stringify(settings, null, 2)], {
@@ -3726,9 +4110,30 @@ class ToolbarHomeToolComponent {
3726
4110
  }
3727
4111
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarHomeToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3728
4112
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarHomeToolComponent, isStandalone: true, selector: "ndt-home-tool", inputs: { badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
3729
- <ndt-toolbar-tool [options]="options" title="Home" icon="angular">
4113
+ <ndt-toolbar-tool [options]="options" toolTitle="Home" icon="angular">
3730
4114
  <section class="settings">
3731
4115
  <div class="settings-container">
4116
+ <div class="instruction">
4117
+ <div class="instruction__label">
4118
+ <span class="instruction__label-text">Toolbar Position</span>
4119
+ <span class="instruction__label-description">
4120
+ Choose where the toolbar appears on screen
4121
+ </span>
4122
+ </div>
4123
+ </div>
4124
+ <div class="position-selector">
4125
+ @for (pos of positions; track pos) {
4126
+ <button
4127
+ class="position-option"
4128
+ [class.position-option--active]="state.position() === pos"
4129
+ [attr.aria-pressed]="state.position() === pos"
4130
+ (click)="onPositionChange(pos)"
4131
+ >
4132
+ {{ pos }}
4133
+ </button>
4134
+ }
4135
+ </div>
4136
+
3732
4137
  <div class="instruction">
3733
4138
  <div class="instruction__label">
3734
4139
  <span class="instruction__label-text">Reset Settings</span>
@@ -3772,7 +4177,7 @@ class ToolbarHomeToolComponent {
3772
4177
  </div>
3773
4178
  </section>
3774
4179
  </ndt-toolbar-tool>
3775
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.settings{display:flex;flex-direction:column;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;gap:var(--ndt-spacing-md)}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{margin-top:auto;padding-top:var(--ndt-spacing-lg);border-top:1px solid var(--ndt-border-subtle);display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"], dependencies: [{ kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarClickableCardComponent, selector: "ndt-clickable-card", inputs: ["icon", "title", "subtitle"] }, { kind: "component", type: ToolbarLinkButtonComponent, selector: "ndt-link-button", inputs: ["url", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4180
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.settings{display:flex;flex-direction:column;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;gap:var(--ndt-spacing-md)}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.position-selector{display:flex;gap:var(--ndt-spacing-sm)}.position-selector .position-option{flex:1;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:transparent;color:var(--ndt-text-secondary);font-size:var(--ndt-font-size-xs);font-family:inherit;cursor:pointer;transition:all .15s ease;text-transform:capitalize}.position-selector .position-option:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.position-selector .position-option--active{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.position-selector .position-option--active:hover{background:var(--ndt-primary);color:var(--ndt-text-on-primary)}.footer-links{margin-top:auto;padding-top:var(--ndt-spacing-lg);border-top:1px solid var(--ndt-border-subtle);display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"], dependencies: [{ kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarClickableCardComponent, selector: "ndt-clickable-card", inputs: ["icon", "title", "subtitle"] }, { kind: "component", type: ToolbarLinkButtonComponent, selector: "ndt-link-button", inputs: ["url", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3776
4181
  }
3777
4182
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarHomeToolComponent, decorators: [{
3778
4183
  type: Component,
@@ -3783,9 +4188,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3783
4188
  ToolbarClickableCardComponent,
3784
4189
  ToolbarLinkButtonComponent,
3785
4190
  ], template: `
3786
- <ndt-toolbar-tool [options]="options" title="Home" icon="angular">
4191
+ <ndt-toolbar-tool [options]="options" toolTitle="Home" icon="angular">
3787
4192
  <section class="settings">
3788
4193
  <div class="settings-container">
4194
+ <div class="instruction">
4195
+ <div class="instruction__label">
4196
+ <span class="instruction__label-text">Toolbar Position</span>
4197
+ <span class="instruction__label-description">
4198
+ Choose where the toolbar appears on screen
4199
+ </span>
4200
+ </div>
4201
+ </div>
4202
+ <div class="position-selector">
4203
+ @for (pos of positions; track pos) {
4204
+ <button
4205
+ class="position-option"
4206
+ [class.position-option--active]="state.position() === pos"
4207
+ [attr.aria-pressed]="state.position() === pos"
4208
+ (click)="onPositionChange(pos)"
4209
+ >
4210
+ {{ pos }}
4211
+ </button>
4212
+ }
4213
+ </div>
4214
+
3789
4215
  <div class="instruction">
3790
4216
  <div class="instruction__label">
3791
4217
  <span class="instruction__label-text">Reset Settings</span>
@@ -3829,146 +4255,1030 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
3829
4255
  </div>
3830
4256
  </section>
3831
4257
  </ndt-toolbar-tool>
3832
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.settings{display:flex;flex-direction:column;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;gap:var(--ndt-spacing-md)}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.footer-links{margin-top:auto;padding-top:var(--ndt-spacing-lg);border-top:1px solid var(--ndt-border-subtle);display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"] }]
4258
+ `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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)}.settings{display:flex;flex-direction:column;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;gap:var(--ndt-spacing-md)}.settings-container .settings-actions{display:flex;gap:var(--ndt-spacing-md)}.settings-container .settings-actions>*{width:50%;min-width:0}.position-selector{display:flex;gap:var(--ndt-spacing-sm)}.position-selector .position-option{flex:1;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);background:transparent;color:var(--ndt-text-secondary);font-size:var(--ndt-font-size-xs);font-family:inherit;cursor:pointer;transition:all .15s ease;text-transform:capitalize}.position-selector .position-option:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary)}.position-selector .position-option--active{background:var(--ndt-primary);color:var(--ndt-text-on-primary);border-color:var(--ndt-primary)}.position-selector .position-option--active:hover{background:var(--ndt-primary);color:var(--ndt-text-on-primary)}.footer-links{margin-top:auto;padding-top:var(--ndt-spacing-lg);border-top:1px solid var(--ndt-border-subtle);display:flex;flex-direction:row;justify-content:space-between;gap:var(--ndt-spacing-lg)}\n"] }]
3833
4259
  }] });
3834
4260
 
3835
- class ToolbarInternalLanguageService {
4261
+ const DEFAULT_TIMEZONES = [
4262
+ { id: 'UTC', name: 'UTC', offset: '+00:00' },
4263
+ { id: 'America/New_York', name: 'Eastern Time (US)', offset: '-05:00' },
4264
+ { id: 'America/Chicago', name: 'Central Time (US)', offset: '-06:00' },
4265
+ { id: 'America/Denver', name: 'Mountain Time (US)', offset: '-07:00' },
4266
+ { id: 'America/Los_Angeles', name: 'Pacific Time (US)', offset: '-08:00' },
4267
+ { id: 'Europe/London', name: 'London (GMT)', offset: '+00:00' },
4268
+ { id: 'Europe/Paris', name: 'Paris (CET)', offset: '+01:00' },
4269
+ { id: 'Europe/Berlin', name: 'Berlin (CET)', offset: '+01:00' },
4270
+ { id: 'Asia/Tokyo', name: 'Tokyo (JST)', offset: '+09:00' },
4271
+ { id: 'Asia/Shanghai', name: 'Shanghai (CST)', offset: '+08:00' },
4272
+ { id: 'Asia/Kolkata', name: 'India (IST)', offset: '+05:30' },
4273
+ { id: 'Asia/Dubai', name: 'Dubai (GST)', offset: '+04:00' },
4274
+ { id: 'Australia/Sydney', name: 'Sydney (AEST)', offset: '+10:00' },
4275
+ { id: 'Pacific/Auckland', name: 'Auckland (NZST)', offset: '+12:00' },
4276
+ { id: 'America/Sao_Paulo', name: 'Sao Paulo (BRT)', offset: '-03:00' },
4277
+ ];
4278
+ const DEFAULT_CURRENCIES = [
4279
+ { code: 'USD', name: 'US Dollar', symbol: '$' },
4280
+ { code: 'EUR', name: 'Euro', symbol: '\u20AC' },
4281
+ { code: 'GBP', name: 'British Pound', symbol: '\u00A3' },
4282
+ { code: 'JPY', name: 'Japanese Yen', symbol: '\u00A5' },
4283
+ { code: 'CNY', name: 'Chinese Yuan', symbol: '\u00A5' },
4284
+ { code: 'INR', name: 'Indian Rupee', symbol: '\u20B9' },
4285
+ { code: 'BRL', name: 'Brazilian Real', symbol: 'R$' },
4286
+ { code: 'CAD', name: 'Canadian Dollar', symbol: 'CA$' },
4287
+ { code: 'AUD', name: 'Australian Dollar', symbol: 'A$' },
4288
+ { code: 'CHF', name: 'Swiss Franc', symbol: 'CHF' },
4289
+ { code: 'KRW', name: 'South Korean Won', symbol: '\u20A9' },
4290
+ { code: 'MXN', name: 'Mexican Peso', symbol: 'MX$' },
4291
+ { code: 'AED', name: 'UAE Dirham', symbol: 'AED' },
4292
+ { code: 'SAR', name: 'Saudi Riyal', symbol: 'SAR' },
4293
+ ];
4294
+ const CURRENCY_SYMBOLS = Object.fromEntries(DEFAULT_CURRENCIES.map(({ code, symbol }) => [code, symbol]));
4295
+
4296
+ class ToolbarInternalI18nService {
3836
4297
  constructor() {
3837
- this.STORAGE_KEY = 'language';
4298
+ this.STORAGE_LOCALE = 'i18n.locale';
4299
+ this.STORAGE_TIMEZONE = 'i18n.timezone';
4300
+ this.STORAGE_CURRENCY = 'i18n.currency';
4301
+ this.STORAGE_UNIT_SYSTEM = 'i18n.unitSystem';
4302
+ this.STORAGE_DATE_FORMAT = 'i18n.dateFormat';
4303
+ this.STORAGE_FIRST_DAY = 'i18n.firstDay';
4304
+ this.STORAGE_NUMBER_FORMAT = 'i18n.numberFormat';
4305
+ this.STORAGE_PSEUDO_LOC = 'i18n.pseudoLoc';
4306
+ this.STORAGE_RTL = 'i18n.rtl';
4307
+ this.OLD_LANGUAGE_KEY = 'language';
3838
4308
  this.storageService = inject(ToolbarStorageService);
3839
4309
  this.stateService = inject(ToolbarStateService);
3840
- this.languages$ = new BehaviorSubject([]);
3841
- this.forcedLanguage$ = new BehaviorSubject(null);
3842
- this.languages = toSignal(this.languages$, { initialValue: [] });
3843
- this.loadForcedLanguage();
3844
- }
3845
- setAppLanguages(languages) {
3846
- this.languages$.next(languages);
3847
- }
3848
- getAppLanguages() {
3849
- return this.languages$.asObservable();
3850
- }
3851
- setForcedLanguage(language) {
3852
- this.forcedLanguage$.next(language);
3853
- this.storageService.set(this.STORAGE_KEY, language);
3854
- }
3855
- getForcedLanguage() {
3856
- return this.forcedLanguage$.pipe(map((language) => {
3857
- // If toolbar is disabled, return empty array (no forced values)
4310
+ this.document = inject(DOCUMENT);
4311
+ this.locales$ = new BehaviorSubject([]);
4312
+ this.timezones$ = new BehaviorSubject(DEFAULT_TIMEZONES);
4313
+ this.currencies$ = new BehaviorSubject(DEFAULT_CURRENCIES);
4314
+ this.forcedLocale$ = new BehaviorSubject(null);
4315
+ this.forcedTimezone$ = new BehaviorSubject(null);
4316
+ this.forcedCurrency$ = new BehaviorSubject(null);
4317
+ this.forcedUnitSystem$ = new BehaviorSubject(null);
4318
+ this.forcedDateFormat$ = new BehaviorSubject(null);
4319
+ this.forcedFirstDayOfWeek$ = new BehaviorSubject(null);
4320
+ this.forcedNumberFormat$ = new BehaviorSubject(null);
4321
+ this.toolConfig$ = new BehaviorSubject({});
4322
+ this.pseudoLocEnabled$ = new BehaviorSubject(false);
4323
+ this.rtlEnabled$ = new BehaviorSubject(false);
4324
+ this.locales = toSignal(this.locales$, { initialValue: [] });
4325
+ this.timezones = toSignal(this.timezones$, { initialValue: DEFAULT_TIMEZONES });
4326
+ this.availableCurrencies = toSignal(this.currencies$, { initialValue: DEFAULT_CURRENCIES });
4327
+ this.forcedLocale = toSignal(this.forcedLocale$, { initialValue: null });
4328
+ this.forcedTimezone = toSignal(this.forcedTimezone$, { initialValue: null });
4329
+ this.forcedCurrency = toSignal(this.forcedCurrency$, { initialValue: null });
4330
+ this.forcedUnitSystem = toSignal(this.forcedUnitSystem$, { initialValue: null });
4331
+ this.forcedDateFormat = toSignal(this.forcedDateFormat$, { initialValue: null });
4332
+ this.forcedFirstDayOfWeek = toSignal(this.forcedFirstDayOfWeek$, { initialValue: null });
4333
+ this.forcedNumberFormat = toSignal(this.forcedNumberFormat$, { initialValue: null });
4334
+ this.toolConfig = toSignal(this.toolConfig$, { initialValue: {} });
4335
+ this.pseudoLocEnabled = toSignal(this.pseudoLocEnabled$, { initialValue: false });
4336
+ this.rtlEnabled = toSignal(this.rtlEnabled$, { initialValue: false });
4337
+ this.migrateOldLanguageKey();
4338
+ this.loadFromStorage();
4339
+ }
4340
+ // --- Locale ---
4341
+ setAvailableLocales(locales) {
4342
+ this.locales$.next(locales);
4343
+ }
4344
+ getAvailableLocales() {
4345
+ return this.locales$.asObservable();
4346
+ }
4347
+ setForcedLocale(locale) {
4348
+ this.forcedLocale$.next(locale);
4349
+ this.storageService.set(this.STORAGE_LOCALE, locale);
4350
+ }
4351
+ getForcedLocale() {
4352
+ return this.forcedLocale$.pipe(map((locale) => {
3858
4353
  if (!this.stateService.isEnabled()) {
3859
4354
  return [];
3860
4355
  }
3861
- return language ? [language] : [];
4356
+ return locale ? [locale] : [];
3862
4357
  }));
3863
4358
  }
3864
- removeForcedLanguage() {
3865
- this.forcedLanguage$.next(null);
3866
- this.storageService.remove(this.STORAGE_KEY);
4359
+ removeForcedLocale() {
4360
+ this.forcedLocale$.next(null);
4361
+ this.storageService.remove(this.STORAGE_LOCALE);
3867
4362
  }
3868
- loadForcedLanguage() {
3869
- const savedLanguage = this.storageService.get(this.STORAGE_KEY);
3870
- if (savedLanguage) {
3871
- this.forcedLanguage$.next(savedLanguage);
3872
- }
4363
+ // --- Timezone ---
4364
+ setAvailableTimezones(timezones) {
4365
+ this.timezones$.next(timezones);
3873
4366
  }
3874
- /**
3875
- * Apply language from a preset (used by Presets Tool)
3876
- * Accepts a language ID and finds the corresponding Language object from available languages
3877
- */
3878
- async applyPresetLanguage(languageId) {
3879
- if (languageId === null) {
3880
- this.removeForcedLanguage();
4367
+ getAvailableTimezones() {
4368
+ return this.timezones$.asObservable();
4369
+ }
4370
+ setForcedTimezone(timezone) {
4371
+ this.forcedTimezone$.next(timezone);
4372
+ this.storageService.set(this.STORAGE_TIMEZONE, timezone);
4373
+ }
4374
+ getForcedTimezone() {
4375
+ return this.forcedTimezone$.pipe(map((tz) => (this.stateService.isEnabled() ? tz : null)));
4376
+ }
4377
+ removeForcedTimezone() {
4378
+ this.forcedTimezone$.next(null);
4379
+ this.storageService.remove(this.STORAGE_TIMEZONE);
4380
+ }
4381
+ // --- Currency ---
4382
+ setAvailableCurrencies(currencies) {
4383
+ this.currencies$.next(currencies);
4384
+ }
4385
+ getAvailableCurrencies() {
4386
+ return this.currencies$.asObservable();
4387
+ }
4388
+ setForcedCurrency(currency) {
4389
+ this.forcedCurrency$.next(currency);
4390
+ this.storageService.set(this.STORAGE_CURRENCY, currency);
4391
+ }
4392
+ getForcedCurrency() {
4393
+ return this.forcedCurrency$.pipe(map((c) => (this.stateService.isEnabled() ? c : null)));
4394
+ }
4395
+ removeForcedCurrency() {
4396
+ this.forcedCurrency$.next(null);
4397
+ this.storageService.remove(this.STORAGE_CURRENCY);
4398
+ }
4399
+ // --- Unit System ---
4400
+ setForcedUnitSystem(unitSystem) {
4401
+ this.forcedUnitSystem$.next(unitSystem);
4402
+ this.storageService.set(this.STORAGE_UNIT_SYSTEM, unitSystem);
4403
+ }
4404
+ getForcedUnitSystem() {
4405
+ return this.forcedUnitSystem$.pipe(map((u) => (this.stateService.isEnabled() ? u : null)));
4406
+ }
4407
+ removeForcedUnitSystem() {
4408
+ this.forcedUnitSystem$.next(null);
4409
+ this.storageService.remove(this.STORAGE_UNIT_SYSTEM);
4410
+ }
4411
+ // --- Date Format ---
4412
+ setForcedDateFormat(dateFormat) {
4413
+ this.forcedDateFormat$.next(dateFormat);
4414
+ this.storageService.set(this.STORAGE_DATE_FORMAT, dateFormat);
4415
+ }
4416
+ getForcedDateFormat() {
4417
+ return this.forcedDateFormat$.pipe(map((df) => (this.stateService.isEnabled() ? df : null)));
4418
+ }
4419
+ removeForcedDateFormat() {
4420
+ this.forcedDateFormat$.next(null);
4421
+ this.storageService.remove(this.STORAGE_DATE_FORMAT);
4422
+ }
4423
+ // --- First Day of Week ---
4424
+ setForcedFirstDayOfWeek(firstDay) {
4425
+ this.forcedFirstDayOfWeek$.next(firstDay);
4426
+ this.storageService.set(this.STORAGE_FIRST_DAY, firstDay);
4427
+ }
4428
+ getForcedFirstDayOfWeek() {
4429
+ return this.forcedFirstDayOfWeek$.pipe(map((fd) => (this.stateService.isEnabled() ? fd : null)));
4430
+ }
4431
+ removeForcedFirstDayOfWeek() {
4432
+ this.forcedFirstDayOfWeek$.next(null);
4433
+ this.storageService.remove(this.STORAGE_FIRST_DAY);
4434
+ }
4435
+ // --- Number Format ---
4436
+ setForcedNumberFormat(numberFormat) {
4437
+ this.forcedNumberFormat$.next(numberFormat);
4438
+ this.storageService.set(this.STORAGE_NUMBER_FORMAT, numberFormat);
4439
+ }
4440
+ getForcedNumberFormat() {
4441
+ return this.forcedNumberFormat$.pipe(map((nf) => (this.stateService.isEnabled() ? nf : null)));
4442
+ }
4443
+ removeForcedNumberFormat() {
4444
+ this.forcedNumberFormat$.next(null);
4445
+ this.storageService.remove(this.STORAGE_NUMBER_FORMAT);
4446
+ }
4447
+ // --- Tool Config ---
4448
+ setToolConfig(config) {
4449
+ this.toolConfig$.next(config);
4450
+ }
4451
+ // --- Pseudo-Localization ---
4452
+ setPseudoLocEnabled(enabled) {
4453
+ this.pseudoLocEnabled$.next(enabled);
4454
+ this.storageService.set(this.STORAGE_PSEUDO_LOC, enabled);
4455
+ }
4456
+ getPseudoLocEnabled() {
4457
+ return this.pseudoLocEnabled$.pipe(map((enabled) => (this.stateService.isEnabled() ? enabled : false)));
4458
+ }
4459
+ // --- RTL ---
4460
+ setRtlEnabled(enabled) {
4461
+ this.rtlEnabled$.next(enabled);
4462
+ this.storageService.set(this.STORAGE_RTL, enabled);
4463
+ this.applyRtl(enabled);
4464
+ }
4465
+ getRtlEnabled() {
4466
+ return this.rtlEnabled$.pipe(map((enabled) => (this.stateService.isEnabled() ? enabled : false)));
4467
+ }
4468
+ // --- Preset Hooks ---
4469
+ async applyPresetLocale(localeId) {
4470
+ if (localeId === null) {
4471
+ this.removeForcedLocale();
3881
4472
  return;
3882
4473
  }
3883
- // Get available languages and find matching one
3884
- const languages = await firstValueFrom(this.languages$);
3885
- const language = languages.find((lang) => lang.id === languageId);
3886
- if (language) {
3887
- this.setForcedLanguage(language);
4474
+ const locales = await firstValueFrom(this.locales$);
4475
+ const locale = locales.find((l) => l.id === localeId);
4476
+ if (locale) {
4477
+ this.setForcedLocale(locale);
3888
4478
  }
3889
4479
  else {
3890
- console.warn(`Language ${languageId} not found in available languages. Skipping.`);
4480
+ console.warn(`Locale ${localeId} not found in available locales. Skipping.`);
3891
4481
  }
3892
4482
  }
3893
- /**
3894
- * Get current forced language ID for saving to preset
3895
- * Returns the language ID or null if no language is forced
3896
- */
3897
- getCurrentForcedLanguage() {
3898
- return this.forcedLanguage$.value?.id ?? null;
4483
+ applyPresetI18n(config) {
4484
+ if (!config)
4485
+ return;
4486
+ if (config.locale !== undefined) {
4487
+ if (config.locale === null) {
4488
+ this.removeForcedLocale();
4489
+ }
4490
+ else {
4491
+ const locale = this.locales$.value.find((l) => l.id === config.locale);
4492
+ if (locale) {
4493
+ this.setForcedLocale(locale);
4494
+ }
4495
+ }
4496
+ }
4497
+ if (config.timezone !== undefined) {
4498
+ if (config.timezone === null) {
4499
+ this.removeForcedTimezone();
4500
+ }
4501
+ else {
4502
+ const timezone = this.timezones$.value.find((t) => t.id === config.timezone);
4503
+ if (timezone) {
4504
+ this.setForcedTimezone(timezone);
4505
+ }
4506
+ }
4507
+ }
4508
+ if (config.currency !== undefined) {
4509
+ if (config.currency === null) {
4510
+ this.removeForcedCurrency();
4511
+ }
4512
+ else {
4513
+ const currency = this.currencies$.value.find((c) => c.code === config.currency);
4514
+ if (currency) {
4515
+ this.setForcedCurrency(currency);
4516
+ }
4517
+ }
4518
+ }
4519
+ if (config.unitSystem !== undefined) {
4520
+ if (config.unitSystem === null) {
4521
+ this.removeForcedUnitSystem();
4522
+ }
4523
+ else {
4524
+ this.setForcedUnitSystem(config.unitSystem);
4525
+ }
4526
+ }
4527
+ if (config.dateFormat !== undefined) {
4528
+ if (config.dateFormat === null) {
4529
+ this.removeForcedDateFormat();
4530
+ }
4531
+ else {
4532
+ this.setForcedDateFormat(config.dateFormat);
4533
+ }
4534
+ }
4535
+ if (config.firstDayOfWeek !== undefined) {
4536
+ if (config.firstDayOfWeek === null) {
4537
+ this.removeForcedFirstDayOfWeek();
4538
+ }
4539
+ else {
4540
+ this.setForcedFirstDayOfWeek(config.firstDayOfWeek);
4541
+ }
4542
+ }
4543
+ if (config.numberFormat !== undefined) {
4544
+ if (config.numberFormat === null) {
4545
+ this.removeForcedNumberFormat();
4546
+ }
4547
+ else {
4548
+ this.setForcedNumberFormat(config.numberFormat);
4549
+ }
4550
+ }
4551
+ if (config.pseudoLocEnabled !== undefined) {
4552
+ this.setPseudoLocEnabled(config.pseudoLocEnabled);
4553
+ }
4554
+ if (config.rtlEnabled !== undefined) {
4555
+ this.setRtlEnabled(config.rtlEnabled);
4556
+ }
4557
+ }
4558
+ getCurrentI18nState() {
4559
+ return {
4560
+ locale: this.forcedLocale$.value,
4561
+ timezone: this.forcedTimezone$.value,
4562
+ currency: this.forcedCurrency$.value,
4563
+ unitSystem: this.forcedUnitSystem$.value,
4564
+ dateFormat: this.forcedDateFormat$.value,
4565
+ firstDayOfWeek: this.forcedFirstDayOfWeek$.value,
4566
+ numberFormat: this.forcedNumberFormat$.value,
4567
+ pseudoLocEnabled: this.pseudoLocEnabled$.value,
4568
+ rtlEnabled: this.rtlEnabled$.value,
4569
+ };
4570
+ }
4571
+ getCurrentForcedLocaleId() {
4572
+ return this.forcedLocale$.value?.id ?? null;
4573
+ }
4574
+ // --- Private ---
4575
+ loadFromStorage() {
4576
+ const savedLocale = this.storageService.get(this.STORAGE_LOCALE);
4577
+ if (savedLocale) {
4578
+ this.forcedLocale$.next(savedLocale);
4579
+ }
4580
+ const savedTimezone = this.storageService.get(this.STORAGE_TIMEZONE);
4581
+ if (savedTimezone) {
4582
+ this.forcedTimezone$.next(savedTimezone);
4583
+ }
4584
+ const savedCurrency = this.storageService.get(this.STORAGE_CURRENCY);
4585
+ if (savedCurrency) {
4586
+ this.forcedCurrency$.next(savedCurrency);
4587
+ }
4588
+ const savedUnitSystem = this.storageService.get(this.STORAGE_UNIT_SYSTEM);
4589
+ if (savedUnitSystem) {
4590
+ this.forcedUnitSystem$.next(savedUnitSystem);
4591
+ }
4592
+ const savedDateFormat = this.storageService.get(this.STORAGE_DATE_FORMAT);
4593
+ if (savedDateFormat) {
4594
+ this.forcedDateFormat$.next(savedDateFormat);
4595
+ }
4596
+ const savedFirstDay = this.storageService.get(this.STORAGE_FIRST_DAY);
4597
+ if (savedFirstDay) {
4598
+ this.forcedFirstDayOfWeek$.next(savedFirstDay);
4599
+ }
4600
+ const savedNumberFormat = this.storageService.get(this.STORAGE_NUMBER_FORMAT);
4601
+ if (savedNumberFormat) {
4602
+ this.forcedNumberFormat$.next(savedNumberFormat);
4603
+ }
4604
+ const savedPseudoLoc = this.storageService.get(this.STORAGE_PSEUDO_LOC);
4605
+ if (savedPseudoLoc !== null) {
4606
+ this.pseudoLocEnabled$.next(savedPseudoLoc);
4607
+ }
4608
+ const savedRtl = this.storageService.get(this.STORAGE_RTL);
4609
+ if (savedRtl !== null) {
4610
+ this.rtlEnabled$.next(savedRtl);
4611
+ if (savedRtl) {
4612
+ this.applyRtl(true);
4613
+ }
4614
+ }
4615
+ }
4616
+ migrateOldLanguageKey() {
4617
+ const oldLanguage = this.storageService.get(this.OLD_LANGUAGE_KEY);
4618
+ if (oldLanguage && !this.storageService.get(this.STORAGE_LOCALE)) {
4619
+ const migrated = {
4620
+ id: oldLanguage.id,
4621
+ name: oldLanguage.name,
4622
+ code: oldLanguage.id,
4623
+ };
4624
+ this.storageService.set(this.STORAGE_LOCALE, migrated);
4625
+ this.storageService.remove(this.OLD_LANGUAGE_KEY);
4626
+ }
4627
+ }
4628
+ applyRtl(enabled) {
4629
+ if (this.document?.documentElement) {
4630
+ this.document.documentElement.dir = enabled ? 'rtl' : 'ltr';
4631
+ }
3899
4632
  }
3900
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalLanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3901
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalLanguageService, providedIn: 'root' }); }
4633
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalI18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4634
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalI18nService, providedIn: 'root' }); }
3902
4635
  }
3903
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalLanguageService, decorators: [{
4636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarInternalI18nService, decorators: [{
3904
4637
  type: Injectable,
3905
4638
  args: [{ providedIn: 'root' }]
3906
4639
  }], ctorParameters: () => [] });
3907
4640
 
3908
- class ToolbarLanguageToolComponent {
4641
+ const PSEUDO_CHAR_MAP = {
4642
+ a: '\u00e4', b: '\u0183', c: '\u00e7', d: '\u0111', e: '\u00e9',
4643
+ f: '\u0192', g: '\u011f', h: '\u0127', i: '\u00ef', j: '\u0135',
4644
+ k: '\u0137', l: '\u013c', m: '\u1e41', n: '\u00f1', o: '\u00f6',
4645
+ p: '\u00fe', q: '\u01eb', r: '\u0159', s: '\u0161', t: '\u0163',
4646
+ u: '\u00fc', v: '\u1e7d', w: '\u0175', x: '\u1e8b', y: '\u00fd',
4647
+ z: '\u017e',
4648
+ A: '\u00c4', B: '\u0182', C: '\u00c7', D: '\u0110', E: '\u00c9',
4649
+ F: '\u0191', G: '\u011e', H: '\u0126', I: '\u00cf', J: '\u0134',
4650
+ K: '\u0136', L: '\u013b', M: '\u1e40', N: '\u00d1', O: '\u00d6',
4651
+ P: '\u00de', Q: '\u01ea', R: '\u0158', S: '\u0160', T: '\u0162',
4652
+ U: '\u00dc', V: '\u1e7c', W: '\u0174', X: '\u1e8a', Y: '\u00dd',
4653
+ Z: '\u017d',
4654
+ };
4655
+ const VOWELS = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
4656
+ function formatNumber(locale, value) {
4657
+ try {
4658
+ return new Intl.NumberFormat(locale).format(value);
4659
+ }
4660
+ catch {
4661
+ return String(value);
4662
+ }
4663
+ }
4664
+ function formatDate(locale, timezone, date) {
4665
+ try {
4666
+ return new Intl.DateTimeFormat(locale, {
4667
+ year: 'numeric',
4668
+ month: '2-digit',
4669
+ day: '2-digit',
4670
+ timeZone: timezone,
4671
+ }).format(date);
4672
+ }
4673
+ catch {
4674
+ return date.toLocaleDateString();
4675
+ }
4676
+ }
4677
+ function formatTime(locale, timezone, date) {
4678
+ try {
4679
+ return new Intl.DateTimeFormat(locale, {
4680
+ hour: '2-digit',
4681
+ minute: '2-digit',
4682
+ second: '2-digit',
4683
+ timeZoneName: 'short',
4684
+ timeZone: timezone,
4685
+ }).format(date);
4686
+ }
4687
+ catch {
4688
+ return date.toLocaleTimeString();
4689
+ }
4690
+ }
4691
+ function formatCurrency(locale, currency, value) {
4692
+ try {
4693
+ return new Intl.NumberFormat(locale, {
4694
+ style: 'currency',
4695
+ currency,
4696
+ }).format(value);
4697
+ }
4698
+ catch {
4699
+ return `${currency} ${value}`;
4700
+ }
4701
+ }
4702
+ function pseudoLocalize(text) {
4703
+ let result = '';
4704
+ for (const char of text) {
4705
+ result += PSEUDO_CHAR_MAP[char] ?? char;
4706
+ }
4707
+ return `[\u200B${result}\u200B]`;
4708
+ }
4709
+ function formatCustomDate(date, format, locale, timezone) {
4710
+ const d = date.getDate().toString().padStart(2, '0');
4711
+ const m = (date.getMonth() + 1).toString().padStart(2, '0');
4712
+ const y = date.getFullYear().toString();
4713
+ switch (format) {
4714
+ case 'MM/DD/YYYY': return `${m}/${d}/${y}`;
4715
+ case 'DD/MM/YYYY': return `${d}/${m}/${y}`;
4716
+ case 'YYYY-MM-DD': return `${y}-${m}-${d}`;
4717
+ default: return formatDate(locale, timezone, date);
4718
+ }
4719
+ }
4720
+ function formatCustomNumber(value, format, locale) {
4721
+ const [intPart, decPart] = value.toFixed(2).split('.');
4722
+ const digits = intPart.replace('-', '');
4723
+ const groups = [];
4724
+ for (let i = digits.length; i > 0; i -= 3) {
4725
+ groups.unshift(digits.slice(Math.max(0, i - 3), i));
4726
+ }
4727
+ const sign = value < 0 ? '-' : '';
4728
+ switch (format) {
4729
+ case 'period-comma': return `${sign}${groups.join(',')}.${decPart}`;
4730
+ case 'comma-period': return `${sign}${groups.join('.')},${decPart}`;
4731
+ case 'space-comma': return `${sign}${groups.join('\u00A0')},${decPart}`;
4732
+ default: return formatNumber(locale, value);
4733
+ }
4734
+ }
4735
+ function expandText(text, factor = 0.35) {
4736
+ const targetLength = Math.ceil(text.length * (1 + factor));
4737
+ let result = '';
4738
+ for (const char of text) {
4739
+ result += char;
4740
+ if (VOWELS.has(char) && result.length < targetLength) {
4741
+ result += char.toLowerCase();
4742
+ }
4743
+ }
4744
+ // Pad remaining if vowel duplication wasn't enough
4745
+ while (result.length < targetLength) {
4746
+ result += '~';
4747
+ }
4748
+ return result;
4749
+ }
4750
+
4751
+ const NOT_FORCED = 'not-forced';
4752
+ const UNIT_SYSTEM_VALUES = ['metric', 'imperial'];
4753
+ const DATE_FORMAT_VALUES = ['locale-default', 'MM/DD/YYYY', 'DD/MM/YYYY', 'YYYY-MM-DD'];
4754
+ const FIRST_DAY_VALUES = ['locale-default', 'sunday', 'monday', 'saturday'];
4755
+ const NUMBER_FORMAT_VALUES = ['locale-default', 'period-comma', 'comma-period', 'space-comma'];
4756
+ class ToolbarI18nToolComponent {
4757
+ // --- Constructor: restore persisted values ---
3909
4758
  constructor() {
3910
- this.languageService = inject(ToolbarInternalLanguageService);
4759
+ // --- Injects ---
4760
+ this.i18nService = inject(ToolbarInternalI18nService);
4761
+ // --- Readonly properties ---
3911
4762
  this.options = {
3912
- title: 'Languages',
3913
- description: 'Set the language for your current session',
3914
- size: 'small',
3915
- id: 'ndt-language',
3916
- isBeta: true,
4763
+ title: 'i18n',
4764
+ description: 'Simulate regional & linguistic environments',
4765
+ size: 'tall',
4766
+ id: 'ndt-i18n',
3917
4767
  isClosable: true,
3918
4768
  };
3919
- this.activeLanguage = signal('not-forced');
3920
- this.languageOptions = toSignal(this.languageService.getAppLanguages().pipe(map((languages) => [
3921
- { value: 'not-forced', label: 'Not Forced' },
3922
- ...languages.map(({ id: value, name: label }) => ({
4769
+ this.unitSystemOptions = [
4770
+ { value: NOT_FORCED, label: 'Not Forced' },
4771
+ { value: 'metric', label: 'Metric' },
4772
+ { value: 'imperial', label: 'Imperial' },
4773
+ ];
4774
+ this.dateFormatOptions = [
4775
+ { value: NOT_FORCED, label: 'Not Forced' },
4776
+ { value: 'locale-default', label: 'Locale Default' },
4777
+ { value: 'MM/DD/YYYY', label: 'MM/DD/YYYY' },
4778
+ { value: 'DD/MM/YYYY', label: 'DD/MM/YYYY' },
4779
+ { value: 'YYYY-MM-DD', label: 'YYYY-MM-DD (ISO)' },
4780
+ ];
4781
+ this.firstDayOptions = [
4782
+ { value: NOT_FORCED, label: 'Not Forced' },
4783
+ { value: 'locale-default', label: 'Locale Default' },
4784
+ { value: 'sunday', label: 'Sunday' },
4785
+ { value: 'monday', label: 'Monday' },
4786
+ { value: 'saturday', label: 'Saturday' },
4787
+ ];
4788
+ this.numberFormatOptions = [
4789
+ { value: NOT_FORCED, label: 'Not Forced' },
4790
+ { value: 'locale-default', label: 'Locale Default' },
4791
+ { value: 'period-comma', label: '1,234.56' },
4792
+ { value: 'comma-period', label: '1.234,56' },
4793
+ { value: 'space-comma', label: '1 234,56' },
4794
+ ];
4795
+ // --- Signals ---
4796
+ this.activeLocale = signal(NOT_FORCED);
4797
+ this.activeTimezone = signal(NOT_FORCED);
4798
+ this.activeCurrency = signal(NOT_FORCED);
4799
+ this.activeUnitSystem = signal(NOT_FORCED);
4800
+ this.activeDateFormat = signal(NOT_FORCED);
4801
+ this.activeFirstDayOfWeek = signal(NOT_FORCED);
4802
+ this.activeNumberFormat = signal(NOT_FORCED);
4803
+ this.pseudoLocEnabled = this.i18nService.pseudoLocEnabled;
4804
+ this.rtlEnabled = this.i18nService.rtlEnabled;
4805
+ // --- Computed ---
4806
+ this.toolConfig = computed(() => this.i18nService.toolConfig());
4807
+ this.localeOptions = toSignal(this.i18nService.getAvailableLocales().pipe(map((locales) => [
4808
+ { value: NOT_FORCED, label: 'Not Forced' },
4809
+ ...locales.map(({ id: value, name: label }) => ({ value, label })),
4810
+ ])), { initialValue: [{ value: NOT_FORCED, label: 'Not Forced' }] });
4811
+ this.timezoneOptions = toSignal(this.i18nService.getAvailableTimezones().pipe(map((timezones) => [
4812
+ { value: NOT_FORCED, label: 'Not Forced' },
4813
+ ...timezones.map(({ id: value, name, offset }) => ({
4814
+ value,
4815
+ label: `${name} (${offset})`,
4816
+ })),
4817
+ ])), { initialValue: [{ value: NOT_FORCED, label: 'Not Forced' }] });
4818
+ this.currencyOptions = toSignal(this.i18nService.getAvailableCurrencies().pipe(map((currencies) => [
4819
+ { value: NOT_FORCED, label: 'Not Forced' },
4820
+ ...currencies.map(({ code: value, name, symbol }) => ({
3923
4821
  value,
3924
- label,
4822
+ label: `${name} (${symbol})`,
3925
4823
  })),
3926
- ])), { initialValue: [] });
4824
+ ])), { initialValue: [{ value: NOT_FORCED, label: 'Not Forced' }] });
4825
+ this.currentLocaleCode = computed(() => {
4826
+ const id = this.activeLocale();
4827
+ return id === NOT_FORCED ? 'en-US' : id;
4828
+ });
4829
+ this.currentTimezone = computed(() => {
4830
+ const id = this.activeTimezone();
4831
+ return id === NOT_FORCED ? 'UTC' : id;
4832
+ });
4833
+ this.currentCurrencyCode = computed(() => {
4834
+ const id = this.activeCurrency();
4835
+ return id === NOT_FORCED ? 'USD' : id;
4836
+ });
4837
+ this.previewDate_ = new Date();
4838
+ this.previewNumber = computed(() => {
4839
+ const nf = this.activeNumberFormat();
4840
+ if (nf !== NOT_FORCED && nf !== 'locale-default') {
4841
+ return formatCustomNumber(1234.56, nf, this.currentLocaleCode());
4842
+ }
4843
+ return formatNumber(this.currentLocaleCode(), 1234.56);
4844
+ });
4845
+ this.previewDate = computed(() => {
4846
+ const df = this.activeDateFormat();
4847
+ if (df !== NOT_FORCED && df !== 'locale-default') {
4848
+ return formatCustomDate(this.previewDate_, df, this.currentLocaleCode(), this.currentTimezone());
4849
+ }
4850
+ return formatDate(this.currentLocaleCode(), this.currentTimezone(), this.previewDate_);
4851
+ });
4852
+ this.previewTime = computed(() => formatTime(this.currentLocaleCode(), this.currentTimezone(), this.previewDate_));
4853
+ this.previewCurrencyValue = computed(() => {
4854
+ const nf = this.activeNumberFormat();
4855
+ if (nf !== NOT_FORCED && nf !== 'locale-default') {
4856
+ const code = this.currentCurrencyCode();
4857
+ const symbol = CURRENCY_SYMBOLS[code] ?? code;
4858
+ return `${symbol}${formatCustomNumber(1234.56, nf, this.currentLocaleCode())}`;
4859
+ }
4860
+ return formatCurrency(this.currentLocaleCode(), this.currentCurrencyCode(), 1234.56);
4861
+ });
4862
+ this.pseudoPreview = computed(() => {
4863
+ const sample = 'Hello World! This is a sample text for testing.';
4864
+ const pseudo = pseudoLocalize(sample);
4865
+ return expandText(pseudo);
4866
+ });
4867
+ const state = this.i18nService.getCurrentI18nState();
4868
+ if (state.locale)
4869
+ this.activeLocale.set(state.locale.id);
4870
+ if (state.timezone)
4871
+ this.activeTimezone.set(state.timezone.id);
4872
+ if (state.currency)
4873
+ this.activeCurrency.set(state.currency.code);
4874
+ if (state.unitSystem)
4875
+ this.activeUnitSystem.set(state.unitSystem);
4876
+ if (state.dateFormat)
4877
+ this.activeDateFormat.set(state.dateFormat);
4878
+ if (state.firstDayOfWeek)
4879
+ this.activeFirstDayOfWeek.set(state.firstDayOfWeek);
4880
+ if (state.numberFormat)
4881
+ this.activeNumberFormat.set(state.numberFormat);
4882
+ }
4883
+ // --- Event handlers ---
4884
+ onLocaleChange(localeId) {
4885
+ this.activeLocale.set(localeId);
4886
+ if (localeId === NOT_FORCED || !localeId) {
4887
+ this.i18nService.removeForcedLocale();
4888
+ return;
4889
+ }
4890
+ const selected = this.i18nService.locales().find(({ id }) => id === localeId);
4891
+ if (selected) {
4892
+ this.i18nService.setForcedLocale(selected);
4893
+ }
4894
+ }
4895
+ onTimezoneChange(timezoneId) {
4896
+ this.activeTimezone.set(timezoneId);
4897
+ if (timezoneId === NOT_FORCED || !timezoneId) {
4898
+ this.i18nService.removeForcedTimezone();
4899
+ return;
4900
+ }
4901
+ const selected = this.i18nService.timezones().find(({ id }) => id === timezoneId);
4902
+ if (selected) {
4903
+ this.i18nService.setForcedTimezone(selected);
4904
+ }
4905
+ }
4906
+ onCurrencyChange(currencyCode) {
4907
+ this.activeCurrency.set(currencyCode);
4908
+ if (currencyCode === NOT_FORCED || !currencyCode) {
4909
+ this.i18nService.removeForcedCurrency();
4910
+ return;
4911
+ }
4912
+ const selected = this.i18nService.availableCurrencies().find(({ code }) => code === currencyCode);
4913
+ if (selected) {
4914
+ this.i18nService.setForcedCurrency(selected);
4915
+ }
3927
4916
  }
3928
- async onLanguageChange(language) {
3929
- if (language === 'not-forced' || !language) {
3930
- this.languageService.removeForcedLanguage();
4917
+ onUnitSystemChange(unitSystem) {
4918
+ this.activeUnitSystem.set(unitSystem);
4919
+ if (unitSystem === NOT_FORCED || !unitSystem) {
4920
+ this.i18nService.removeForcedUnitSystem();
3931
4921
  return;
3932
4922
  }
3933
- const languages = await firstValueFrom(this.languageService.getAppLanguages());
3934
- const selectedLanguage = languages.find(({ id }) => id === language);
3935
- if (selectedLanguage) {
3936
- this.languageService.setForcedLanguage(selectedLanguage);
3937
- }
3938
- }
3939
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLanguageToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3940
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.7", type: ToolbarLanguageToolComponent, isStandalone: true, selector: "ndt-language-tool", ngImport: i0, template: `
3941
- <ndt-toolbar-tool title="Languages" icon="translate" [options]="options">
3942
- <div class="language-select">
3943
- <label for="language-select">Language</label>
3944
- <ndt-select
3945
- id="language-select"
3946
- [value]="activeLanguage()"
3947
- [options]="languageOptions()"
3948
- [size]="'medium'"
3949
- (valueChange)="onLanguageChange($event ?? '')"
3950
- />
4923
+ if (UNIT_SYSTEM_VALUES.includes(unitSystem)) {
4924
+ this.i18nService.setForcedUnitSystem(unitSystem);
4925
+ }
4926
+ }
4927
+ onPseudoLocToggle(event) {
4928
+ const checked = event.target.checked;
4929
+ this.i18nService.setPseudoLocEnabled(checked);
4930
+ }
4931
+ onRtlToggle(event) {
4932
+ const checked = event.target.checked;
4933
+ this.i18nService.setRtlEnabled(checked);
4934
+ }
4935
+ onDateFormatChange(value) {
4936
+ this.activeDateFormat.set(value);
4937
+ if (value === NOT_FORCED || !value) {
4938
+ this.i18nService.removeForcedDateFormat();
4939
+ return;
4940
+ }
4941
+ if (DATE_FORMAT_VALUES.includes(value)) {
4942
+ this.i18nService.setForcedDateFormat(value);
4943
+ }
4944
+ }
4945
+ onFirstDayOfWeekChange(value) {
4946
+ this.activeFirstDayOfWeek.set(value);
4947
+ if (value === NOT_FORCED || !value) {
4948
+ this.i18nService.removeForcedFirstDayOfWeek();
4949
+ return;
4950
+ }
4951
+ if (FIRST_DAY_VALUES.includes(value)) {
4952
+ this.i18nService.setForcedFirstDayOfWeek(value);
4953
+ }
4954
+ }
4955
+ onNumberFormatChange(value) {
4956
+ this.activeNumberFormat.set(value);
4957
+ if (value === NOT_FORCED || !value) {
4958
+ this.i18nService.removeForcedNumberFormat();
4959
+ return;
4960
+ }
4961
+ if (NUMBER_FORMAT_VALUES.includes(value)) {
4962
+ this.i18nService.setForcedNumberFormat(value);
4963
+ }
4964
+ }
4965
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarI18nToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4966
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarI18nToolComponent, isStandalone: true, selector: "ndt-i18n-tool", ngImport: i0, template: `
4967
+ <ndt-toolbar-tool toolTitle="i18n" icon="globe" [options]="options">
4968
+ <div class="i18n-section">
4969
+ <!-- Formatting Preview (at top for immediate feedback) -->
4970
+ @if (toolConfig().showFormattingPreview !== false) {
4971
+ <div class="i18n-section-header">FORMATTING PREVIEW</div>
4972
+ <div class="i18n-preview">
4973
+ <div class="i18n-preview-row">
4974
+ <span class="preview-label">Number</span>
4975
+ <span class="preview-value">{{ previewNumber() }}</span>
4976
+ </div>
4977
+ <div class="i18n-preview-row">
4978
+ <span class="preview-label">Date</span>
4979
+ <span class="preview-value">{{ previewDate() }}</span>
4980
+ </div>
4981
+ <div class="i18n-preview-row">
4982
+ <span class="preview-label">Time</span>
4983
+ <span class="preview-value">{{ previewTime() }}</span>
4984
+ </div>
4985
+ <div class="i18n-preview-row">
4986
+ <span class="preview-label">Currency</span>
4987
+ <span class="preview-value">{{ previewCurrencyValue() }}</span>
4988
+ </div>
4989
+ </div>
4990
+ }
4991
+
4992
+ <!-- Settings (flat 2-column grid) -->
4993
+ <div class="i18n-select-grid">
4994
+ @if (toolConfig().showLocale !== false) {
4995
+ <div class="i18n-select-group">
4996
+ <label for="i18n-locale">Locale</label>
4997
+ <ndt-select
4998
+ id="i18n-locale"
4999
+ [value]="activeLocale()"
5000
+ [options]="localeOptions()"
5001
+ [size]="'medium'"
5002
+ (valueChange)="onLocaleChange($event ?? '')"
5003
+ />
5004
+ </div>
5005
+ }
5006
+ @if (toolConfig().showTimezone !== false) {
5007
+ <div class="i18n-select-group">
5008
+ <label for="i18n-timezone">Timezone</label>
5009
+ <ndt-select
5010
+ id="i18n-timezone"
5011
+ [value]="activeTimezone()"
5012
+ [options]="timezoneOptions()"
5013
+ [size]="'medium'"
5014
+ (valueChange)="onTimezoneChange($event ?? '')"
5015
+ />
5016
+ </div>
5017
+ }
5018
+ @if (toolConfig().showCurrency !== false) {
5019
+ <div class="i18n-select-group">
5020
+ <label for="i18n-currency">Currency</label>
5021
+ <ndt-select
5022
+ id="i18n-currency"
5023
+ [value]="activeCurrency()"
5024
+ [options]="currencyOptions()"
5025
+ [size]="'medium'"
5026
+ (valueChange)="onCurrencyChange($event ?? '')"
5027
+ />
5028
+ </div>
5029
+ }
5030
+ @if (toolConfig().showUnits !== false) {
5031
+ <div class="i18n-select-group">
5032
+ <label for="i18n-units">Units</label>
5033
+ <ndt-select
5034
+ id="i18n-units"
5035
+ [value]="activeUnitSystem()"
5036
+ [options]="unitSystemOptions"
5037
+ [size]="'medium'"
5038
+ (valueChange)="onUnitSystemChange($event ?? '')"
5039
+ />
5040
+ </div>
5041
+ }
5042
+ @if (toolConfig().showDateFormat !== false) {
5043
+ <div class="i18n-select-group">
5044
+ <label for="i18n-date-format">Date Format</label>
5045
+ <ndt-select
5046
+ id="i18n-date-format"
5047
+ [value]="activeDateFormat()"
5048
+ [options]="dateFormatOptions"
5049
+ [size]="'medium'"
5050
+ (valueChange)="onDateFormatChange($event ?? '')"
5051
+ />
5052
+ </div>
5053
+ }
5054
+ @if (toolConfig().showNumberFormat !== false) {
5055
+ <div class="i18n-select-group">
5056
+ <label for="i18n-number-format">Number Format</label>
5057
+ <ndt-select
5058
+ id="i18n-number-format"
5059
+ [value]="activeNumberFormat()"
5060
+ [options]="numberFormatOptions"
5061
+ [size]="'medium'"
5062
+ (valueChange)="onNumberFormatChange($event ?? '')"
5063
+ />
5064
+ </div>
5065
+ }
5066
+ @if (toolConfig().showFirstDayOfWeek !== false) {
5067
+ <div class="i18n-select-group">
5068
+ <label for="i18n-first-day">First Day of Week</label>
5069
+ <ndt-select
5070
+ id="i18n-first-day"
5071
+ [value]="activeFirstDayOfWeek()"
5072
+ [options]="firstDayOptions"
5073
+ [size]="'medium'"
5074
+ (valueChange)="onFirstDayOfWeekChange($event ?? '')"
5075
+ />
5076
+ </div>
5077
+ }
5078
+ </div>
5079
+
5080
+ <!-- Stress Testing -->
5081
+ @if (toolConfig().showStressTesting !== false) {
5082
+ <div class="i18n-section-header">STRESS TESTING</div>
5083
+ <div class="i18n-toggle-section">
5084
+ <div class="i18n-toggle-row">
5085
+ <div class="toggle-info">
5086
+ <span class="toggle-label">Pseudo-Localization</span>
5087
+ <span class="toggle-hint">Detect hardcoded strings</span>
5088
+ </div>
5089
+ <label class="toggle-switch">
5090
+ <input
5091
+ type="checkbox"
5092
+ [checked]="pseudoLocEnabled()"
5093
+ (change)="onPseudoLocToggle($event)"
5094
+ />
5095
+ <span class="toggle-track"></span>
5096
+ </label>
5097
+ </div>
5098
+ @if (pseudoLocEnabled()) {
5099
+ <div class="i18n-pseudo-preview">
5100
+ {{ pseudoPreview() }}
5101
+ </div>
5102
+ }
5103
+ <div class="i18n-toggle-row">
5104
+ <div class="toggle-info">
5105
+ <span class="toggle-label">RTL Mirroring</span>
5106
+ <span class="toggle-hint">Set document direction to RTL</span>
5107
+ </div>
5108
+ <label class="toggle-switch">
5109
+ <input
5110
+ type="checkbox"
5111
+ [checked]="rtlEnabled()"
5112
+ (change)="onRtlToggle($event)"
5113
+ />
5114
+ <span class="toggle-track"></span>
5115
+ </label>
5116
+ </div>
5117
+ </div>
5118
+ }
3951
5119
  </div>
3952
5120
  </ndt-toolbar-tool>
3953
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.language-select{display:flex;flex-direction:row;gap:.5rem;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }] }); }
5121
+ `, isInline: true, styles: [":host{display:block}.i18n-section{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);padding-top:0}.i18n-section-header{font-size:var(--ndt-font-size-xxs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ndt-text-muted);margin-top:var(--ndt-spacing-md);padding:var(--ndt-spacing-xs) 0 var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-left:2px solid rgba(var(--ndt-primary-rgb),.4)}.i18n-section-header:first-child{margin-top:0}.i18n-select-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--ndt-spacing-sm) var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-xs)}.i18n-select-group{display:flex;flex-direction:column;gap:2px}.i18n-select-group label{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-secondary);font-weight:600}.i18n-standalone-select{margin-top:var(--ndt-spacing-sm)}.i18n-preview{background:var(--ndt-hover-bg);border-radius:var(--ndt-border-radius-medium);border-left:2px solid var(--ndt-border-primary);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-xs);display:flex;flex-direction:column;gap:1px}.i18n-preview-row{display:flex;justify-content:space-between;align-items:center;font-size:var(--ndt-font-size-xxs);gap:var(--ndt-spacing-xs);padding:2px 0}.i18n-preview-row .preview-label{color:var(--ndt-text-muted);flex-shrink:0}.i18n-preview-row .preview-value{font-family:JetBrains Mono,ui-monospace,monospace;font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-primary);text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.i18n-toggle-section{display:flex;flex-direction:column;gap:0;margin-top:var(--ndt-spacing-xs)}.i18n-toggle-row{display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);gap:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);transition:background .15s ease}.i18n-toggle-row:hover{background:var(--ndt-hover-bg)}.i18n-toggle-row .toggle-info{display:flex;flex-direction:column;gap:1px;min-width:0}.i18n-toggle-row .toggle-label{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-secondary);font-weight:500}.i18n-toggle-row .toggle-hint{font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-muted);line-height:1.3}.toggle-switch{position:relative;display:inline-flex;align-items:center;width:34px;height:18px;flex-shrink:0;cursor:pointer}.toggle-switch input{opacity:0;width:0;height:0;position:absolute}.toggle-switch input:focus-visible+.toggle-track{outline:2px solid rgba(var(--ndt-primary-rgb),.5);outline-offset:2px}.toggle-switch .toggle-track{position:absolute;inset:0;background:var(--ndt-border-primary);border-radius:9px;transition:background .2s ease}.toggle-switch .toggle-track:after{content:\"\";position:absolute;top:2px;left:2px;width:14px;height:14px;background:#fff;border-radius:50%;transition:transform .2s cubic-bezier(.4,0,.2,1);box-shadow:0 1px 2px #0000001f}.toggle-switch input:checked+.toggle-track{background:var(--ndt-primary)}.toggle-switch input:checked+.toggle-track:after{transform:translate(16px)}.i18n-pseudo-preview{background:var(--ndt-hover-bg);border-radius:var(--ndt-border-radius-small);border-left:2px solid rgba(var(--ndt-primary-rgb),.3);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);margin:0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);font-family:JetBrains Mono,ui-monospace,monospace;word-break:break-word;line-height:1.5}\n"], dependencies: [{ kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3954
5122
  }
3955
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLanguageToolComponent, decorators: [{
5123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarI18nToolComponent, decorators: [{
3956
5124
  type: Component,
3957
- args: [{ selector: 'ndt-language-tool', standalone: true, imports: [ToolbarToolComponent, ToolbarSelectComponent], template: `
3958
- <ndt-toolbar-tool title="Languages" icon="translate" [options]="options">
3959
- <div class="language-select">
3960
- <label for="language-select">Language</label>
3961
- <ndt-select
3962
- id="language-select"
3963
- [value]="activeLanguage()"
3964
- [options]="languageOptions()"
3965
- [size]="'medium'"
3966
- (valueChange)="onLanguageChange($event ?? '')"
3967
- />
5125
+ args: [{ selector: 'ndt-i18n-tool', standalone: true, imports: [ToolbarToolComponent, ToolbarSelectComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
5126
+ <ndt-toolbar-tool toolTitle="i18n" icon="globe" [options]="options">
5127
+ <div class="i18n-section">
5128
+ <!-- Formatting Preview (at top for immediate feedback) -->
5129
+ @if (toolConfig().showFormattingPreview !== false) {
5130
+ <div class="i18n-section-header">FORMATTING PREVIEW</div>
5131
+ <div class="i18n-preview">
5132
+ <div class="i18n-preview-row">
5133
+ <span class="preview-label">Number</span>
5134
+ <span class="preview-value">{{ previewNumber() }}</span>
5135
+ </div>
5136
+ <div class="i18n-preview-row">
5137
+ <span class="preview-label">Date</span>
5138
+ <span class="preview-value">{{ previewDate() }}</span>
5139
+ </div>
5140
+ <div class="i18n-preview-row">
5141
+ <span class="preview-label">Time</span>
5142
+ <span class="preview-value">{{ previewTime() }}</span>
5143
+ </div>
5144
+ <div class="i18n-preview-row">
5145
+ <span class="preview-label">Currency</span>
5146
+ <span class="preview-value">{{ previewCurrencyValue() }}</span>
5147
+ </div>
5148
+ </div>
5149
+ }
5150
+
5151
+ <!-- Settings (flat 2-column grid) -->
5152
+ <div class="i18n-select-grid">
5153
+ @if (toolConfig().showLocale !== false) {
5154
+ <div class="i18n-select-group">
5155
+ <label for="i18n-locale">Locale</label>
5156
+ <ndt-select
5157
+ id="i18n-locale"
5158
+ [value]="activeLocale()"
5159
+ [options]="localeOptions()"
5160
+ [size]="'medium'"
5161
+ (valueChange)="onLocaleChange($event ?? '')"
5162
+ />
5163
+ </div>
5164
+ }
5165
+ @if (toolConfig().showTimezone !== false) {
5166
+ <div class="i18n-select-group">
5167
+ <label for="i18n-timezone">Timezone</label>
5168
+ <ndt-select
5169
+ id="i18n-timezone"
5170
+ [value]="activeTimezone()"
5171
+ [options]="timezoneOptions()"
5172
+ [size]="'medium'"
5173
+ (valueChange)="onTimezoneChange($event ?? '')"
5174
+ />
5175
+ </div>
5176
+ }
5177
+ @if (toolConfig().showCurrency !== false) {
5178
+ <div class="i18n-select-group">
5179
+ <label for="i18n-currency">Currency</label>
5180
+ <ndt-select
5181
+ id="i18n-currency"
5182
+ [value]="activeCurrency()"
5183
+ [options]="currencyOptions()"
5184
+ [size]="'medium'"
5185
+ (valueChange)="onCurrencyChange($event ?? '')"
5186
+ />
5187
+ </div>
5188
+ }
5189
+ @if (toolConfig().showUnits !== false) {
5190
+ <div class="i18n-select-group">
5191
+ <label for="i18n-units">Units</label>
5192
+ <ndt-select
5193
+ id="i18n-units"
5194
+ [value]="activeUnitSystem()"
5195
+ [options]="unitSystemOptions"
5196
+ [size]="'medium'"
5197
+ (valueChange)="onUnitSystemChange($event ?? '')"
5198
+ />
5199
+ </div>
5200
+ }
5201
+ @if (toolConfig().showDateFormat !== false) {
5202
+ <div class="i18n-select-group">
5203
+ <label for="i18n-date-format">Date Format</label>
5204
+ <ndt-select
5205
+ id="i18n-date-format"
5206
+ [value]="activeDateFormat()"
5207
+ [options]="dateFormatOptions"
5208
+ [size]="'medium'"
5209
+ (valueChange)="onDateFormatChange($event ?? '')"
5210
+ />
5211
+ </div>
5212
+ }
5213
+ @if (toolConfig().showNumberFormat !== false) {
5214
+ <div class="i18n-select-group">
5215
+ <label for="i18n-number-format">Number Format</label>
5216
+ <ndt-select
5217
+ id="i18n-number-format"
5218
+ [value]="activeNumberFormat()"
5219
+ [options]="numberFormatOptions"
5220
+ [size]="'medium'"
5221
+ (valueChange)="onNumberFormatChange($event ?? '')"
5222
+ />
5223
+ </div>
5224
+ }
5225
+ @if (toolConfig().showFirstDayOfWeek !== false) {
5226
+ <div class="i18n-select-group">
5227
+ <label for="i18n-first-day">First Day of Week</label>
5228
+ <ndt-select
5229
+ id="i18n-first-day"
5230
+ [value]="activeFirstDayOfWeek()"
5231
+ [options]="firstDayOptions"
5232
+ [size]="'medium'"
5233
+ (valueChange)="onFirstDayOfWeekChange($event ?? '')"
5234
+ />
5235
+ </div>
5236
+ }
5237
+ </div>
5238
+
5239
+ <!-- Stress Testing -->
5240
+ @if (toolConfig().showStressTesting !== false) {
5241
+ <div class="i18n-section-header">STRESS TESTING</div>
5242
+ <div class="i18n-toggle-section">
5243
+ <div class="i18n-toggle-row">
5244
+ <div class="toggle-info">
5245
+ <span class="toggle-label">Pseudo-Localization</span>
5246
+ <span class="toggle-hint">Detect hardcoded strings</span>
5247
+ </div>
5248
+ <label class="toggle-switch">
5249
+ <input
5250
+ type="checkbox"
5251
+ [checked]="pseudoLocEnabled()"
5252
+ (change)="onPseudoLocToggle($event)"
5253
+ />
5254
+ <span class="toggle-track"></span>
5255
+ </label>
5256
+ </div>
5257
+ @if (pseudoLocEnabled()) {
5258
+ <div class="i18n-pseudo-preview">
5259
+ {{ pseudoPreview() }}
5260
+ </div>
5261
+ }
5262
+ <div class="i18n-toggle-row">
5263
+ <div class="toggle-info">
5264
+ <span class="toggle-label">RTL Mirroring</span>
5265
+ <span class="toggle-hint">Set document direction to RTL</span>
5266
+ </div>
5267
+ <label class="toggle-switch">
5268
+ <input
5269
+ type="checkbox"
5270
+ [checked]="rtlEnabled()"
5271
+ (change)="onRtlToggle($event)"
5272
+ />
5273
+ <span class="toggle-track"></span>
5274
+ </label>
5275
+ </div>
5276
+ </div>
5277
+ }
3968
5278
  </div>
3969
5279
  </ndt-toolbar-tool>
3970
- `, 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-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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)}.language-select{display:flex;flex-direction:row;gap:.5rem;align-items:center;justify-content:space-between}\n"] }]
3971
- }] });
5280
+ `, styles: [":host{display:block}.i18n-section{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);padding-top:0}.i18n-section-header{font-size:var(--ndt-font-size-xxs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ndt-text-muted);margin-top:var(--ndt-spacing-md);padding:var(--ndt-spacing-xs) 0 var(--ndt-spacing-xs) var(--ndt-spacing-sm);border-left:2px solid rgba(var(--ndt-primary-rgb),.4)}.i18n-section-header:first-child{margin-top:0}.i18n-select-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--ndt-spacing-sm) var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-xs)}.i18n-select-group{display:flex;flex-direction:column;gap:2px}.i18n-select-group label{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-secondary);font-weight:600}.i18n-standalone-select{margin-top:var(--ndt-spacing-sm)}.i18n-preview{background:var(--ndt-hover-bg);border-radius:var(--ndt-border-radius-medium);border-left:2px solid var(--ndt-border-primary);padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);margin-top:var(--ndt-spacing-xs);display:flex;flex-direction:column;gap:1px}.i18n-preview-row{display:flex;justify-content:space-between;align-items:center;font-size:var(--ndt-font-size-xxs);gap:var(--ndt-spacing-xs);padding:2px 0}.i18n-preview-row .preview-label{color:var(--ndt-text-muted);flex-shrink:0}.i18n-preview-row .preview-value{font-family:JetBrains Mono,ui-monospace,monospace;font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-primary);text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.i18n-toggle-section{display:flex;flex-direction:column;gap:0;margin-top:var(--ndt-spacing-xs)}.i18n-toggle-row{display:flex;align-items:center;justify-content:space-between;padding:var(--ndt-spacing-xs) var(--ndt-spacing-sm);gap:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);transition:background .15s ease}.i18n-toggle-row:hover{background:var(--ndt-hover-bg)}.i18n-toggle-row .toggle-info{display:flex;flex-direction:column;gap:1px;min-width:0}.i18n-toggle-row .toggle-label{font-size:var(--ndt-font-size-xs);color:var(--ndt-text-secondary);font-weight:500}.i18n-toggle-row .toggle-hint{font-size:var(--ndt-font-size-xxs);color:var(--ndt-text-muted);line-height:1.3}.toggle-switch{position:relative;display:inline-flex;align-items:center;width:34px;height:18px;flex-shrink:0;cursor:pointer}.toggle-switch input{opacity:0;width:0;height:0;position:absolute}.toggle-switch input:focus-visible+.toggle-track{outline:2px solid rgba(var(--ndt-primary-rgb),.5);outline-offset:2px}.toggle-switch .toggle-track{position:absolute;inset:0;background:var(--ndt-border-primary);border-radius:9px;transition:background .2s ease}.toggle-switch .toggle-track:after{content:\"\";position:absolute;top:2px;left:2px;width:14px;height:14px;background:#fff;border-radius:50%;transition:transform .2s cubic-bezier(.4,0,.2,1);box-shadow:0 1px 2px #0000001f}.toggle-switch input:checked+.toggle-track{background:var(--ndt-primary)}.toggle-switch input:checked+.toggle-track:after{transform:translate(16px)}.i18n-pseudo-preview{background:var(--ndt-hover-bg);border-radius:var(--ndt-border-radius-small);border-left:2px solid rgba(var(--ndt-primary-rgb),.3);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);margin:0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-xs);color:var(--ndt-text-muted);font-family:JetBrains Mono,ui-monospace,monospace;word-break:break-word;line-height:1.5}\n"] }]
5281
+ }], ctorParameters: () => [] });
3972
5282
 
3973
5283
  class ToolbarInternalPermissionsService {
3974
5284
  constructor() {
@@ -4004,6 +5314,10 @@ class ToolbarInternalPermissionsService {
4004
5314
  });
4005
5315
  }));
4006
5316
  this.permissions = toSignal(this.permissions$, { initialValue: [] });
5317
+ // Apply to source
5318
+ this.applyCallback = signal(null);
5319
+ this.applyStates = signal({});
5320
+ this.hasApplyCallback = computed(() => this.applyCallback() !== null);
4007
5321
  this.loadForcedState();
4008
5322
  }
4009
5323
  setAppPermissions(permissions) {
@@ -4082,6 +5396,24 @@ class ToolbarInternalPermissionsService {
4082
5396
  return (Array.isArray(candidate['granted']) &&
4083
5397
  Array.isArray(candidate['denied']));
4084
5398
  }
5399
+ setApplyToSource(callback) {
5400
+ this.applyCallback.set(callback);
5401
+ }
5402
+ async applyToSource(id, value) {
5403
+ const callback = this.applyCallback();
5404
+ if (!callback)
5405
+ return;
5406
+ this.applyStates.update((s) => ({ ...s, [id]: 'loading' }));
5407
+ try {
5408
+ await callback(id, value);
5409
+ this.applyStates.update((s) => ({ ...s, [id]: 'success' }));
5410
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
5411
+ }
5412
+ catch {
5413
+ this.applyStates.update((s) => ({ ...s, [id]: 'error' }));
5414
+ setTimeout(() => this.applyStates.update((s) => ({ ...s, [id]: 'idle' })), 1500);
5415
+ }
5416
+ }
4085
5417
  validateAndCleanForcedState(permissions) {
4086
5418
  const currentState = this.forcedStateSubject.value;
4087
5419
  const validIds = new Set(permissions.map((p) => p.id));
@@ -4123,6 +5455,7 @@ class ToolbarPermissionsToolComponent {
4123
5455
  // Signals
4124
5456
  this.activeFilter = signal('all');
4125
5457
  this.searchQuery = signal('');
5458
+ this.pinnedIds = signal(new Set());
4126
5459
  this.permissions = this.permissionsService.permissions;
4127
5460
  // Computed badge count for forced values
4128
5461
  this.badgeCount = computed(() => {
@@ -4148,8 +5481,15 @@ class ToolbarPermissionsToolComponent {
4148
5481
  (this.activeFilter() === 'denied' && !permission.isGranted);
4149
5482
  return matchesSearch && matchesFilter;
4150
5483
  });
4151
- // Sort alphabetically by name
4152
- return filtered.sort((a, b) => a.name.localeCompare(b.name));
5484
+ const pinned = this.pinnedIds();
5485
+ // Sort pinned first, then alphabetically within each group
5486
+ return filtered.sort((a, b) => {
5487
+ const aPinned = pinned.has(a.id);
5488
+ const bPinned = pinned.has(b.id);
5489
+ if (aPinned !== bPinned)
5490
+ return aPinned ? -1 : 1;
5491
+ return a.name.localeCompare(b.name);
5492
+ });
4153
5493
  });
4154
5494
  this.hasNoFilteredPermissions = computed(() => this.filteredPermissions().length === 0);
4155
5495
  // Other properties
@@ -4159,7 +5499,6 @@ class ToolbarPermissionsToolComponent {
4159
5499
  isClosable: true,
4160
5500
  size: 'tall',
4161
5501
  id: 'ndt-permissions',
4162
- isBeta: true,
4163
5502
  };
4164
5503
  this.filterOptions = [
4165
5504
  { value: 'all', label: 'All Permissions' },
@@ -4172,6 +5511,8 @@ class ToolbarPermissionsToolComponent {
4172
5511
  { value: 'denied', label: 'Forced Denied' },
4173
5512
  { value: 'granted', label: 'Forced Granted' },
4174
5513
  ];
5514
+ // Apply to source (delegated to internal service)
5515
+ this.hasApplyCallback = this.permissionsService.hasApplyCallback;
4175
5516
  this.loadViewState();
4176
5517
  // Save view state on changes
4177
5518
  effect(() => {
@@ -4179,6 +5520,7 @@ class ToolbarPermissionsToolComponent {
4179
5520
  searchQuery: this.searchQuery(),
4180
5521
  filter: this.activeFilter(),
4181
5522
  sortOrder: 'asc',
5523
+ pinnedIds: [...this.pinnedIds()],
4182
5524
  };
4183
5525
  this.storageService.set(this.VIEW_STATE_KEY, state);
4184
5526
  });
@@ -4192,12 +5534,21 @@ class ToolbarPermissionsToolComponent {
4192
5534
  if (['all', 'forced', 'granted', 'denied'].includes(filter)) {
4193
5535
  this.activeFilter.set(filter);
4194
5536
  }
5537
+ if (saved.pinnedIds?.length) {
5538
+ this.pinnedIds.set(new Set(saved.pinnedIds));
5539
+ }
4195
5540
  }
4196
5541
  }
4197
5542
  catch {
4198
5543
  // Use defaults on error
4199
5544
  }
4200
5545
  }
5546
+ getApplyState(permissionId) {
5547
+ return this.permissionsService.applyStates()[permissionId] ?? 'idle';
5548
+ }
5549
+ onApplyToSource(permissionId, value) {
5550
+ this.permissionsService.applyToSource(permissionId, value);
5551
+ }
4201
5552
  // Public methods
4202
5553
  onFilterChange(value) {
4203
5554
  const filter = this.filterOptions.find((f) => f.value === value);
@@ -4221,6 +5572,18 @@ class ToolbarPermissionsToolComponent {
4221
5572
  onSearchChange(query) {
4222
5573
  this.searchQuery.set(query);
4223
5574
  }
5575
+ togglePin(permissionId) {
5576
+ this.pinnedIds.update((ids) => {
5577
+ const next = new Set(ids);
5578
+ if (next.has(permissionId)) {
5579
+ next.delete(permissionId);
5580
+ }
5581
+ else {
5582
+ next.add(permissionId);
5583
+ }
5584
+ return next;
5585
+ });
5586
+ }
4224
5587
  // Protected methods
4225
5588
  getPermissionValue(permission) {
4226
5589
  if (!permission.isForced)
@@ -4231,7 +5594,7 @@ class ToolbarPermissionsToolComponent {
4231
5594
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarPermissionsToolComponent, isStandalone: true, selector: "ndt-permissions-tool", ngImport: i0, template: `
4232
5595
  <ndt-toolbar-tool
4233
5596
  [options]="options"
4234
- title="Permissions"
5597
+ toolTitle="Permissions"
4235
5598
  icon="lock"
4236
5599
  [badge]="badgeCount()"
4237
5600
  >
@@ -4244,7 +5607,6 @@ class ToolbarPermissionsToolComponent {
4244
5607
  [ariaLabel]="'Search permissions'"
4245
5608
  />
4246
5609
  <div class="filter-wrapper">
4247
- <ndt-icon name="filter" class="filter-icon" />
4248
5610
  <ndt-select
4249
5611
  [value]="activeFilter()"
4250
5612
  [options]="filterOptions"
@@ -4269,6 +5631,11 @@ class ToolbarPermissionsToolComponent {
4269
5631
  [isForced]="permission.isForced"
4270
5632
  [currentValue]="permission.isGranted"
4271
5633
  [originalValue]="permission.originalValue"
5634
+ [isPinned]="pinnedIds().has(permission.id)"
5635
+ (pinToggle)="togglePin(permission.id)"
5636
+ [showApply]="hasApplyCallback()"
5637
+ [applyState]="getApplyState(permission.id)"
5638
+ (applyToSource)="onApplyToSource(permission.id, permission.isGranted)"
4272
5639
  >
4273
5640
  <ndt-select
4274
5641
  [value]="getPermissionValue(permission)"
@@ -4282,7 +5649,7 @@ class ToolbarPermissionsToolComponent {
4282
5649
  </ndt-list>
4283
5650
  </div>
4284
5651
  </ndt-toolbar-tool>
4285
- `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5652
+ `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarSelectComponent, selector: "ndt-select", inputs: ["value", "options", "ariaLabel", "label", "size", "placeholder"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarListComponent, selector: "ndt-list", inputs: ["hasItems", "hasResults", "emptyMessage", "emptyHint", "noResultsMessage"] }, { kind: "component", type: ToolbarListItemComponent, selector: "ndt-list-item", inputs: ["title", "description", "isForced", "currentValue", "originalValue", "showApply", "applyState", "isPinned"], outputs: ["pinToggle", "applyToSource"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4286
5653
  }
4287
5654
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsToolComponent, decorators: [{
4288
5655
  type: Component,
@@ -4291,13 +5658,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
4291
5658
  ToolbarToolComponent,
4292
5659
  ToolbarInputComponent,
4293
5660
  ToolbarSelectComponent,
4294
- ToolbarIconComponent,
4295
5661
  ToolbarListComponent,
4296
5662
  ToolbarListItemComponent,
4297
5663
  ], template: `
4298
5664
  <ndt-toolbar-tool
4299
5665
  [options]="options"
4300
- title="Permissions"
5666
+ toolTitle="Permissions"
4301
5667
  icon="lock"
4302
5668
  [badge]="badgeCount()"
4303
5669
  >
@@ -4310,7 +5676,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
4310
5676
  [ariaLabel]="'Search permissions'"
4311
5677
  />
4312
5678
  <div class="filter-wrapper">
4313
- <ndt-icon name="filter" class="filter-icon" />
4314
5679
  <ndt-select
4315
5680
  [value]="activeFilter()"
4316
5681
  [options]="filterOptions"
@@ -4335,6 +5700,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
4335
5700
  [isForced]="permission.isForced"
4336
5701
  [currentValue]="permission.isGranted"
4337
5702
  [originalValue]="permission.originalValue"
5703
+ [isPinned]="pinnedIds().has(permission.id)"
5704
+ (pinToggle)="togglePin(permission.id)"
5705
+ [showApply]="hasApplyCallback()"
5706
+ [applyState]="getApplyState(permission.id)"
5707
+ (applyToSource)="onApplyToSource(permission.id, permission.isGranted)"
4338
5708
  >
4339
5709
  <ndt-select
4340
5710
  [value]="getPermissionValue(permission)"
@@ -4348,7 +5718,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
4348
5718
  </ndt-list>
4349
5719
  </div>
4350
5720
  </ndt-toolbar-tool>
4351
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;gap:var(--ndt-spacing-md);.filter-icon{width:18px;height:18px;flex-shrink:0;opacity:.6}ndt-select{flex:0 0 auto;min-width:180px}}}\n"] }]
5721
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);ndt-input{flex:1}.filter-wrapper{flex:0 0 auto;display:flex;align-items:center;border-left:1px solid var(--ndt-border-primary);padding-left:var(--ndt-spacing-sm);ndt-select{flex:0 0 auto;min-width:140px}}}\n"] }]
4352
5722
  }], ctorParameters: () => [] });
4353
5723
 
4354
5724
  /**
@@ -4361,9 +5731,9 @@ class ToolbarInternalPresetsService {
4361
5731
  this.storageService = inject(ToolbarStorageService);
4362
5732
  // Inject all other tool internal services (for reading/writing state)
4363
5733
  this.featureFlagsService = inject(ToolbarInternalFeatureFlagService);
4364
- this.languageService = inject(ToolbarInternalLanguageService);
4365
5734
  this.permissionsService = inject(ToolbarInternalPermissionsService);
4366
5735
  this.appFeaturesService = inject(ToolbarInternalAppFeaturesService);
5736
+ this.i18nService = inject(ToolbarInternalI18nService);
4367
5737
  this.presetsSubject = new BehaviorSubject([]);
4368
5738
  this.presets$ = this.presetsSubject.asObservable();
4369
5739
  this.presets = toSignal(this.presets$, { initialValue: [] });
@@ -4395,9 +5765,11 @@ class ToolbarInternalPresetsService {
4395
5765
  return;
4396
5766
  // Apply to each tool's internal service
4397
5767
  this.featureFlagsService.applyPresetFlags(preset.config.featureFlags);
4398
- await this.languageService.applyPresetLanguage(preset.config.language);
4399
5768
  this.permissionsService.applyPresetPermissions(preset.config.permissions);
4400
5769
  this.appFeaturesService.applyForcedState(preset.config.appFeatures);
5770
+ if (preset.config.i18n) {
5771
+ this.i18nService.applyPresetI18n(preset.config.i18n);
5772
+ }
4401
5773
  }
4402
5774
  /**
4403
5775
  * Update an existing preset with current toolbar state
@@ -4464,15 +5836,15 @@ class ToolbarInternalPresetsService {
4464
5836
  if (options.applyFeatureFlags) {
4465
5837
  this.featureFlagsService.applyPresetFlags(preset.config.featureFlags);
4466
5838
  }
4467
- if (options.applyLanguage) {
4468
- await this.languageService.applyPresetLanguage(preset.config.language);
4469
- }
4470
5839
  if (options.applyPermissions) {
4471
5840
  this.permissionsService.applyPresetPermissions(preset.config.permissions);
4472
5841
  }
4473
5842
  if (options.applyAppFeatures) {
4474
5843
  this.appFeaturesService.applyForcedState(preset.config.appFeatures);
4475
5844
  }
5845
+ if (options.applyI18n && preset.config.i18n) {
5846
+ this.i18nService.applyPresetI18n(preset.config.i18n);
5847
+ }
4476
5848
  }
4477
5849
  /**
4478
5850
  * Update only the metadata (name, description) of a preset without changing config
@@ -4501,7 +5873,7 @@ class ToolbarInternalPresetsService {
4501
5873
  includeFeatureFlags: categoryOptions?.includeFeatureFlags ?? true,
4502
5874
  includePermissions: categoryOptions?.includePermissions ?? true,
4503
5875
  includeAppFeatures: categoryOptions?.includeAppFeatures ?? true,
4504
- includeLanguage: categoryOptions?.includeLanguage ?? true,
5876
+ includeI18n: categoryOptions?.includeI18n ?? true,
4505
5877
  };
4506
5878
  // Get current forced states
4507
5879
  const currentFlags = this.featureFlagsService.getCurrentForcedState();
@@ -4516,9 +5888,6 @@ class ToolbarInternalPresetsService {
4516
5888
  disabled: filterById(currentFlags.disabled, categoryOptions?.selectedFlagIds),
4517
5889
  }
4518
5890
  : { enabled: [], disabled: [] },
4519
- language: options.includeLanguage
4520
- ? this.languageService.getCurrentForcedLanguage()
4521
- : null,
4522
5891
  permissions: options.includePermissions
4523
5892
  ? {
4524
5893
  granted: filterById(currentPerms.granted, categoryOptions?.selectedPermissionIds),
@@ -4531,6 +5900,19 @@ class ToolbarInternalPresetsService {
4531
5900
  disabled: filterById(currentFeatures.disabled, categoryOptions?.selectedFeatureIds),
4532
5901
  }
4533
5902
  : { enabled: [], disabled: [] },
5903
+ i18n: options.includeI18n
5904
+ ? (() => {
5905
+ const i18nState = this.i18nService.getCurrentI18nState();
5906
+ return {
5907
+ locale: i18nState.locale?.id ?? null,
5908
+ timezone: i18nState.timezone?.id ?? null,
5909
+ currency: i18nState.currency?.code ?? null,
5910
+ unitSystem: i18nState.unitSystem ?? null,
5911
+ pseudoLocEnabled: i18nState.pseudoLocEnabled,
5912
+ rtlEnabled: i18nState.rtlEnabled,
5913
+ };
5914
+ })()
5915
+ : undefined,
4534
5916
  };
4535
5917
  }
4536
5918
  /**
@@ -4562,24 +5944,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
4562
5944
  }], ctorParameters: () => [] });
4563
5945
 
4564
5946
  class ToolbarPresetsToolComponent {
5947
+ onDocumentClick() {
5948
+ this.openMenuId.set(null);
5949
+ }
4565
5950
  constructor() {
4566
5951
  // Injects
4567
5952
  this.presetsService = inject(ToolbarInternalPresetsService);
4568
5953
  this.featureFlagsService = inject(ToolbarInternalFeatureFlagService);
4569
5954
  this.permissionsService = inject(ToolbarInternalPermissionsService);
4570
5955
  this.appFeaturesService = inject(ToolbarInternalAppFeaturesService);
4571
- this.languageService = inject(ToolbarInternalLanguageService);
4572
5956
  this.state = inject(ToolbarStateService);
4573
5957
  // View state signals
4574
5958
  this.viewMode = signal('list');
4575
5959
  this.searchQuery = signal('');
5960
+ this.expandedPresetId = signal(null);
5961
+ this.openMenuId = signal(null);
4576
5962
  // Create form signals
4577
5963
  this.presetName = signal('');
4578
5964
  this.presetDescription = signal('');
4579
5965
  this.includeFeatureFlags = signal(true);
4580
5966
  this.includePermissions = signal(true);
4581
5967
  this.includeAppFeatures = signal(true);
4582
- this.includeLanguage = signal(true);
4583
5968
  this.selectedFlagIds = signal(new Set());
4584
5969
  this.selectedPermissionIds = signal(new Set());
4585
5970
  this.selectedFeatureIds = signal(new Set());
@@ -4596,7 +5981,6 @@ class ToolbarPresetsToolComponent {
4596
5981
  this.applyFeatureFlags = signal(true);
4597
5982
  this.applyPermissions = signal(true);
4598
5983
  this.applyAppFeatures = signal(true);
4599
- this.applyLanguage = signal(true);
4600
5984
  // Delete confirmation signals
4601
5985
  this.deletePresetId = signal(null);
4602
5986
  // Toast signals
@@ -4648,7 +6032,6 @@ class ToolbarPresetsToolComponent {
4648
6032
  this.isFeatureFlagsEnabled = computed(() => this.state.config().showFeatureFlagsTool ?? true);
4649
6033
  this.isPermissionsEnabled = computed(() => this.state.config().showPermissionsTool ?? true);
4650
6034
  this.isAppFeaturesEnabled = computed(() => this.state.config().showAppFeaturesTool ?? true);
4651
- this.isLanguageEnabled = computed(() => this.state.config().showLanguageTool ?? true);
4652
6035
  // Forced items details
4653
6036
  this.forcedFlags = computed(() => {
4654
6037
  return this.featureFlagsService.flags().filter((flag) => flag.isForced);
@@ -4666,7 +6049,6 @@ class ToolbarPresetsToolComponent {
4666
6049
  isClosable: true,
4667
6050
  size: 'tall',
4668
6051
  id: 'ndt-presets',
4669
- isBeta: true,
4670
6052
  };
4671
6053
  effect(() => {
4672
6054
  const message = this.toastMessage();
@@ -4689,6 +6071,12 @@ class ToolbarPresetsToolComponent {
4689
6071
  onSearchChange(query) {
4690
6072
  this.searchQuery.set(query);
4691
6073
  }
6074
+ onToggleExpand(presetId) {
6075
+ this.expandedPresetId.update((current) => current === presetId ? null : presetId);
6076
+ }
6077
+ onToggleMenu(presetId) {
6078
+ this.openMenuId.update((current) => current === presetId ? null : presetId);
6079
+ }
4692
6080
  onSwitchToListMode() {
4693
6081
  this.viewMode.set('list');
4694
6082
  this.nameError.set(null);
@@ -4704,8 +6092,6 @@ class ToolbarPresetsToolComponent {
4704
6092
  this.includeFeatureFlags.set(this.getCurrentFlagsCount() > 0);
4705
6093
  this.includePermissions.set(this.getCurrentPermissionsCount() > 0);
4706
6094
  this.includeAppFeatures.set(this.getCurrentAppFeaturesCount() > 0);
4707
- const currentLang = this.getCurrentLanguage();
4708
- this.includeLanguage.set(!!currentLang && currentLang !== 'Not Forced');
4709
6095
  // Initialize selected items - select all by default
4710
6096
  this.selectedFlagIds.set(new Set(this.forcedFlags().map((f) => f.id)));
4711
6097
  this.selectedPermissionIds.set(new Set(this.forcedPermissions().map((p) => p.id)));
@@ -4741,7 +6127,6 @@ class ToolbarPresetsToolComponent {
4741
6127
  includeFeatureFlags: this.includeFeatureFlags(),
4742
6128
  includePermissions: this.includePermissions(),
4743
6129
  includeAppFeatures: this.includeAppFeatures(),
4744
- includeLanguage: this.includeLanguage(),
4745
6130
  selectedFlagIds: Array.from(this.selectedFlagIds()),
4746
6131
  selectedPermissionIds: Array.from(this.selectedPermissionIds()),
4747
6132
  selectedFeatureIds: Array.from(this.selectedFeatureIds()),
@@ -4871,7 +6256,6 @@ class ToolbarPresetsToolComponent {
4871
6256
  this.applyFeatureFlags.set(true);
4872
6257
  this.applyPermissions.set(true);
4873
6258
  this.applyAppFeatures.set(true);
4874
- this.applyLanguage.set(true);
4875
6259
  this.viewMode.set('apply');
4876
6260
  }
4877
6261
  onConfirmPartialApply() {
@@ -4882,7 +6266,6 @@ class ToolbarPresetsToolComponent {
4882
6266
  applyFeatureFlags: this.applyFeatureFlags(),
4883
6267
  applyPermissions: this.applyPermissions(),
4884
6268
  applyAppFeatures: this.applyAppFeatures(),
4885
- applyLanguage: this.applyLanguage(),
4886
6269
  });
4887
6270
  this.showToast('Preset applied successfully');
4888
6271
  this.onSwitchToListMode();
@@ -4938,9 +6321,6 @@ class ToolbarPresetsToolComponent {
4938
6321
  const state = this.appFeaturesService.getCurrentForcedState();
4939
6322
  return state.enabled.length + state.disabled.length;
4940
6323
  }
4941
- getCurrentLanguage() {
4942
- return this.languageService.getCurrentForcedLanguage() || 'Not Forced';
4943
- }
4944
6324
  formatDate(isoString) {
4945
6325
  return new Date(isoString).toLocaleDateString();
4946
6326
  }
@@ -4974,12 +6354,6 @@ class ToolbarPresetsToolComponent {
4974
6354
  featuresEnabled.forEach(id => lines.push(` ✓ ${id}: ON`));
4975
6355
  featuresDisabled.forEach(id => lines.push(` ✗ ${id}: OFF`));
4976
6356
  }
4977
- // Language
4978
- if (preset.config.language) {
4979
- if (lines.length > 0)
4980
- lines.push('');
4981
- lines.push(`Language: ${preset.config.language}`);
4982
- }
4983
6357
  return lines.length > 0 ? lines.join('\n') : 'No configuration';
4984
6358
  }
4985
6359
  toggleItemSelection(signal, itemId) {
@@ -4996,8 +6370,8 @@ class ToolbarPresetsToolComponent {
4996
6370
  return selectedSet.has(itemId);
4997
6371
  }
4998
6372
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPresetsToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4999
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarPresetsToolComponent, isStandalone: true, selector: "ndt-presets-tool", ngImport: i0, template: `
5000
- <ndt-toolbar-tool [options]="options" title="Presets" icon="layout">
6373
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarPresetsToolComponent, isStandalone: true, selector: "ndt-presets-tool", host: { listeners: { "document:click": "onDocumentClick()" } }, ngImport: i0, template: `
6374
+ <ndt-toolbar-tool [options]="options" toolTitle="Presets" icon="layout">
5001
6375
  <div class="container">
5002
6376
  <!-- Toast Notification -->
5003
6377
  @if (toastMessage()) {
@@ -5169,19 +6543,6 @@ class ToolbarPresetsToolComponent {
5169
6543
  </div>
5170
6544
  }
5171
6545
 
5172
- @if (isLanguageEnabled()) {
5173
- <div class="category-section">
5174
- <label class="checkbox-option">
5175
- <input
5176
- type="checkbox"
5177
- [checked]="includeLanguage()"
5178
- (change)="includeLanguage.set(!includeLanguage())"
5179
- [disabled]="!getCurrentLanguage() || getCurrentLanguage() === 'Not Forced'"
5180
- />
5181
- <span>Language ({{ getCurrentLanguage() }})</span>
5182
- </label>
5183
- </div>
5184
- }
5185
6546
  </div>
5186
6547
 
5187
6548
  <div class="form-actions">
@@ -5258,12 +6619,6 @@ class ToolbarPresetsToolComponent {
5258
6619
  </div>
5259
6620
  </div>
5260
6621
  }
5261
- @if (editingPreset()!.config.language) {
5262
- <div class="config-category">
5263
- <span class="config-category__title">Language</span>
5264
- <span class="config-item">{{ editingPreset()!.config.language }}</span>
5265
- </div>
5266
- }
5267
6622
  <button type="button" class="replace-config-button" (click)="onReplaceConfig()">
5268
6623
  ↻ Replace with current toolbar state
5269
6624
  </button>
@@ -5434,28 +6789,6 @@ class ToolbarPresetsToolComponent {
5434
6789
  </div>
5435
6790
  }
5436
6791
 
5437
- <!-- Language -->
5438
- @if (applyingPreset()!.config.language) {
5439
- <div class="apply-category" [class.apply-category--disabled]="!applyLanguage()">
5440
- <label class="apply-category__header">
5441
- <input
5442
- type="checkbox"
5443
- [checked]="applyLanguage()"
5444
- (change)="applyLanguage.set(!applyLanguage())"
5445
- />
5446
- <span>Language</span>
5447
- </label>
5448
- @if (applyLanguage()) {
5449
- <div class="apply-diff">
5450
- <div class="diff-item">
5451
- <span class="diff-item__name">Language</span>
5452
- <span class="diff-item__arrow">→</span>
5453
- <span class="diff-item__value">{{ applyingPreset()!.config.language }}</span>
5454
- </div>
5455
- </div>
5456
- }
5457
- </div>
5458
- }
5459
6792
  </div>
5460
6793
  }
5461
6794
 
@@ -5503,8 +6836,13 @@ class ToolbarPresetsToolComponent {
5503
6836
  <!-- Preset List -->
5504
6837
  <div class="preset-list">
5505
6838
  @for (preset of sortedPresets(); track preset.id) {
5506
- <div class="preset-card" [title]="getPresetTooltip(preset)">
6839
+ <div class="preset-card">
5507
6840
  <div class="preset-card__header">
6841
+ <button
6842
+ class="expand-toggle"
6843
+ (click)="onToggleExpand(preset.id); $event.stopPropagation()"
6844
+ [attr.aria-label]="expandedPresetId() === preset.id ? 'Collapse details' : 'Expand details'"
6845
+ >{{ expandedPresetId() === preset.id ? '▾' : '▸' }}</button>
5508
6846
  <button
5509
6847
  class="favorite-button"
5510
6848
  [class.favorite-button--active]="preset.isFavorite"
@@ -5515,16 +6853,40 @@ class ToolbarPresetsToolComponent {
5515
6853
  @if (preset.isSystem) {<span class="system-badge">SYS</span>}
5516
6854
  <span class="preset-card__spacer"></span>
5517
6855
  <div class="preset-card__actions">
5518
- <button class="icon-button" (click)="onStartApply(preset.id)"><ndt-icon name="refresh" /></button>
6856
+ <button
6857
+ class="more-button"
6858
+ (click)="onToggleMenu(preset.id); $event.stopPropagation()"
6859
+ aria-label="Actions"
6860
+ >⋯</button>
6861
+ </div>
6862
+ @if (openMenuId() === preset.id) {
6863
+ <div class="action-menu" role="menu" tabindex="-1" (click)="$event.stopPropagation()" (keydown.escape)="openMenuId.set(null)">
6864
+ <button class="action-menu__item" (click)="onStartApply(preset.id); openMenuId.set(null)">
6865
+ <ndt-icon name="refresh" />
6866
+ <span>Apply preset</span>
6867
+ </button>
5519
6868
  @if (!preset.isSystem) {
5520
- <button class="icon-button" (click)="onStartEdit(preset.id)"><ndt-icon name="edit" /></button>
5521
- <button class="icon-button" (click)="onUpdatePreset(preset.id)"><ndt-icon name="gear" /></button>
6869
+ <button class="action-menu__item" (click)="onStartEdit(preset.id); openMenuId.set(null)">
6870
+ <ndt-icon name="edit" />
6871
+ <span>Edit</span>
6872
+ </button>
6873
+ <button class="action-menu__item" (click)="onUpdatePreset(preset.id); openMenuId.set(null)">
6874
+ <ndt-icon name="gear" />
6875
+ <span>Update with current values</span>
6876
+ </button>
5522
6877
  }
5523
- <button class="icon-button" (click)="onExportPreset(preset.id)"><ndt-icon name="export" /></button>
6878
+ <button class="action-menu__item" (click)="onExportPreset(preset.id); openMenuId.set(null)">
6879
+ <ndt-icon name="export" />
6880
+ <span>Export as JSON</span>
6881
+ </button>
5524
6882
  @if (!preset.isSystem) {
5525
- <button class="icon-button" (click)="onDeletePreset(preset.id)"><ndt-icon name="trash" /></button>
6883
+ <button class="action-menu__item action-menu__item--danger" (click)="onDeletePreset(preset.id); openMenuId.set(null)">
6884
+ <ndt-icon name="trash" />
6885
+ <span>Delete</span>
6886
+ </button>
5526
6887
  }
5527
6888
  </div>
6889
+ }
5528
6890
  </div>
5529
6891
  @if (preset.description) {
5530
6892
  <div class="preset-card__row preset-card__row--meta">
@@ -5541,18 +6903,58 @@ class ToolbarPresetsToolComponent {
5541
6903
  @if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
5542
6904
  <span class="badge">{{ preset.config.appFeatures.enabled.length + preset.config.appFeatures.disabled.length }} features</span>
5543
6905
  }
5544
- @if (preset.config.language) {
5545
- <span class="badge badge--lang">{{ preset.config.language }}</span>
5546
- }
5547
6906
  <span class="preset-card__date">{{ formatDate(preset.updatedAt) }}</span>
5548
6907
  </div>
6908
+ @if (expandedPresetId() === preset.id) {
6909
+ <div class="preset-card__details">
6910
+ @if (preset.config.featureFlags.enabled.length > 0 || preset.config.featureFlags.disabled.length > 0) {
6911
+ <div class="details-section">
6912
+ <span class="details-section__title">Feature Flags</span>
6913
+ <div class="details-section__items">
6914
+ @for (id of preset.config.featureFlags.enabled; track id) {
6915
+ <span class="detail-badge detail-badge--on">{{ id }}: ON</span>
6916
+ }
6917
+ @for (id of preset.config.featureFlags.disabled; track id) {
6918
+ <span class="detail-badge detail-badge--off">{{ id }}: OFF</span>
6919
+ }
6920
+ </div>
6921
+ </div>
6922
+ }
6923
+ @if (preset.config.permissions.granted.length > 0 || preset.config.permissions.denied.length > 0) {
6924
+ <div class="details-section">
6925
+ <span class="details-section__title">Permissions</span>
6926
+ <div class="details-section__items">
6927
+ @for (id of preset.config.permissions.granted; track id) {
6928
+ <span class="detail-badge detail-badge--on">{{ id }}: GRANTED</span>
6929
+ }
6930
+ @for (id of preset.config.permissions.denied; track id) {
6931
+ <span class="detail-badge detail-badge--off">{{ id }}: DENIED</span>
6932
+ }
6933
+ </div>
6934
+ </div>
6935
+ }
6936
+ @if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
6937
+ <div class="details-section">
6938
+ <span class="details-section__title">App Features</span>
6939
+ <div class="details-section__items">
6940
+ @for (id of preset.config.appFeatures.enabled; track id) {
6941
+ <span class="detail-badge detail-badge--on">{{ id }}: ON</span>
6942
+ }
6943
+ @for (id of preset.config.appFeatures.disabled; track id) {
6944
+ <span class="detail-badge detail-badge--off">{{ id }}: OFF</span>
6945
+ }
6946
+ </div>
6947
+ </div>
6948
+ }
6949
+ </div>
6950
+ }
5549
6951
  </div>
5550
6952
  }
5551
6953
  </div>
5552
6954
  }
5553
6955
  </div>
5554
6956
  </ndt-toolbar-tool>
5555
- `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ndt-spacing-md);left:var(--ndt-spacing-md);right:var(--ndt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ndt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ndt-spacing-lg) var(--ndt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ndt-spacing-md)}.delete-view__title{margin:0 0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.delete-view__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);cursor:pointer;font-size:var(--ndt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md);ndt-input{flex:1}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;p{margin:0}.hint{font-size:var(--ndt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px;&:hover{background:var(--ndt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-card{background:var(--ndt-background-secondary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:2px}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:18px}.preset-card__row--badges{padding-left:18px;gap:4px}.preset-card__name{font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ndt-border-primary);color:var(--ndt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ndt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:0;flex-shrink:0}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:4px;color:var(--ndt-text-muted);display:inline-flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out;line-height:0;&:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}ndt-icon,ndt-icon>*,svg{display:block;width:12px!important;height:12px!important}}.preset-card__description{font-size:11px;color:var(--ndt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ndt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm);ndt-input{width:100%}}.form-title{margin:0;font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ndt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ndt-spacing-xs);cursor:pointer;color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ndt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm);margin-top:auto;padding-top:var(--ndt-spacing-sm)}.config-preview{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ndt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ndt-background-primary);color:var(--ndt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ndt-border-primary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ndt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ndt-spacing-md);border:2px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ndt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ndt-spacing-sm);color:var(--ndt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ndt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ndt-spacing-xs);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background:var(--ndt-background-secondary);color:var(--ndt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ndt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ndt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.apply-category{background:var(--ndt-background-secondary);border-radius:var(--ndt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ndt-spacing-xs);padding:6px var(--ndt-spacing-sm);cursor:pointer;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ndt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ndt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ndt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ndt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6957
+ `, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ndt-spacing-md);left:var(--ndt-spacing-md);right:var(--ndt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ndt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ndt-spacing-lg) var(--ndt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ndt-spacing-md)}.delete-view__title{margin:0 0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.delete-view__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);cursor:pointer;font-size:var(--ndt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md);ndt-input{flex:1}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;p{margin:0}.hint{font-size:var(--ndt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px;&:hover{background:var(--ndt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-card{background:var(--ndt-background-secondary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:2px;position:relative}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:36px}.preset-card__row--badges{padding-left:36px;gap:4px}.preset-card__name{font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ndt-border-primary);color:var(--ndt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ndt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:2px;flex-shrink:0}.more-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-muted);display:flex;align-items:center;justify-content:center;width:22px;height:22px;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out,background .15s ease-out;line-height:1;font-size:14px;font-weight:700;position:relative;&:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}}.action-menu{position:absolute;top:28px;right:var(--ndt-spacing-sm);background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);box-shadow:var(--ndt-shadow-tooltip);z-index:20;min-width:180px;padding:4px;display:flex;flex-direction:column;gap:2px}.action-menu__item{appearance:none;background:none;border:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-xs);transition:background .15s ease-out;white-space:nowrap;&:hover{background:var(--ndt-hover-bg)}ndt-icon{display:block;width:14px;height:14px;flex-shrink:0;color:var(--ndt-text-muted)}}.action-menu__item--danger{color:#ef4444;ndt-icon{color:#ef4444}&:hover{background:#ef44441a}}.expand-toggle{appearance:none;background:none;border:none;cursor:pointer;padding:0 4px;margin-right:2px;font-size:10px;color:var(--ndt-text-muted);line-height:1;opacity:.6;transition:opacity .15s ease-out;flex-shrink:0;&:hover{opacity:1}}.preset-card__details{padding:var(--ndt-spacing-sm) var(--ndt-spacing-sm) var(--ndt-spacing-xs);margin-top:2px;border-top:1px solid var(--ndt-border-primary);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.details-section__title{font-size:10px;font-weight:600;color:var(--ndt-text-muted);text-transform:uppercase;letter-spacing:.5px}.details-section__items{display:flex;flex-wrap:wrap;gap:4px;margin-top:2px}.detail-badge{font-size:10px;padding:1px 6px;border-radius:var(--ndt-border-radius-small);white-space:nowrap}.detail-badge--on{background:#22c55e1a;color:#22c55e}.detail-badge--off{background:#ef44441a;color:#ef4444}.preset-card__description{font-size:11px;color:var(--ndt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ndt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm);ndt-input{width:100%}}.form-title{margin:0;font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ndt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ndt-spacing-xs);cursor:pointer;color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ndt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm);margin-top:auto;padding-top:var(--ndt-spacing-sm)}.config-preview{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ndt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ndt-background-primary);color:var(--ndt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ndt-border-primary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ndt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ndt-spacing-md);border:2px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ndt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ndt-spacing-sm);color:var(--ndt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ndt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ndt-spacing-xs);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background:var(--ndt-background-secondary);color:var(--ndt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ndt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ndt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.apply-category{background:var(--ndt-background-secondary);border-radius:var(--ndt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ndt-spacing-xs);padding:6px var(--ndt-spacing-sm);cursor:pointer;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ndt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ndt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ndt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ndt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ToolbarToolComponent, selector: "ndt-toolbar-tool", inputs: ["options", "icon", "toolTitle", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ndt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarButtonComponent, selector: "ndt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarIconComponent, selector: "ndt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5556
6958
  }
5557
6959
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPresetsToolComponent, decorators: [{
5558
6960
  type: Component,
@@ -5563,7 +6965,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
5563
6965
  ToolbarButtonComponent,
5564
6966
  ToolbarIconComponent,
5565
6967
  ], template: `
5566
- <ndt-toolbar-tool [options]="options" title="Presets" icon="layout">
6968
+ <ndt-toolbar-tool [options]="options" toolTitle="Presets" icon="layout">
5567
6969
  <div class="container">
5568
6970
  <!-- Toast Notification -->
5569
6971
  @if (toastMessage()) {
@@ -5735,19 +7137,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
5735
7137
  </div>
5736
7138
  }
5737
7139
 
5738
- @if (isLanguageEnabled()) {
5739
- <div class="category-section">
5740
- <label class="checkbox-option">
5741
- <input
5742
- type="checkbox"
5743
- [checked]="includeLanguage()"
5744
- (change)="includeLanguage.set(!includeLanguage())"
5745
- [disabled]="!getCurrentLanguage() || getCurrentLanguage() === 'Not Forced'"
5746
- />
5747
- <span>Language ({{ getCurrentLanguage() }})</span>
5748
- </label>
5749
- </div>
5750
- }
5751
7140
  </div>
5752
7141
 
5753
7142
  <div class="form-actions">
@@ -5824,12 +7213,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
5824
7213
  </div>
5825
7214
  </div>
5826
7215
  }
5827
- @if (editingPreset()!.config.language) {
5828
- <div class="config-category">
5829
- <span class="config-category__title">Language</span>
5830
- <span class="config-item">{{ editingPreset()!.config.language }}</span>
5831
- </div>
5832
- }
5833
7216
  <button type="button" class="replace-config-button" (click)="onReplaceConfig()">
5834
7217
  ↻ Replace with current toolbar state
5835
7218
  </button>
@@ -6000,28 +7383,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6000
7383
  </div>
6001
7384
  }
6002
7385
 
6003
- <!-- Language -->
6004
- @if (applyingPreset()!.config.language) {
6005
- <div class="apply-category" [class.apply-category--disabled]="!applyLanguage()">
6006
- <label class="apply-category__header">
6007
- <input
6008
- type="checkbox"
6009
- [checked]="applyLanguage()"
6010
- (change)="applyLanguage.set(!applyLanguage())"
6011
- />
6012
- <span>Language</span>
6013
- </label>
6014
- @if (applyLanguage()) {
6015
- <div class="apply-diff">
6016
- <div class="diff-item">
6017
- <span class="diff-item__name">Language</span>
6018
- <span class="diff-item__arrow">→</span>
6019
- <span class="diff-item__value">{{ applyingPreset()!.config.language }}</span>
6020
- </div>
6021
- </div>
6022
- }
6023
- </div>
6024
- }
6025
7386
  </div>
6026
7387
  }
6027
7388
 
@@ -6069,8 +7430,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6069
7430
  <!-- Preset List -->
6070
7431
  <div class="preset-list">
6071
7432
  @for (preset of sortedPresets(); track preset.id) {
6072
- <div class="preset-card" [title]="getPresetTooltip(preset)">
7433
+ <div class="preset-card">
6073
7434
  <div class="preset-card__header">
7435
+ <button
7436
+ class="expand-toggle"
7437
+ (click)="onToggleExpand(preset.id); $event.stopPropagation()"
7438
+ [attr.aria-label]="expandedPresetId() === preset.id ? 'Collapse details' : 'Expand details'"
7439
+ >{{ expandedPresetId() === preset.id ? '▾' : '▸' }}</button>
6074
7440
  <button
6075
7441
  class="favorite-button"
6076
7442
  [class.favorite-button--active]="preset.isFavorite"
@@ -6081,16 +7447,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6081
7447
  @if (preset.isSystem) {<span class="system-badge">SYS</span>}
6082
7448
  <span class="preset-card__spacer"></span>
6083
7449
  <div class="preset-card__actions">
6084
- <button class="icon-button" (click)="onStartApply(preset.id)"><ndt-icon name="refresh" /></button>
7450
+ <button
7451
+ class="more-button"
7452
+ (click)="onToggleMenu(preset.id); $event.stopPropagation()"
7453
+ aria-label="Actions"
7454
+ >⋯</button>
7455
+ </div>
7456
+ @if (openMenuId() === preset.id) {
7457
+ <div class="action-menu" role="menu" tabindex="-1" (click)="$event.stopPropagation()" (keydown.escape)="openMenuId.set(null)">
7458
+ <button class="action-menu__item" (click)="onStartApply(preset.id); openMenuId.set(null)">
7459
+ <ndt-icon name="refresh" />
7460
+ <span>Apply preset</span>
7461
+ </button>
6085
7462
  @if (!preset.isSystem) {
6086
- <button class="icon-button" (click)="onStartEdit(preset.id)"><ndt-icon name="edit" /></button>
6087
- <button class="icon-button" (click)="onUpdatePreset(preset.id)"><ndt-icon name="gear" /></button>
7463
+ <button class="action-menu__item" (click)="onStartEdit(preset.id); openMenuId.set(null)">
7464
+ <ndt-icon name="edit" />
7465
+ <span>Edit</span>
7466
+ </button>
7467
+ <button class="action-menu__item" (click)="onUpdatePreset(preset.id); openMenuId.set(null)">
7468
+ <ndt-icon name="gear" />
7469
+ <span>Update with current values</span>
7470
+ </button>
6088
7471
  }
6089
- <button class="icon-button" (click)="onExportPreset(preset.id)"><ndt-icon name="export" /></button>
7472
+ <button class="action-menu__item" (click)="onExportPreset(preset.id); openMenuId.set(null)">
7473
+ <ndt-icon name="export" />
7474
+ <span>Export as JSON</span>
7475
+ </button>
6090
7476
  @if (!preset.isSystem) {
6091
- <button class="icon-button" (click)="onDeletePreset(preset.id)"><ndt-icon name="trash" /></button>
7477
+ <button class="action-menu__item action-menu__item--danger" (click)="onDeletePreset(preset.id); openMenuId.set(null)">
7478
+ <ndt-icon name="trash" />
7479
+ <span>Delete</span>
7480
+ </button>
6092
7481
  }
6093
7482
  </div>
7483
+ }
6094
7484
  </div>
6095
7485
  @if (preset.description) {
6096
7486
  <div class="preset-card__row preset-card__row--meta">
@@ -6107,19 +7497,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6107
7497
  @if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
6108
7498
  <span class="badge">{{ preset.config.appFeatures.enabled.length + preset.config.appFeatures.disabled.length }} features</span>
6109
7499
  }
6110
- @if (preset.config.language) {
6111
- <span class="badge badge--lang">{{ preset.config.language }}</span>
6112
- }
6113
7500
  <span class="preset-card__date">{{ formatDate(preset.updatedAt) }}</span>
6114
7501
  </div>
7502
+ @if (expandedPresetId() === preset.id) {
7503
+ <div class="preset-card__details">
7504
+ @if (preset.config.featureFlags.enabled.length > 0 || preset.config.featureFlags.disabled.length > 0) {
7505
+ <div class="details-section">
7506
+ <span class="details-section__title">Feature Flags</span>
7507
+ <div class="details-section__items">
7508
+ @for (id of preset.config.featureFlags.enabled; track id) {
7509
+ <span class="detail-badge detail-badge--on">{{ id }}: ON</span>
7510
+ }
7511
+ @for (id of preset.config.featureFlags.disabled; track id) {
7512
+ <span class="detail-badge detail-badge--off">{{ id }}: OFF</span>
7513
+ }
7514
+ </div>
7515
+ </div>
7516
+ }
7517
+ @if (preset.config.permissions.granted.length > 0 || preset.config.permissions.denied.length > 0) {
7518
+ <div class="details-section">
7519
+ <span class="details-section__title">Permissions</span>
7520
+ <div class="details-section__items">
7521
+ @for (id of preset.config.permissions.granted; track id) {
7522
+ <span class="detail-badge detail-badge--on">{{ id }}: GRANTED</span>
7523
+ }
7524
+ @for (id of preset.config.permissions.denied; track id) {
7525
+ <span class="detail-badge detail-badge--off">{{ id }}: DENIED</span>
7526
+ }
7527
+ </div>
7528
+ </div>
7529
+ }
7530
+ @if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
7531
+ <div class="details-section">
7532
+ <span class="details-section__title">App Features</span>
7533
+ <div class="details-section__items">
7534
+ @for (id of preset.config.appFeatures.enabled; track id) {
7535
+ <span class="detail-badge detail-badge--on">{{ id }}: ON</span>
7536
+ }
7537
+ @for (id of preset.config.appFeatures.disabled; track id) {
7538
+ <span class="detail-badge detail-badge--off">{{ id }}: OFF</span>
7539
+ }
7540
+ </div>
7541
+ </div>
7542
+ }
7543
+ </div>
7544
+ }
6115
7545
  </div>
6116
7546
  }
6117
7547
  </div>
6118
7548
  }
6119
7549
  </div>
6120
7550
  </ndt-toolbar-tool>
6121
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ndt-spacing-md);left:var(--ndt-spacing-md);right:var(--ndt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ndt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ndt-spacing-lg) var(--ndt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ndt-spacing-md)}.delete-view__title{margin:0 0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.delete-view__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);cursor:pointer;font-size:var(--ndt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md);ndt-input{flex:1}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;p{margin:0}.hint{font-size:var(--ndt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px;&:hover{background:var(--ndt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-card{background:var(--ndt-background-secondary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:2px}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:18px}.preset-card__row--badges{padding-left:18px;gap:4px}.preset-card__name{font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ndt-border-primary);color:var(--ndt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ndt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:0;flex-shrink:0}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:4px;color:var(--ndt-text-muted);display:inline-flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out;line-height:0;&:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}ndt-icon,ndt-icon>*,svg{display:block;width:12px!important;height:12px!important}}.preset-card__description{font-size:11px;color:var(--ndt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ndt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm);ndt-input{width:100%}}.form-title{margin:0;font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ndt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ndt-spacing-xs);cursor:pointer;color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ndt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm);margin-top:auto;padding-top:var(--ndt-spacing-sm)}.config-preview{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ndt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ndt-background-primary);color:var(--ndt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ndt-border-primary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ndt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ndt-spacing-md);border:2px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ndt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ndt-spacing-sm);color:var(--ndt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ndt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ndt-spacing-xs);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background:var(--ndt-background-secondary);color:var(--ndt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ndt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ndt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.apply-category{background:var(--ndt-background-secondary);border-radius:var(--ndt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ndt-spacing-xs);padding:6px var(--ndt-spacing-sm);cursor:pointer;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ndt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ndt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ndt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ndt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"] }]
6122
- }], ctorParameters: () => [] });
7551
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ndt-spacing-md);left:var(--ndt-spacing-md);right:var(--ndt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);font-size:var(--ndt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ndt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ndt-spacing-lg) var(--ndt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ndt-spacing-md)}.delete-view__title{margin:0 0 var(--ndt-spacing-sm);font-size:var(--ndt-font-size-md);color:var(--ndt-text-primary)}.delete-view__description{margin:0;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ndt-spacing-sm) var(--ndt-spacing-md);border-radius:var(--ndt-border-radius-small);cursor:pointer;font-size:var(--ndt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-md);ndt-input{flex:1}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;p{margin:0}.hint{font-size:var(--ndt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ndt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ndt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ndt-border-primary);border-radius:4px;&:hover{background:var(--ndt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ndt-border-primary) var(--ndt-background-secondary)}.preset-card{background:var(--ndt-background-secondary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:2px;position:relative}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:36px}.preset-card__row--badges{padding-left:36px;gap:4px}.preset-card__name{font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ndt-border-primary);color:var(--ndt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ndt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:2px;flex-shrink:0}.more-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-muted);display:flex;align-items:center;justify-content:center;width:22px;height:22px;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out,background .15s ease-out;line-height:1;font-size:14px;font-weight:700;position:relative;&:hover{background:var(--ndt-hover-bg);color:var(--ndt-text-primary);opacity:1}}.action-menu{position:absolute;top:28px;right:var(--ndt-spacing-sm);background:var(--ndt-bg-primary);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);box-shadow:var(--ndt-shadow-tooltip);z-index:20;min-width:180px;padding:4px;display:flex;flex-direction:column;gap:2px}.action-menu__item{appearance:none;background:none;border:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-primary);font-size:var(--ndt-font-size-xs);transition:background .15s ease-out;white-space:nowrap;&:hover{background:var(--ndt-hover-bg)}ndt-icon{display:block;width:14px;height:14px;flex-shrink:0;color:var(--ndt-text-muted)}}.action-menu__item--danger{color:#ef4444;ndt-icon{color:#ef4444}&:hover{background:#ef44441a}}.expand-toggle{appearance:none;background:none;border:none;cursor:pointer;padding:0 4px;margin-right:2px;font-size:10px;color:var(--ndt-text-muted);line-height:1;opacity:.6;transition:opacity .15s ease-out;flex-shrink:0;&:hover{opacity:1}}.preset-card__details{padding:var(--ndt-spacing-sm) var(--ndt-spacing-sm) var(--ndt-spacing-xs);margin-top:2px;border-top:1px solid var(--ndt-border-primary);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.details-section__title{font-size:10px;font-weight:600;color:var(--ndt-text-muted);text-transform:uppercase;letter-spacing:.5px}.details-section__items{display:flex;flex-wrap:wrap;gap:4px;margin-top:2px}.detail-badge{font-size:10px;padding:1px 6px;border-radius:var(--ndt-border-radius-small);white-space:nowrap}.detail-badge--on{background:#22c55e1a;color:#22c55e}.detail-badge--off{background:#ef44441a;color:#ef4444}.preset-card__description{font-size:11px;color:var(--ndt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ndt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ndt-spacing-sm);padding:var(--ndt-spacing-sm);ndt-input{width:100%}}.form-title{margin:0;font-size:var(--ndt-font-size-sm);font-weight:600;color:var(--ndt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ndt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ndt-spacing-xs);cursor:pointer;color:var(--ndt-text-primary);font-size:var(--ndt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ndt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ndt-spacing-sm);margin-top:auto;padding-top:var(--ndt-spacing-sm)}.config-preview{background:var(--ndt-background-secondary);padding:var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ndt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ndt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ndt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ndt-background-primary);color:var(--ndt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ndt-border-primary);padding:6px var(--ndt-spacing-sm);border-radius:var(--ndt-border-radius-small);color:var(--ndt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ndt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ndt-spacing-md);border:2px dashed var(--ndt-border-primary);border-radius:var(--ndt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ndt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ndt-spacing-sm);color:var(--ndt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ndt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ndt-spacing-xs);border:1px solid var(--ndt-border-primary);border-radius:var(--ndt-border-radius-small);background:var(--ndt-background-secondary);color:var(--ndt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ndt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ndt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ndt-spacing-xs)}.apply-category{background:var(--ndt-background-secondary);border-radius:var(--ndt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ndt-spacing-xs);padding:6px var(--ndt-spacing-sm);cursor:pointer;font-size:var(--ndt-font-size-sm);color:var(--ndt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ndt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ndt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ndt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ndt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"] }]
7552
+ }], ctorParameters: () => [], propDecorators: { onDocumentClick: [{
7553
+ type: HostListener,
7554
+ args: ['document:click']
7555
+ }] } });
6123
7556
 
6124
7557
  class ToolbarComponent {
6125
7558
  constructor() {
@@ -6131,6 +7564,14 @@ class ToolbarComponent {
6131
7564
  this.keyboardShortcut = fromEvent(window, 'keydown')
6132
7565
  .pipe(filter((event) => event.ctrlKey && event.shiftKey && event.key === 'D'), takeUntilDestroyed(this.destroyRef))
6133
7566
  .subscribe(() => this.toggleDevTools());
7567
+ this.hideShortcut = fromEvent(window, 'keydown')
7568
+ .pipe(filter((event) => (event.metaKey || event.ctrlKey) &&
7569
+ !event.shiftKey &&
7570
+ event.key === '.'), takeUntilDestroyed(this.destroyRef))
7571
+ .subscribe((event) => {
7572
+ event.preventDefault();
7573
+ this.state.toggleCompletelyHidden();
7574
+ });
6134
7575
  this.mouseLeave = fromEvent(document, 'mouseleave')
6135
7576
  .pipe(throttleTime(3000), takeUntilDestroyed(this.destroyRef))
6136
7577
  .subscribe(() => this.onMouseLeave());
@@ -6207,6 +7648,8 @@ class ToolbarComponent {
6207
7648
  --ndt-background-secondary: var(--ndt-bg-primary);
6208
7649
  --ndt-background-hover: var(--ndt-hover-bg);
6209
7650
  --ndt-border-color: var(--ndt-border-primary);
7651
+ --ndt-tooltip-bg: rgb(17, 24, 39);
7652
+ --ndt-tooltip-text: rgb(255, 255, 255);
6210
7653
  --ndt-note-background: rgb(219, 234, 254);
6211
7654
  --ndt-note-border: rgba(37, 99, 235, 0.2);
6212
7655
  --ndt-warning-background: rgb(254, 249, 195);
@@ -6231,20 +7674,23 @@ class ToolbarComponent {
6231
7674
  }
6232
7675
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6233
7676
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarComponent, isStandalone: true, selector: "ndt-toolbar", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
6234
- @if (config().enabled ?? true) {
7677
+ @if ((config().enabled ?? true) && !state.isCompletelyHidden()) {
6235
7678
  <div
6236
7679
  aria-label="Developer tools"
6237
7680
  role="toolbar"
6238
7681
  class="ndt-toolbar"
6239
- [@toolbarState]="state.isVisible() ? 'visible' : 'hidden'"
7682
+ [class.ndt-toolbar--top]="state.position() === 'top'"
7683
+ [class.ndt-toolbar--right]="state.position() === 'right'"
7684
+ [class.ndt-toolbar--bottom]="state.position() === 'bottom'"
7685
+ [class.ndt-toolbar--left]="state.position() === 'left'"
7686
+ [class.ndt-toolbar--visible]="state.isVisible()"
6240
7687
  [attr.data-theme]="state.theme()"
6241
- [class.ndt-toolbar--active]="state.isVisible()"
6242
7688
  (mouseenter)="onMouseEnter()"
6243
7689
  >
6244
7690
  <ndt-home-tool />
6245
7691
  <ng-content />
6246
- @if (config().showLanguageTool ?? false) {
6247
- <ndt-language-tool />
7692
+ @if (config().showI18nTool ?? false) {
7693
+ <ndt-i18n-tool />
6248
7694
  }
6249
7695
  @if (config().showPresetsTool ?? false) {
6250
7696
  <ndt-presets-tool />
@@ -6260,44 +7706,35 @@ class ToolbarComponent {
6260
7706
  }
6261
7707
  </div>
6262
7708
  }
6263
- `, isInline: true, styles: [":host{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\"}.ndt-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: 6px;--ndt-spacing-md: 12px;--ndt-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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);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:visible}.ndt-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: ToolbarHomeToolComponent, selector: "ndt-home-tool", inputs: ["badge"] }, { kind: "component", type: ToolbarLanguageToolComponent, selector: "ndt-language-tool" }, { kind: "component", type: ToolbarFeatureFlagsToolComponent, selector: "ndt-feature-flags-tool" }, { kind: "component", type: ToolbarAppFeaturesToolComponent, selector: "ndt-app-features-tool" }, { kind: "component", type: ToolbarPermissionsToolComponent, selector: "ndt-permissions-tool" }, { kind: "component", type: ToolbarPresetsToolComponent, selector: "ndt-presets-tool" }], animations: [
6264
- trigger('toolbarState', [
6265
- state('hidden', style({
6266
- transform: 'translate(-50%, calc(100% + -1.2rem))',
6267
- })),
6268
- state('visible', style({
6269
- transform: 'translate(-50%, -1rem)',
6270
- })),
6271
- transition('hidden <=> visible', [
6272
- animate('300ms cubic-bezier(0.4, 0, 0.2, 1)'),
6273
- ]),
6274
- ]),
6275
- ], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
7709
+ `, isInline: true, styles: [":host{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\"}.ndt-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: 6px;--ndt-spacing-md: 12px;--ndt-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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);position:fixed;z-index:999999;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);transition:transform .3s cubic-bezier(.4,0,.2,1)}.ndt-toolbar--bottom{bottom:0;left:50%;flex-direction:row;height:30px;padding:0 2px;transform:translate(-50%) translateY(calc(100% - .5rem))}.ndt-toolbar--bottom.ndt-toolbar--visible{transform:translate(-50%) translateY(-10px)}.ndt-toolbar--top{top:0;left:50%;flex-direction:row;height:30px;padding:0 2px;transform:translate(-50%) translateY(calc(-100% + .5rem))}.ndt-toolbar--top.ndt-toolbar--visible{transform:translate(-50%) translateY(10px)}.ndt-toolbar--left{left:0;top:50%;flex-direction:column;width:30px;padding:2px 0;transform:translateY(-50%) translate(calc(-100% + .5rem))}.ndt-toolbar--left.ndt-toolbar--visible{transform:translateY(-50%) translate(10px)}.ndt-toolbar--right{right:0;top:50%;flex-direction:column;width:30px;padding:2px 0;transform:translateY(-50%) translate(calc(100% - .5rem))}.ndt-toolbar--right.ndt-toolbar--visible{transform:translateY(-50%) translate(-10px)}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: ToolbarHomeToolComponent, selector: "ndt-home-tool", inputs: ["badge"] }, { kind: "component", type: ToolbarI18nToolComponent, selector: "ndt-i18n-tool" }, { kind: "component", type: ToolbarFeatureFlagsToolComponent, selector: "ndt-feature-flags-tool" }, { kind: "component", type: ToolbarAppFeaturesToolComponent, selector: "ndt-app-features-tool" }, { kind: "component", type: ToolbarPermissionsToolComponent, selector: "ndt-permissions-tool" }, { kind: "component", type: ToolbarPresetsToolComponent, selector: "ndt-presets-tool" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
6276
7710
  }
6277
7711
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarComponent, decorators: [{
6278
7712
  type: Component,
6279
- args: [{ standalone: true, selector: 'ndt-toolbar', encapsulation: ViewEncapsulation.ShadowDom, imports: [
7713
+ args: [{ standalone: true, selector: 'ndt-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, imports: [
6280
7714
  ToolbarHomeToolComponent,
6281
- ToolbarLanguageToolComponent,
7715
+ ToolbarI18nToolComponent,
6282
7716
  ToolbarFeatureFlagsToolComponent,
6283
7717
  ToolbarAppFeaturesToolComponent,
6284
7718
  ToolbarPermissionsToolComponent,
6285
7719
  ToolbarPresetsToolComponent,
6286
7720
  ], template: `
6287
- @if (config().enabled ?? true) {
7721
+ @if ((config().enabled ?? true) && !state.isCompletelyHidden()) {
6288
7722
  <div
6289
7723
  aria-label="Developer tools"
6290
7724
  role="toolbar"
6291
7725
  class="ndt-toolbar"
6292
- [@toolbarState]="state.isVisible() ? 'visible' : 'hidden'"
7726
+ [class.ndt-toolbar--top]="state.position() === 'top'"
7727
+ [class.ndt-toolbar--right]="state.position() === 'right'"
7728
+ [class.ndt-toolbar--bottom]="state.position() === 'bottom'"
7729
+ [class.ndt-toolbar--left]="state.position() === 'left'"
7730
+ [class.ndt-toolbar--visible]="state.isVisible()"
6293
7731
  [attr.data-theme]="state.theme()"
6294
- [class.ndt-toolbar--active]="state.isVisible()"
6295
7732
  (mouseenter)="onMouseEnter()"
6296
7733
  >
6297
7734
  <ndt-home-tool />
6298
7735
  <ng-content />
6299
- @if (config().showLanguageTool ?? false) {
6300
- <ndt-language-tool />
7736
+ @if (config().showI18nTool ?? false) {
7737
+ <ndt-i18n-tool />
6301
7738
  }
6302
7739
  @if (config().showPresetsTool ?? false) {
6303
7740
  <ndt-presets-tool />
@@ -6313,19 +7750,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6313
7750
  }
6314
7751
  </div>
6315
7752
  }
6316
- `, animations: [
6317
- trigger('toolbarState', [
6318
- state('hidden', style({
6319
- transform: 'translate(-50%, calc(100% + -1.2rem))',
6320
- })),
6321
- state('visible', style({
6322
- transform: 'translate(-50%, -1rem)',
6323
- })),
6324
- transition('hidden <=> visible', [
6325
- animate('300ms cubic-bezier(0.4, 0, 0.2, 1)'),
6326
- ]),
6327
- ]),
6328
- ], styles: [":host{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\"}.ndt-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: 6px;--ndt-spacing-md: 12px;--ndt-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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);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:visible}.ndt-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"] }]
7753
+ `, styles: [":host{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\"}.ndt-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: 6px;--ndt-spacing-md: 12px;--ndt-spacing-lg: 16px;--ndt-window-padding: 16px;--ndt-font-size-xxs: .65rem;--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-tooltip-bg: rgb(17, 24, 39);--ndt-tooltip-text: rgb(255, 255, 255);--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);position:fixed;z-index:999999;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);transition:transform .3s cubic-bezier(.4,0,.2,1)}.ndt-toolbar--bottom{bottom:0;left:50%;flex-direction:row;height:30px;padding:0 2px;transform:translate(-50%) translateY(calc(100% - .5rem))}.ndt-toolbar--bottom.ndt-toolbar--visible{transform:translate(-50%) translateY(-10px)}.ndt-toolbar--top{top:0;left:50%;flex-direction:row;height:30px;padding:0 2px;transform:translate(-50%) translateY(calc(-100% + .5rem))}.ndt-toolbar--top.ndt-toolbar--visible{transform:translate(-50%) translateY(10px)}.ndt-toolbar--left{left:0;top:50%;flex-direction:column;width:30px;padding:2px 0;transform:translateY(-50%) translate(calc(-100% + .5rem))}.ndt-toolbar--left.ndt-toolbar--visible{transform:translateY(-50%) translate(10px)}.ndt-toolbar--right{right:0;top:50%;flex-direction:column;width:30px;padding:2px 0;transform:translateY(-50%) translate(calc(100% - .5rem))}.ndt-toolbar--right.ndt-toolbar--visible{transform:translateY(-50%) translate(-10px)}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"] }]
6329
7754
  }], ctorParameters: () => [] });
6330
7755
 
6331
7756
  class ToolbarFeatureFlagService {
@@ -6372,6 +7797,15 @@ class ToolbarFeatureFlagService {
6372
7797
  getValues() {
6373
7798
  return this.internalService.flags$;
6374
7799
  }
7800
+ /**
7801
+ * Registers a callback to persist a forced flag value back to the actual data source.
7802
+ * When set, an "apply to source" button appears on each forced flag in the toolbar UI.
7803
+ *
7804
+ * @param callback - Async function that receives the flag ID and its forced boolean value
7805
+ */
7806
+ setApplyToSource(callback) {
7807
+ this.internalService.setApplyToSource(callback);
7808
+ }
6375
7809
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarFeatureFlagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6376
7810
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarFeatureFlagService, providedIn: 'root' }); }
6377
7811
  }
@@ -6496,45 +7930,19 @@ class ToolbarPermissionsService {
6496
7930
  getCurrentState() {
6497
7931
  return this.internalService.getCurrentForcedState();
6498
7932
  }
6499
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6500
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, providedIn: 'root' }); }
6501
- }
6502
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, decorators: [{
6503
- type: Injectable,
6504
- args: [{ providedIn: 'root' }]
6505
- }] });
6506
-
6507
- class ToolbarLanguageService {
6508
- constructor() {
6509
- this.internalService = inject(ToolbarInternalLanguageService);
6510
- }
6511
- /**
6512
- * Sets the available languages that will be displayed in the tool on the dev toolbar
6513
- * @param languages The languages to be displayed
6514
- */
6515
- setAvailableOptions(languages) {
6516
- this.internalService.setAppLanguages(languages);
6517
- }
6518
- /**
6519
- * Gets the languages that were forced/modified through the tool on the dev toolbar
6520
- * @returns Observable of forced languages array
6521
- */
6522
- getForcedValues() {
6523
- return this.internalService.getForcedLanguage();
6524
- }
6525
7933
  /**
6526
- * Gets the forced language value.
6527
- * For the language tool, this returns the same as getForcedValues() since
6528
- * only one language can be selected at a time.
6529
- * @returns Observable of forced language array (single item or empty)
7934
+ * Registers a callback to persist a forced permission value back to the actual data source.
7935
+ * When set, an "apply to source" button appears on each forced permission in the toolbar UI.
7936
+ *
7937
+ * @param callback - Async function that receives the permission ID and its forced boolean value
6530
7938
  */
6531
- getValues() {
6532
- return this.internalService.getForcedLanguage();
7939
+ setApplyToSource(callback) {
7940
+ this.internalService.setApplyToSource(callback);
6533
7941
  }
6534
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6535
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLanguageService, providedIn: 'root' }); }
7942
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7943
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, providedIn: 'root' }); }
6536
7944
  }
6537
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarLanguageService, decorators: [{
7945
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPermissionsService, decorators: [{
6538
7946
  type: Injectable,
6539
7947
  args: [{ providedIn: 'root' }]
6540
7948
  }] });
@@ -6719,6 +8127,15 @@ class ToolbarAppFeaturesService {
6719
8127
  getCurrentForcedState() {
6720
8128
  return this.internalService.getCurrentForcedState();
6721
8129
  }
8130
+ /**
8131
+ * Registers a callback to persist a forced app feature value back to the actual data source.
8132
+ * When set, an "apply to source" button appears on each forced feature in the toolbar UI.
8133
+ *
8134
+ * @param callback - Async function that receives the feature ID and its forced boolean value
8135
+ */
8136
+ setApplyToSource(callback) {
8137
+ this.internalService.setApplyToSource(callback);
8138
+ }
6722
8139
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarAppFeaturesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6723
8140
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarAppFeaturesService, providedIn: 'root' }); }
6724
8141
  }
@@ -6791,7 +8208,6 @@ function provideToolbar(config) {
6791
8208
  return makeEnvironmentProviders([
6792
8209
  { provide: TOOLBAR_FEATURE_FLAGS, useClass: ToolbarFeatureFlagService },
6793
8210
  { provide: TOOLBAR_PERMISSIONS, useClass: ToolbarPermissionsService },
6794
- { provide: TOOLBAR_LANGUAGE, useClass: ToolbarLanguageService },
6795
8211
  { provide: TOOLBAR_APP_FEATURES, useClass: ToolbarAppFeaturesService },
6796
8212
  { provide: TOOLBAR_CONFIG, useValue: config ?? {} },
6797
8213
  {
@@ -6801,6 +8217,19 @@ function provideToolbar(config) {
6801
8217
  const appRef = inject(ApplicationRef);
6802
8218
  const injector = inject(EnvironmentInjector);
6803
8219
  const toolbarConfig = inject(TOOLBAR_CONFIG);
8220
+ // Bridge deprecated config callbacks to service-based setApplyToSource
8221
+ if (toolbarConfig.onApplyFeatureFlag) {
8222
+ console.warn('[ngx-dev-toolbar] onApplyFeatureFlag in config is deprecated. Use ToolbarFeatureFlagService.setApplyToSource() instead.');
8223
+ inject(ToolbarInternalFeatureFlagService).setApplyToSource(toolbarConfig.onApplyFeatureFlag);
8224
+ }
8225
+ if (toolbarConfig.onApplyPermission) {
8226
+ console.warn('[ngx-dev-toolbar] onApplyPermission in config is deprecated. Use ToolbarPermissionsService.setApplyToSource() instead.');
8227
+ inject(ToolbarInternalPermissionsService).setApplyToSource(toolbarConfig.onApplyPermission);
8228
+ }
8229
+ if (toolbarConfig.onApplyAppFeature) {
8230
+ console.warn('[ngx-dev-toolbar] onApplyAppFeature in config is deprecated. Use ToolbarAppFeaturesService.setApplyToSource() instead.');
8231
+ inject(ToolbarInternalAppFeaturesService).setApplyToSource(toolbarConfig.onApplyAppFeature);
8232
+ }
6804
8233
  const componentRef = createComponent(ToolbarComponent, {
6805
8234
  environmentInjector: injector,
6806
8235
  });
@@ -6874,6 +8303,108 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
6874
8303
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;flex-direction:column}.step-header{display:flex;align-items:center;gap:var(--ndt-spacing-sm);padding-bottom:var(--ndt-spacing-sm);margin-bottom:var(--ndt-spacing-sm);border-bottom:1px solid var(--ndt-border-primary)}.step-title{font-size:var(--ndt-font-size-md);font-weight:600;color:var(--ndt-text-primary)}\n"] }]
6875
8304
  }] });
6876
8305
 
8306
+ class ToolbarI18nService {
8307
+ constructor() {
8308
+ this.internalService = inject(ToolbarInternalI18nService);
8309
+ }
8310
+ /**
8311
+ * Sets the available locales displayed in the i18n tool
8312
+ */
8313
+ setAvailableOptions(locales) {
8314
+ this.internalService.setAvailableLocales(locales);
8315
+ }
8316
+ /**
8317
+ * Gets the locale that was forced through the i18n tool
8318
+ * @returns Observable of forced locale array (single item or empty)
8319
+ */
8320
+ getForcedValues() {
8321
+ return this.internalService.getForcedLocale();
8322
+ }
8323
+ /**
8324
+ * Gets the forced locale value.
8325
+ * For the i18n tool, this returns the same as getForcedValues() since
8326
+ * only one locale can be selected at a time.
8327
+ */
8328
+ getValues() {
8329
+ return this.internalService.getForcedLocale();
8330
+ }
8331
+ // --- Extended i18n accessors ---
8332
+ /**
8333
+ * Sets the available timezones displayed in the i18n tool.
8334
+ * If not called, defaults to a built-in list of common timezones.
8335
+ */
8336
+ setAvailableTimezones(timezones) {
8337
+ this.internalService.setAvailableTimezones(timezones);
8338
+ }
8339
+ /**
8340
+ * Sets the available currencies displayed in the i18n tool.
8341
+ * If not called, defaults to a built-in list of common currencies.
8342
+ */
8343
+ setAvailableCurrencies(currencies) {
8344
+ this.internalService.setAvailableCurrencies(currencies);
8345
+ }
8346
+ /**
8347
+ * Gets the timezone that was forced through the i18n tool
8348
+ */
8349
+ getForcedTimezone() {
8350
+ return this.internalService.getForcedTimezone();
8351
+ }
8352
+ /**
8353
+ * Gets the currency that was forced through the i18n tool
8354
+ */
8355
+ getForcedCurrency() {
8356
+ return this.internalService.getForcedCurrency();
8357
+ }
8358
+ /**
8359
+ * Gets the unit system that was forced through the i18n tool
8360
+ */
8361
+ getUnitSystem() {
8362
+ return this.internalService.getForcedUnitSystem();
8363
+ }
8364
+ /**
8365
+ * Whether pseudo-localization mode is enabled
8366
+ */
8367
+ isPseudoLocalizationEnabled() {
8368
+ return this.internalService.getPseudoLocEnabled();
8369
+ }
8370
+ /**
8371
+ * Whether RTL mirroring is enabled
8372
+ */
8373
+ isRtlEnabled() {
8374
+ return this.internalService.getRtlEnabled();
8375
+ }
8376
+ /**
8377
+ * Gets the date format that was forced through the i18n tool
8378
+ */
8379
+ getForcedDateFormat() {
8380
+ return this.internalService.getForcedDateFormat();
8381
+ }
8382
+ /**
8383
+ * Gets the first day of week that was forced through the i18n tool
8384
+ */
8385
+ getForcedFirstDayOfWeek() {
8386
+ return this.internalService.getForcedFirstDayOfWeek();
8387
+ }
8388
+ /**
8389
+ * Gets the number format that was forced through the i18n tool
8390
+ */
8391
+ getForcedNumberFormat() {
8392
+ return this.internalService.getForcedNumberFormat();
8393
+ }
8394
+ /**
8395
+ * Configures which sections are visible in the i18n tool panel
8396
+ */
8397
+ configure(config) {
8398
+ this.internalService.setToolConfig(config);
8399
+ }
8400
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarI18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8401
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarI18nService, providedIn: 'root' }); }
8402
+ }
8403
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarI18nService, decorators: [{
8404
+ type: Injectable,
8405
+ args: [{ providedIn: 'root' }]
8406
+ }] });
8407
+
6877
8408
  /**
6878
8409
  * Public service for managing dev toolbar presets.
6879
8410
  * Allows developers to programmatically save, load, and manage presets.
@@ -7060,5 +8591,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
7060
8591
  * Generated bundle index. Do not edit.
7061
8592
  */
7062
8593
 
7063
- export { TOOLBAR_APP_FEATURES, TOOLBAR_CONFIG, TOOLBAR_FEATURE_FLAGS, TOOLBAR_LANGUAGE, TOOLBAR_PERMISSIONS, ToolbarAppFeaturesService, ToolbarAppFeaturesToolComponent, ToolbarButtonComponent, ToolbarCardComponent, ToolbarClickableCardComponent, ToolbarComponent, ToolbarFeatureFlagService, ToolbarIconComponent, ToolbarInputComponent, ToolbarLanguageService, ToolbarLinkButtonComponent, ToolbarListComponent, ToolbarListItemComponent, ToolbarPermissionsService, ToolbarPermissionsToolComponent, ToolbarPresetsService, ToolbarPresetsToolComponent, ToolbarSelectComponent, ToolbarStepDirective, ToolbarStepViewComponent, ToolbarToolComponent, provideToolbar };
8594
+ export { CURRENCY_SYMBOLS, DEFAULT_CURRENCIES, DEFAULT_TIMEZONES, TOOLBAR_APP_FEATURES, TOOLBAR_CONFIG, TOOLBAR_FEATURE_FLAGS, TOOLBAR_PERMISSIONS, TOOLBAR_POSITIONS, ToolbarAppFeaturesService, ToolbarAppFeaturesToolComponent, ToolbarButtonComponent, ToolbarCardComponent, ToolbarClickableCardComponent, ToolbarComponent, ToolbarFeatureFlagService, ToolbarI18nService, ToolbarI18nToolComponent, ToolbarIconButtonComponent, ToolbarIconComponent, ToolbarInputComponent, ToolbarLinkButtonComponent, ToolbarListComponent, ToolbarListItemComponent, ToolbarPermissionsService, ToolbarPermissionsToolComponent, ToolbarPresetsService, ToolbarPresetsToolComponent, ToolbarSelectComponent, ToolbarStepDirective, ToolbarStepViewComponent, ToolbarToolComponent, expandText, formatCurrency, formatCustomDate, formatCustomNumber, formatDate, formatNumber, formatTime, isHorizontalPosition, provideToolbar, pseudoLocalize };
7064
8595
  //# sourceMappingURL=ngx-dev-toolbar.mjs.map