@nexterajs/ui 0.0.1 → 0.0.2

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/fesm2022/nexterajs-ui-core.mjs +189 -5
  2. package/fesm2022/nexterajs-ui-core.mjs.map +1 -1
  3. package/fesm2022/nexterajs-ui-dropdowns.mjs +314 -50
  4. package/fesm2022/nexterajs-ui-dropdowns.mjs.map +1 -1
  5. package/fesm2022/nexterajs-ui-file-uploader.mjs +6 -3
  6. package/fesm2022/nexterajs-ui-file-uploader.mjs.map +1 -1
  7. package/fesm2022/nexterajs-ui-forms.mjs +729 -370
  8. package/fesm2022/nexterajs-ui-forms.mjs.map +1 -1
  9. package/fesm2022/nexterajs-ui-grid.mjs +1188 -208
  10. package/fesm2022/nexterajs-ui-grid.mjs.map +1 -1
  11. package/fesm2022/nexterajs-ui-intl.mjs +15 -5
  12. package/fesm2022/nexterajs-ui-intl.mjs.map +1 -1
  13. package/fesm2022/nexterajs-ui-notify.mjs +351 -0
  14. package/fesm2022/nexterajs-ui-notify.mjs.map +1 -0
  15. package/fesm2022/nexterajs-ui-pivot.mjs +146 -116
  16. package/fesm2022/nexterajs-ui-pivot.mjs.map +1 -1
  17. package/fesm2022/nexterajs-ui-styling.mjs +568 -3
  18. package/fesm2022/nexterajs-ui-styling.mjs.map +1 -1
  19. package/fesm2022/nexterajs-ui-tree-view.mjs +147 -18
  20. package/fesm2022/nexterajs-ui-tree-view.mjs.map +1 -1
  21. package/fesm2022/nexterajs-ui-validation.mjs +247 -92
  22. package/fesm2022/nexterajs-ui-validation.mjs.map +1 -1
  23. package/fesm2022/nexterajs-ui.mjs +1 -0
  24. package/fesm2022/nexterajs-ui.mjs.map +1 -1
  25. package/package.json +5 -1
  26. package/styles/_dropdown.scss +149 -0
  27. package/styles/_editor.scss +23 -4
  28. package/styles/_icons.scss +92 -0
  29. package/styles/_mixins.scss +104 -1
  30. package/styles/_scrollbar.scss +134 -0
  31. package/styles/_toast.scss +243 -0
  32. package/styles/_tokens.scss +48 -0
  33. package/styles/index.scss +4 -0
  34. package/types/nexterajs-ui-core.d.ts +142 -22
  35. package/types/nexterajs-ui-dropdowns.d.ts +145 -27
  36. package/types/nexterajs-ui-file-uploader.d.ts +4 -1
  37. package/types/nexterajs-ui-forms.d.ts +103 -19
  38. package/types/nexterajs-ui-grid.d.ts +445 -57
  39. package/types/nexterajs-ui-notify.d.ts +147 -0
  40. package/types/nexterajs-ui-pivot.d.ts +35 -22
  41. package/types/nexterajs-ui-styling.d.ts +163 -3
  42. package/types/nexterajs-ui-tree-view.d.ts +50 -1
  43. package/types/nexterajs-ui-validation.d.ts +94 -15
  44. package/types/nexterajs-ui.d.ts +1 -0
@@ -0,0 +1,147 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken, EnvironmentProviders } from '@angular/core';
3
+ import { SafeHtml } from '@angular/platform-browser';
4
+
5
+ type NxeToastType = 'success' | 'error' | 'warning' | 'info';
6
+ type NxeToastPosition = 'toast-top-center' | 'toast-bottom-center' | 'toast-top-right' | 'toast-bottom-right' | 'toast-top-left' | 'toast-bottom-left' | 'toast-top-full-width' | 'toast-bottom-full-width';
7
+ /** Per-call options. Anything omitted falls back to the global {@link NxeToastConfig}. */
8
+ interface NxeToastOverride {
9
+ /**
10
+ * Render the message as HTML rather than text.
11
+ *
12
+ * The message is still sanitised. Callers pass server-composed strings here — a list of
13
+ * validation failures joined with `<br>` — so the markup is not author-controlled and must not
14
+ * be trusted, but stripping it entirely would collapse those lists onto one line.
15
+ */
16
+ enableHtml?: boolean;
17
+ /** Dismiss when the body is clicked. The close button works regardless. */
18
+ tapToDismiss?: boolean;
19
+ /** Milliseconds before auto-dismiss. `0` keeps it up until dismissed. */
20
+ timeOut?: number;
21
+ closeButton?: boolean;
22
+ progressBar?: boolean;
23
+ /** Extra classes on the toast element. */
24
+ toastClass?: string;
25
+ titleClass?: string;
26
+ messageClass?: string;
27
+ }
28
+ interface NxeToastConfig extends NxeToastOverride {
29
+ /** Which corner or edge the stack is anchored to. */
30
+ positionClass?: NxeToastPosition;
31
+ /**
32
+ * Put the newest toast at the top of the stack.
33
+ *
34
+ * Defaults to true, matching the library this replaces. A naive appending list reverses it —
35
+ * visibly, and without any test failing.
36
+ */
37
+ newestOnTop?: boolean;
38
+ /** Drop a toast whose type, title and message match one already showing. */
39
+ preventDuplicates?: boolean;
40
+ /** Cap the stack; 0 means no cap. Older toasts are dismissed first. */
41
+ maxOpened?: number;
42
+ }
43
+ declare const NXE_TOAST_DEFAULTS: Required<Pick<NxeToastConfig, 'positionClass' | 'timeOut' | 'closeButton' | 'progressBar' | 'tapToDismiss' | 'enableHtml' | 'newestOnTop' | 'preventDuplicates' | 'maxOpened'>>;
44
+ declare const NXE_TOAST_CONFIG: InjectionToken<NxeToastConfig>;
45
+
46
+ /**
47
+ * One toast. Rendered by {@link NxeToastService} into its container; not used directly.
48
+ *
49
+ * **The element order is load-bearing.** The close button comes first and is floated right, which
50
+ * is how the library this replaces positioned it — move it after the title and it drops below the
51
+ * text instead of sitting in the corner. Likewise the host carries the classes rather than an
52
+ * inner wrapper, because the shipped stylesheet targets `.nxe-toast-container .nxe-toast`
53
+ * directly and an extra element between them changes what `width` and `margin` apply to.
54
+ *
55
+ * Styles are global (`@nexterajs/ui/styles/_toast.scss`), not encapsulated, so an application's
56
+ * existing overrides keep winning on specificity exactly as they did before.
57
+ *
58
+ * Accessibility, which the original had none of:
59
+ * - `error` and `warning` announce as `alert` (assertive — the user's own action caused it).
60
+ * `success` and `info` announce as `status` (polite).
61
+ * - Focus is never taken. A validation toast typically appears mid-keystroke, and moving focus
62
+ * would pull the caret out of the field being corrected.
63
+ * - The close button is a real `<button>` with a label, reachable by keyboard.
64
+ */
65
+ declare class NxeToastComponent {
66
+ private readonly sanitizer;
67
+ readonly type: _angular_core.InputSignal<NxeToastType>;
68
+ readonly title: _angular_core.InputSignal<string>;
69
+ readonly message: _angular_core.InputSignal<string>;
70
+ readonly enableHtml: _angular_core.InputSignal<boolean>;
71
+ readonly tapToDismiss: _angular_core.InputSignal<boolean>;
72
+ readonly closeButton: _angular_core.InputSignal<boolean>;
73
+ readonly progressBar: _angular_core.InputSignal<boolean>;
74
+ readonly toastClass: _angular_core.InputSignal<string>;
75
+ readonly titleClass: _angular_core.InputSignal<string>;
76
+ readonly messageClass: _angular_core.InputSignal<string>;
77
+ readonly dismissed: _angular_core.OutputEmitterRef<void>;
78
+ /** Pre-enter state: the service clears it a frame later so the opacity transition runs. */
79
+ readonly entering: _angular_core.WritableSignal<boolean>;
80
+ /** Set while the leave transition plays; the service removes the view once it finishes. */
81
+ readonly dismissing: _angular_core.WritableSignal<boolean>;
82
+ readonly progressWidth: _angular_core.WritableSignal<number>;
83
+ protected readonly assertive: _angular_core.Signal<boolean>;
84
+ protected readonly hostClass: _angular_core.Signal<string>;
85
+ /**
86
+ * Sanitised HTML for the message.
87
+ *
88
+ * Callers pass server-composed strings here — validation failures joined with `<br>` — so this
89
+ * is data, not markup the application authored. `sanitize` drops anything executable and keeps
90
+ * the line breaks the lists depend on.
91
+ */
92
+ protected readonly safeMessage: _angular_core.Signal<SafeHtml>;
93
+ protected onBodyClick(): void;
94
+ protected onCloseClick(event: Event): void;
95
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeToastComponent, never>;
96
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeToastComponent, "nxe-toast", never, { "type": { "alias": "type"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "message": { "alias": "message"; "required": false; "isSignal": true; }; "enableHtml": { "alias": "enableHtml"; "required": false; "isSignal": true; }; "tapToDismiss": { "alias": "tapToDismiss"; "required": false; "isSignal": true; }; "closeButton": { "alias": "closeButton"; "required": false; "isSignal": true; }; "progressBar": { "alias": "progressBar"; "required": false; "isSignal": true; }; "toastClass": { "alias": "toastClass"; "required": false; "isSignal": true; }; "titleClass": { "alias": "titleClass"; "required": false; "isSignal": true; }; "messageClass": { "alias": "messageClass"; "required": false; "isSignal": true; }; }, { "dismissed": "dismissed"; }, never, never, true, never>;
97
+ }
98
+
99
+ /** Handle on a shown toast. `dismiss()` is safe to call more than once. */
100
+ interface NxeToastRef {
101
+ dismiss(): void;
102
+ readonly type: NxeToastType;
103
+ readonly title: string | null;
104
+ readonly message: string | null;
105
+ }
106
+ /**
107
+ * Configure the toast stack once, at bootstrap.
108
+ *
109
+ * ```ts
110
+ * providers: [provideNxeToast({ positionClass: 'toast-top-center' })]
111
+ * ```
112
+ */
113
+ declare function provideNxeToast(config?: NxeToastConfig): EnvironmentProviders;
114
+ /**
115
+ * Shows toasts.
116
+ *
117
+ * **The container is deliberately not a CDK overlay.** A CDK overlay pane lands in the same
118
+ * `.cdk-overlay-container` as the application's dialogs, which makes paint order creation order —
119
+ * so a toast raised right after a dialog closes can end up behind the next dialog that opens.
120
+ * Callers do exactly that. A dedicated container with its own stacking context keeps toasts above
121
+ * dialogs regardless of the order things were created in.
122
+ */
123
+ declare class NxeToastService {
124
+ private readonly appRef;
125
+ private readonly injector;
126
+ private readonly document;
127
+ private readonly userConfig;
128
+ private readonly config;
129
+ private container;
130
+ private readonly active;
131
+ success(message?: string | null, title?: string | null, override?: NxeToastOverride): NxeToastRef;
132
+ error(message?: string | null, title?: string | null, override?: NxeToastOverride): NxeToastRef;
133
+ warning(message?: string | null, title?: string | null, override?: NxeToastOverride): NxeToastRef;
134
+ info(message?: string | null, title?: string | null, override?: NxeToastOverride): NxeToastRef;
135
+ /** Dismiss everything currently showing. */
136
+ clear(): void;
137
+ show(type: NxeToastType, message?: string | null, title?: string | null, override?: NxeToastOverride): NxeToastRef;
138
+ /** Shrink the progress bar across the toast's lifetime, the way the original drove it. */
139
+ private runProgress;
140
+ private remove;
141
+ private ensureContainer;
142
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeToastService, never>;
143
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeToastService>;
144
+ }
145
+
146
+ export { NXE_TOAST_CONFIG, NXE_TOAST_DEFAULTS, NxeToastComponent, NxeToastService, provideNxeToast };
147
+ export type { NxeToastConfig, NxeToastOverride, NxeToastPosition, NxeToastRef, NxeToastType };
@@ -1,4 +1,5 @@
1
1
  import { NxeColumnFormat, NxeGridInstance, NxeExcelExportOptions, NxeScrollingComponent, NxeHeaderFilterModel } from '@nexterajs/ui/grid';
2
+ import { NxeNumberSeparators } from '@nexterajs/ui/intl';
2
3
  import * as _angular_core from '@angular/core';
3
4
  import { OnDestroy, TemplateRef, Signal, EventEmitter } from '@angular/core';
4
5
 
@@ -142,6 +143,11 @@ interface NxePivotDataSourceOptions {
142
143
  store?: any[];
143
144
  retrieveFields?: boolean;
144
145
  dataFieldArea?: 'row' | 'column';
146
+ /**
147
+ * Locale separators for rendered cell text. Supplied by the pivot component from
148
+ * `NXE_NUMBER_SEPARATORS`; omitted means en-US, which is what the engine always did.
149
+ */
150
+ separators?: NxeNumberSeparators;
145
151
  }
146
152
  /**
147
153
  * A rendered column leaf = (column-path × data-field). Since P2-C2 the column axis is N-level:
@@ -177,7 +183,7 @@ interface NxePivotHeaderCell {
177
183
  /** Set when > 1: a 'T'/'GT'/collapsed-parent cell filling the remaining value rows (dx
178
184
  * `depthSize`, m_data_controller). */
179
185
  rowspan?: number;
180
- /** True on "{value} Total" cells (dx `dx-row-total dx-total`, on both axes). */
186
+ /** True on "{value} Total" cells (dx `dx-row-total nxe-total`, on both axes). */
181
187
  isTotal?: boolean;
182
188
  /** True when the cell carries an expand/collapse chevron (dx `dx-expand-icon-container`). */
183
189
  expandable?: boolean;
@@ -206,7 +212,7 @@ interface NxePivotRowHeaderCell {
206
212
  /** True when the cell carries an expand/collapse chevron (a parent node's label). */
207
213
  expandable: boolean;
208
214
  expanded: boolean;
209
- /** True for a "{value} Total" label cell (dx `dx-row-total dx-total`). */
215
+ /** True for a "{value} Total" label cell (dx `dx-row-total nxe-total`). */
210
216
  isTotal: boolean;
211
217
  pathKey: string;
212
218
  }
@@ -771,7 +777,7 @@ interface NxePivotPanelChip {
771
777
  caption: string;
772
778
  sortOrder: 'asc' | 'desc';
773
779
  sortable: boolean;
774
- /** P3-C4: the chip renders the `.dx-header-filter` funnel (never on data-area chips). */
780
+ /** P3-C4: the chip renders the `.nxe-header-filter` funnel (never on data-area chips). */
775
781
  filterable: boolean;
776
782
  /** A filter is applied (`filterValues` non-empty) — full-alpha funnel, no `-empty` class. */
777
783
  filterActive: boolean;
@@ -825,9 +831,9 @@ declare class NxePivotFieldPanelComponent implements OnDestroy {
825
831
  * header-filter funnel. Same per-field precedence as `allowSorting`. */
826
832
  readonly allowFiltering: _angular_core.InputSignal<boolean>;
827
833
  /** Widget `showBorders`: the panel bands sit INSIDE the border box (dx draws the outer
828
- * border around the filter/chip bands — `.dx-pivotgrid-border .dx-filter-header` et al). */
834
+ * border around the filter/chip bands — `.nxe-pivotgrid-border .nxe-filter-header` et al). */
829
835
  readonly showBorders: _angular_core.InputSignal<boolean>;
830
- /** P3-C3: the pivot's `.dx-pivotgrid-toolbar` template (field-chooser button) — rendered
836
+ /** P3-C3: the pivot's `.nxe-pivotgrid-toolbar` template (field-chooser button) — rendered
831
837
  * where dx prepends its toolbar container (m_widget.js `_renderDescriptionArea`). */
832
838
  readonly toolbarTemplate: _angular_core.InputSignal<TemplateRef<unknown>>;
833
839
  /** Which panel band hosts the toolbar (the pivot resolves dx's placement branches):
@@ -846,7 +852,7 @@ declare class NxePivotFieldPanelComponent implements OnDestroy {
846
852
  /** A chip's funnel was clicked — the pivot opens the header-filter panel (P3-C4). */
847
853
  readonly filterOpen: _angular_core.OutputEmitterRef<NxePivotFilterOpenEvent>;
848
854
  /** The ROW fields area — NxePivotGridComponent outlets this into its corner cell (dx hosts
849
- * the row chips inside `.dx-area-description-cell`, never in a band of their own). */
855
+ * the row chips inside `.nxe-area-description-cell`, never in a band of their own). */
850
856
  readonly rowAreaTemplate: _angular_core.Signal<TemplateRef<unknown>>;
851
857
  private readonly elementRef;
852
858
  private readonly zone;
@@ -867,12 +873,12 @@ declare class NxePivotFieldPanelComponent implements OnDestroy {
867
873
  private dragRoot;
868
874
  /**
869
875
  * Drop zones. For filter/data/column the fields-area element is both hit rect and highlight
870
- * target; for ROW the enclosing corner cell (`th.dx-area-description-cell`) is — dx's row
876
+ * target; for ROW the enclosing corner cell (`th.nxe-area-description-cell`) is — dx's row
871
877
  * area IS the corner, so a drop anywhere on it must land in rows, not read as "outside".
872
878
  */
873
879
  private dropZones;
874
880
  private trackPointer;
875
- /** dx `.dx-position-indicator`: a 2px gray bar between chips, inside the (positioned) area. */
881
+ /** dx `.nxe-position-indicator`: a 2px gray bar between chips, inside the (positioned) area. */
876
882
  private placeIndicator;
877
883
  private completeDrop;
878
884
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxePivotFieldPanelComponent, never>;
@@ -880,7 +886,7 @@ declare class NxePivotFieldPanelComponent implements OnDestroy {
880
886
  }
881
887
 
882
888
  /** `dxo-field-chooser` — LIVE since P3-C3: with `enabled` the pivot renders the
883
- * `.dx-pivotgrid-field-chooser-button` toolbar button and opens the chooser popup
889
+ * `.nxe-pivotgrid-field-chooser-button` toolbar button and opens the chooser popup
884
890
  * (nxe-pivot-field-chooser) in a CDK overlay. Defaults are dxPivotGrid's `fieldChooser`
885
891
  * defaults (m_widget.js): enabled true, width/height 600, allowSearch false,
886
892
  * applyChangesMode 'instantly' (no OK/Cancel — changes hit the pivot live). */
@@ -895,7 +901,7 @@ declare class NxeFieldChooserComponent {
895
901
  declare class NxePivotGridComponent implements OnDestroy {
896
902
  readonly dataSource: _angular_core.InputSignal<NxePivotDataSourceOptions | NxePivotDataSource>;
897
903
  /** dx `allowFiltering` (default false) — LIVE since P3-C4: filterable dimension chips
898
- * (panel AND chooser) render the `.dx-header-filter` funnel and open the shared
904
+ * (panel AND chooser) render the `.nxe-header-filter` funnel and open the shared
899
905
  * header-filter panel; per-field `field.allowFiltering` overrides the widget flag
900
906
  * (dx m_widget `_updateCalculatedOptions`). */
901
907
  readonly allowFiltering: _angular_core.InputSignal<boolean>;
@@ -908,7 +914,7 @@ declare class NxePivotGridComponent implements OnDestroy {
908
914
  * `expandAll()`/`collapseAll()` work regardless, exactly as dx's data-source methods do. */
909
915
  readonly allowExpandAll: _angular_core.InputSignal<boolean>;
910
916
  readonly showBorders: _angular_core.InputSignal<boolean>;
911
- /** dx default TRUE (m_widget.js defaultOptions): `dx-word-wrap` on the table lets header
917
+ /** dx default TRUE (m_widget.js defaultOptions): `nxe-word-wrap` on the table lets header
912
918
  * cells wrap; data cells stay nowrap either way (dx.light's direct td rule). */
913
919
  readonly wordWrapEnabled: _angular_core.InputSignal<boolean>;
914
920
  readonly rowHeaderLayout: _angular_core.InputSignal<NxePivotRowHeaderLayout>;
@@ -927,7 +933,7 @@ declare class NxePivotGridComponent implements OnDestroy {
927
933
  * Left undefined the engine falls back to the dataSource options' own `dataFieldArea`. */
928
934
  readonly dataFieldArea: _angular_core.InputSignal<"row" | "column">;
929
935
  /** dx `allowSorting` (default false, P3-C2): field-panel chips toggle their field's
930
- * sortOrder on click and carry the `.dx-sort` arrow in `.dx-column-indicators`. */
936
+ * sortOrder on click and carry the `.nxe-sort` arrow in `.nxe-column-indicators`. */
931
937
  readonly allowSorting: _angular_core.InputSignal<boolean>;
932
938
  /**
933
939
  * Facade `option(name, value)` writes land here and WIN over the input bindings — the dx
@@ -983,17 +989,18 @@ declare class NxePivotGridComponent implements OnDestroy {
983
989
  /** The rendered panel component — source of the corner-hosted row-area template. */
984
990
  private readonly panelCmp;
985
991
  /** The ROW fields area, outletted into the corner cell (dx hosts the row chips inside
986
- * `.dx-area-description-cell` — oracle §c; the corner shows NO caption text then). */
992
+ * `.nxe-area-description-cell` — oracle §c; the corner shows NO caption text then). */
987
993
  protected readonly panelRowAreaTpl: Signal<_angular_core.TemplateRef<unknown>>;
988
- /** The `.dx-pivotgrid-field-chooser-button` renders only when an `nxe-field-chooser` is
994
+ /** The `.nxe-pivotgrid-field-chooser-button` renders only when an `nxe-field-chooser` is
989
995
  * projected with `enabled` not false (the DA page passes [enabled]="true"). */
990
996
  protected readonly chooserEnabled: Signal<boolean>;
991
997
  /** dx toolbar placement (m_widget.js `_renderDescriptionArea`, verbatim branch order):
992
- * (a) panel visible && showFilterFields -> the `.dx-filter-header` band;
993
- * (b) panel visible && (showDataFields || showColumnFields) -> the `.dx-column-header`
998
+ * (a) panel visible && showFilterFields -> the `.nxe-filter-header` band;
999
+ * (b) panel visible && (showDataFields || showColumnFields) -> the `.nxe-column-header`
994
1000
  * band (dx-compat's dormant column-header button rules go live);
995
- * (c) else -> the cross-tab corner `.dx-area-description-cell`, where the
996
- * transparent-until-hover button rules (dx-compat ~1113-1118) apply. */
1001
+ * (c) else -> the cross-tab corner `.nxe-area-description-cell`, where the button is
1002
+ * transparent until hover and the corner drops its caption (the library's own rules,
1003
+ * nxe-pivot-grid.component.scss — dx.light's description-cell toolbar rules). */
997
1004
  protected readonly chooserToolbarHost: Signal<"column" | "filter" | "corner">;
998
1005
  /** The panel-hosted placements, bound into the panel's `toolbarArea` input. */
999
1006
  protected readonly panelToolbarArea: Signal<"column" | "filter">;
@@ -1002,6 +1009,8 @@ declare class NxePivotGridComponent implements OnDestroy {
1002
1009
  private readonly overlay;
1003
1010
  private readonly viewContainerRef;
1004
1011
  private readonly elementRef;
1012
+ /** Locale separators for every number the pivot renders; threaded into the data source. */
1013
+ private readonly separators;
1005
1014
  /** Bumped by `getDataSource().reload()` to force a re-aggregate. */
1006
1015
  private readonly reloadTick;
1007
1016
  /**
@@ -1086,7 +1095,7 @@ declare class NxePivotGridComponent implements OnDestroy {
1086
1095
  protected readonly totalColCount: Signal<number>;
1087
1096
  protected onPivotScroll(event: Event): void;
1088
1097
  /**
1089
- * dx `.dx-pivotgrid-nodata` (gridCoreUtils.renderNoDataText): shown when the data source
1098
+ * dx `.nxe-pivotgrid-nodata` (gridCoreUtils.renderNoDataText): shown when the data source
1090
1099
  * `isEmpty()` — no VISIBLE data field or nothing aggregated (empty/fully-filtered store);
1091
1100
  * text `texts.noData` (dx default "No data"). The reloadTick read re-checks after an
1092
1101
  * in-place instance reload.
@@ -1311,6 +1320,10 @@ declare class NxePivotGridComponent implements OnDestroy {
1311
1320
 
1312
1321
  declare class NxePivotFieldChipComponent {
1313
1322
  readonly chip: _angular_core.InputSignal<NxePivotPanelChip>;
1323
+ /** dx showColumnLines for this chip's surface: true in the field chooser and the panel's
1324
+ * ROW area — the indicators come FIRST and float right; false (panel column / filter /
1325
+ * data areas) — they follow the caption inline. */
1326
+ readonly floatIndicators: _angular_core.InputSignal<boolean>;
1314
1327
  /** Raw pointerdown — the host decides whether a drag gesture may begin. */
1315
1328
  readonly chipPointerDown: _angular_core.OutputEmitterRef<PointerEvent>;
1316
1329
  /** Chip click (the host consults its gesture's click suppression before sorting). */
@@ -1319,7 +1332,7 @@ declare class NxePivotFieldChipComponent {
1319
1332
  readonly chipFilterClick: _angular_core.OutputEmitterRef<MouseEvent>;
1320
1333
  protected onFunnelClick(event: MouseEvent): void;
1321
1334
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxePivotFieldChipComponent, never>;
1322
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxePivotFieldChipComponent, "div[nxePivotFieldChip]", never, { "chip": { "alias": "chip"; "required": true; "isSignal": true; }; }, { "chipPointerDown": "chipPointerDown"; "chipClick": "chipClick"; "chipFilterClick": "chipFilterClick"; }, never, never, true, never>;
1335
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxePivotFieldChipComponent, "div[nxePivotFieldChip]", never, { "chip": { "alias": "chip"; "required": true; "isSignal": true; }; "floatIndicators": { "alias": "floatIndicators"; "required": false; "isSignal": true; }; }, { "chipPointerDown": "chipPointerDown"; "chipClick": "chipClick"; "chipFilterClick": "chipFilterClick"; }, never, never, true, never>;
1323
1336
  }
1324
1337
 
1325
1338
  /** One All-Fields tree row (the fixture's flat leaf list — local fields have no groups). */
@@ -1374,7 +1387,7 @@ declare class NxePivotFieldChooserComponent implements OnDestroy {
1374
1387
  protected readonly searchText: _angular_core.WritableSignal<string>;
1375
1388
  private readonly elementRef;
1376
1389
  private readonly zone;
1377
- /** Popup box size — dx puts fieldChooser.width/height on `.dx-overlay-content` (600 dflt). */
1390
+ /** Popup box size — dx puts fieldChooser.width/height on `.nxe-overlay-content` (600 dflt). */
1378
1391
  protected readonly boxWidth: Signal<string>;
1379
1392
  protected readonly boxHeight: Signal<string>;
1380
1393
  /**
@@ -1403,7 +1416,7 @@ declare class NxePivotFieldChooserComponent implements OnDestroy {
1403
1416
  */
1404
1417
  private allowedIn;
1405
1418
  private trackPointer;
1406
- /** dx `.dx-position-indicator-vertical`: a 2px bar between the stacked chips. */
1419
+ /** dx `.nxe-position-indicator-vertical`: a 2px bar between the stacked chips. */
1407
1420
  private placeIndicator;
1408
1421
  private completeDrop;
1409
1422
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxePivotFieldChooserComponent, never>;
@@ -1,10 +1,12 @@
1
1
  import { OverlayRef } from '@angular/cdk/overlay';
2
2
  import { Subscription } from 'rxjs';
3
+ import * as i0 from '@angular/core';
4
+ import { EnvironmentProviders, OnInit, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
3
5
 
4
6
  /**
5
7
  * Marker class carried by every nxe surface — component hosts and CDK overlay panes alike.
6
8
  *
7
- * It is the nxe counterpart of DevExtreme's `.dx-widget` base and is what gives a surface its
9
+ * It is the nxe counterpart of DevExtreme's `.nxe-widget` base and is what gives a surface its
8
10
  * font family/size/weight/line-height (see styling/_widget.scss).
9
11
  *
10
12
  * It matters most on overlays: a CDK pane is appended to `<body>`, so a portaled dropdown
@@ -30,11 +32,169 @@ declare function nxePane(...extra: (string | null | undefined)[]): string[];
30
32
  *
31
33
  * DevExtreme drew dropdowns flush against the editor — no border on the shared edge — and moved
32
34
  * that seam to the other side when the popup flipped up
33
- * (`.dx-overlay-content.dx-dropdowneditor-overlay-flipped { border-top-width:1px; border-bottom-width:0 }`).
35
+ * (`.nxe-overlay-content.nxe-dropdowneditor-overlay-flipped { border-top-width:1px; border-bottom-width:0 }`).
34
36
  * CDK does not emit any equivalent hook, so panels need this to reproduce it.
35
37
  *
36
38
  * Returns the subscription; callers dispose it with the overlay.
37
39
  */
38
40
  declare function trackPaneFlip(overlayRef: OverlayRef): Subscription | undefined;
39
41
 
40
- export { NXE_PANE_FLIPPED_CLASS, NXE_WIDGET_CLASS, nxePane, trackPaneFlip };
42
+ /**
43
+ * Migration aid: re-emit the old `dx-*` class names alongside the library's `nxe-*` ones.
44
+ *
45
+ * The library dropped the `dx-` prefix from its DOM. Applications that still style themselves
46
+ * with rules like `.dx-datagrid .dx-row > td { padding: 4px }` would silently lose that styling,
47
+ * and no stylesheet can fix it: CSS cannot alias a class, so a rule keyed on `.dx-datagrid` will
48
+ * never match an element that only says `nxe-datagrid`. The class has to be back on the element.
49
+ *
50
+ * So this mirrors them at runtime. Provide it once and unmigrated stylesheets keep working
51
+ * unchanged; provide nothing and the library costs nothing, which is the point of it being
52
+ * opt-in. `tools/dx-compat/rewrite-styles.mjs` rewrites an application's own stylesheets when it
53
+ * is ready to drop the flag — this is a bridge, not a destination.
54
+ *
55
+ * ```ts
56
+ * bootstrapApplication(AppComponent, { providers: [provideNxeDxCompat()] });
57
+ * ```
58
+ */
59
+ declare class NxeDxCompatService {
60
+ private readonly document;
61
+ private readonly ngZone;
62
+ private observer?;
63
+ /** Our own writes retrigger the observer; this stops it chasing its own tail. */
64
+ private mirroring;
65
+ start(): void;
66
+ stop(): void;
67
+ private onMutations;
68
+ private mirrorSubtree;
69
+ /** Keep `dx-x` present exactly while `nxe-x` is, so a removed state class is removed here too. */
70
+ private mirrorElement;
71
+ static ɵfac: i0.ɵɵFactoryDeclaration<NxeDxCompatService, never>;
72
+ static ɵprov: i0.ɵɵInjectableDeclaration<NxeDxCompatService>;
73
+ }
74
+ /**
75
+ * Opt into the `dx-*` compatibility classes. See {@link NxeDxCompatService} for why this is a
76
+ * runtime mirror rather than a stylesheet.
77
+ */
78
+ declare function provideNxeDxCompat(): EnvironmentProviders;
79
+
80
+ /** Where the scroll position sits on each axis: -1 at the start, 1 at the end, 0 in between. */
81
+ interface NxeScrollbarPosition {
82
+ x: number;
83
+ y: number;
84
+ }
85
+ /** Scroll geometry of the host element. */
86
+ interface NxeScrollbarGeometry {
87
+ x: number;
88
+ y: number;
89
+ w: number;
90
+ h: number;
91
+ }
92
+ /**
93
+ * The options that map onto this implementation.
94
+ *
95
+ * `wheelPropagation` is accepted and ignored: it existed because the original took the wheel over
96
+ * from the browser and had to decide when to hand it back. Scrolling here is native, so the
97
+ * browser makes that decision itself — which is what the option was trying to restore.
98
+ */
99
+ interface NxeScrollbarOptions {
100
+ suppressScrollX?: boolean;
101
+ suppressScrollY?: boolean;
102
+ wheelPropagation?: boolean;
103
+ /** Rail is hidden below this content overflow, in px. Matches the original's default. */
104
+ minScrollbarLength?: number;
105
+ maxScrollbarLength?: number;
106
+ }
107
+ /**
108
+ * `[nxeScrollbar]` — a container with custom overlay scrollbars.
109
+ *
110
+ * This replaces a Perfect Scrollbar wrapper, and reproduces its DOM and its rendering exactly:
111
+ * two absolutely-positioned rails, each holding a thumb, sized and offset from the host's own
112
+ * scroll geometry. The stylesheet (`@nexterajs/ui/styles/_scrollbar.scss`) is a value-for-value
113
+ * port, so applications that restyle the rails keep their appearance unchanged.
114
+ *
115
+ * **What is different, deliberately:** the original set `overflow: hidden` and reimplemented
116
+ * wheel, touch, keyboard and momentum scrolling in JavaScript. Here the element scrolls natively
117
+ * and only the native scrollbar is hidden — the rails are painted from the `scroll` event. That is
118
+ * less code and better behaviour on touch and trackpads, and it is invisible: a hidden native
119
+ * scrollbar takes no layout width, exactly like the overlay rails it replaces.
120
+ *
121
+ * The host carries `nxe-scrollbar` while enabled, which is the marker callers branch on.
122
+ */
123
+ declare class NxeScrollbarDirective implements OnInit, OnChanges, OnDestroy {
124
+ private readonly elementRef;
125
+ private readonly zone;
126
+ private readonly destroyRef;
127
+ nxeScrollbar: boolean;
128
+ nxeScrollbarOptions: NxeScrollbarOptions | null;
129
+ private options;
130
+ private animation;
131
+ private railX?;
132
+ private railY?;
133
+ private thumbX?;
134
+ private thumbY?;
135
+ private resizeObserver?;
136
+ private mutationObserver?;
137
+ private scrollingXTimer;
138
+ private scrollingYTimer;
139
+ private teardown;
140
+ private initialised;
141
+ get element(): HTMLElement;
142
+ ngOnInit(): void;
143
+ ngOnChanges(changes: SimpleChanges): void;
144
+ ngOnDestroy(): void;
145
+ isEnabled(): boolean;
146
+ /**
147
+ * Recompute rail and thumb geometry. Call after changing content the directive cannot observe.
148
+ *
149
+ * This reproduces the original's arithmetic exactly, down to how it rounds — the requirement was
150
+ * no visual difference, and each of these is worth a pixel:
151
+ * - the container is measured from `getBoundingClientRect()` rounded, not from `clientHeight`;
152
+ * - sizes and offsets are **truncated** (the original ran them through `parseInt`), not rounded;
153
+ * - `scrollTop` is floored before it is used;
154
+ * - the thumb offset is clamped so it cannot overhang the end of the rail.
155
+ */
156
+ update(): void;
157
+ /** Kept for parity with the wrapper this replaces; teardown also happens in ngOnDestroy. */
158
+ destroy(): void;
159
+ isScrollableX(): boolean;
160
+ isScrollableY(): boolean;
161
+ geometry(prefix?: 'scroll' | 'client' | 'offset'): NxeScrollbarGeometry;
162
+ /** -1 at the start of an axis, 1 at its end, 0 anywhere between. */
163
+ position(absolute?: boolean): NxeScrollbarPosition;
164
+ scrollTo(x: number, y?: number, speed?: number): void;
165
+ scrollToX(x: number, speed?: number): void;
166
+ scrollToY(y: number, speed?: number): void;
167
+ scrollToTop(offset?: number, speed?: number): void;
168
+ scrollToBottom(offset?: number, speed?: number): void;
169
+ scrollToLeft(offset?: number, speed?: number): void;
170
+ scrollToRight(offset?: number, speed?: number): void;
171
+ /**
172
+ * Bring the first descendant matching `selector` into view.
173
+ *
174
+ * `ignoreVisible` skips the scroll when the target already sits inside the viewport less the
175
+ * offset, so an item that is merely low on screen is not yanked to the top on every change.
176
+ */
177
+ scrollToElement(selector: string, offset?: number, ignoreVisible?: boolean, speed?: number): void;
178
+ /**
179
+ * Move one axis to `value`, easing over `speed` ms when one is given.
180
+ *
181
+ * The easing bails as soon as the position stops matching what it last wrote, so a user who
182
+ * grabs the wheel mid-flight takes over instead of fighting the animation.
183
+ */
184
+ animateScrolling(axis: 'scrollTop' | 'scrollLeft', value: number, speed?: number): void;
185
+ private init;
186
+ private buildRail;
187
+ private onScroll;
188
+ private bindThumbDrag;
189
+ /** Only the configured bounds, and only when set — the same shape the original's clamp had. */
190
+ private clampThumb;
191
+ private on;
192
+ private dispose;
193
+ private cancelAnimation;
194
+ static ɵfac: i0.ɵɵFactoryDeclaration<NxeScrollbarDirective, never>;
195
+ static ɵdir: i0.ɵɵDirectiveDeclaration<NxeScrollbarDirective, "[nxeScrollbar]", ["nxeScrollbar"], { "nxeScrollbar": { "alias": "nxeScrollbar"; "required": false; }; "nxeScrollbarOptions": { "alias": "nxeScrollbarOptions"; "required": false; }; }, {}, never, never, true, never>;
196
+ static ngAcceptInputType_nxeScrollbar: boolean | string | null | undefined;
197
+ }
198
+
199
+ export { NXE_PANE_FLIPPED_CLASS, NXE_WIDGET_CLASS, NxeDxCompatService, NxeScrollbarDirective, nxePane, provideNxeDxCompat, trackPaneFlip };
200
+ export type { NxeScrollbarGeometry, NxeScrollbarOptions, NxeScrollbarPosition };
@@ -10,6 +10,12 @@ interface NxeTreeNode {
10
10
  hasChildren: boolean;
11
11
  level: number;
12
12
  }
13
+ /** A visible node with the sibling position a flattened tree has to state explicitly. */
14
+ interface NxeTreeRow {
15
+ node: NxeTreeNode;
16
+ posInSet: number;
17
+ setSize: number;
18
+ }
13
19
  /** DevExtreme-shaped `onItemClick` payload (consumers read `event.itemData.<field>`). */
14
20
  interface NxeTreeItemClickEvent {
15
21
  itemData: Record<string, unknown>;
@@ -29,6 +35,7 @@ interface NxeTreeItemClickEvent {
29
35
  * keeps reading `event.itemData.url/urlParams/objectName`.
30
36
  */
31
37
  declare class NxeTreeViewComponent {
38
+ private readonly elementRef;
32
39
  readonly dataSource: _angular_core.InputSignal<readonly unknown[]>;
33
40
  /** Accepted for parity; this component always assembles a tree from the flat list. */
34
41
  readonly dataStructure: _angular_core.InputSignal<"plain" | "tree">;
@@ -49,10 +56,22 @@ declare class NxeTreeViewComponent {
49
56
  readonly expanded: _angular_core.WritableSignal<ReadonlySet<unknown>>;
50
57
  readonly selectedKey: _angular_core.WritableSignal<unknown>;
51
58
  readonly searchText: _angular_core.WritableSignal<string>;
59
+ private readonly searchInput;
52
60
  /** DevExtreme `.instance` facade — `expandAll()` is the only method used. */
53
61
  get instance(): this;
54
62
  protected readonly widthStyle: _angular_core.Signal<string>;
55
63
  private readonly tree;
64
+ /**
65
+ * The visible nodes, each with its position among its siblings.
66
+ *
67
+ * The tree renders as one flat `<ul>` with indentation rather than nested lists, so a screen
68
+ * reader cannot infer depth or sibling counts from the DOM. `aria-level`, `aria-setsize` and
69
+ * `aria-posinset` are what carry that, which makes them required for a flattened tree rather
70
+ * than optional extras. They are computed during the walk, where the sibling array is already
71
+ * in hand — reconstructing them from the flat list afterwards is possible but much harder to
72
+ * read for no gain.
73
+ */
74
+ protected readonly visibleRows: _angular_core.Signal<NxeTreeRow[]>;
56
75
  /** Flattened list of currently-visible nodes (respects expand state + search). */
57
76
  protected readonly visibleNodes: _angular_core.Signal<NxeTreeNode[]>;
58
77
  expandAll(): void;
@@ -61,9 +80,39 @@ declare class NxeTreeViewComponent {
61
80
  protected toggle(node: NxeTreeNode, event: Event): void;
62
81
  protected onNodeClick(node: NxeTreeNode, event: Event): void;
63
82
  protected onSearch(event: Event): void;
83
+ /**
84
+ * The search box's clear button. dx empties the value and leaves the caret in the box (its
85
+ * clear button swallows the mouse-down so the input never loses focus); refocusing here covers
86
+ * the case where focus had already left the input.
87
+ */
88
+ protected clearSearch(): void;
89
+ /**
90
+ * The node holding the tree's single tab stop.
91
+ *
92
+ * A tree is one stop in the tab order, not one per node, so a roving tabindex is part of the
93
+ * role rather than an extra: `role="tree"` on a list nothing can focus would announce a
94
+ * structure a keyboard user cannot reach.
95
+ */
96
+ protected readonly focusedKey: _angular_core.WritableSignal<unknown>;
97
+ protected isTabStop(node: NxeTreeNode, index: number): boolean;
98
+ /**
99
+ * The node that holds DOM focus right now, or `null` while focus is anywhere else.
100
+ *
101
+ * Deliberately not `focusedKey`: that is the roving tab stop and has to outlive a blur, so Tab
102
+ * comes back to the same node. dx drops `dx-state-focused` the moment focus leaves the node,
103
+ * and the focused look goes with it — the row colour, and the toggle, which follows the row's
104
+ * colour only while focused (`color: unset`, dx.light.css). Keyed off focusin/focusout so the
105
+ * class means exactly what it says.
106
+ */
107
+ private readonly focusedNode;
108
+ protected isFocused(node: NxeTreeNode): boolean;
109
+ protected onNodeFocus(node: NxeTreeNode): void;
110
+ protected onNodeBlur(node: NxeTreeNode): void;
111
+ /** Arrow-key navigation, per the WAI-ARIA tree pattern. */
112
+ protected onKeydown(event: KeyboardEvent): void;
64
113
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeTreeViewComponent, never>;
65
114
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeTreeViewComponent, "nxe-tree-view", never, { "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "dataStructure": { "alias": "dataStructure"; "required": false; "isSignal": true; }; "keyExpr": { "alias": "keyExpr"; "required": false; "isSignal": true; }; "displayExpr": { "alias": "displayExpr"; "required": false; "isSignal": true; }; "parentIdExpr": { "alias": "parentIdExpr"; "required": false; "isSignal": true; }; "rootValue": { "alias": "rootValue"; "required": false; "isSignal": true; }; "expandedExpr": { "alias": "expandedExpr"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "selectByClick": { "alias": "selectByClick"; "required": false; "isSignal": true; }; "searchEnabled": { "alias": "searchEnabled"; "required": false; "isSignal": true; }; "searchMode": { "alias": "searchMode"; "required": false; "isSignal": true; }; "useNativeScrolling": { "alias": "useNativeScrolling"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; }, { "onItemClick": "onItemClick"; }, never, never, true, never>;
66
115
  }
67
116
 
68
117
  export { NxeTreeViewComponent };
69
- export type { NxeTreeItemClickEvent, NxeTreeNode };
118
+ export type { NxeTreeItemClickEvent, NxeTreeNode, NxeTreeRow };