@nexterajs/ui 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +279 -34
  2. package/fesm2022/nexterajs-ui-charts.mjs +1096 -0
  3. package/fesm2022/nexterajs-ui-charts.mjs.map +1 -0
  4. package/fesm2022/nexterajs-ui-core.mjs +652 -12
  5. package/fesm2022/nexterajs-ui-core.mjs.map +1 -1
  6. package/fesm2022/nexterajs-ui-display.mjs +1142 -0
  7. package/fesm2022/nexterajs-ui-display.mjs.map +1 -0
  8. package/fesm2022/nexterajs-ui-dropdowns.mjs +321 -33
  9. package/fesm2022/nexterajs-ui-dropdowns.mjs.map +1 -1
  10. package/fesm2022/nexterajs-ui-file-uploader.mjs +572 -10
  11. package/fesm2022/nexterajs-ui-file-uploader.mjs.map +1 -1
  12. package/fesm2022/nexterajs-ui-forms.mjs +2027 -136
  13. package/fesm2022/nexterajs-ui-forms.mjs.map +1 -1
  14. package/fesm2022/nexterajs-ui-grid.mjs +1222 -188
  15. package/fesm2022/nexterajs-ui-grid.mjs.map +1 -1
  16. package/fesm2022/nexterajs-ui-intl.mjs +103 -11
  17. package/fesm2022/nexterajs-ui-intl.mjs.map +1 -1
  18. package/fesm2022/nexterajs-ui-navigation.mjs +1054 -0
  19. package/fesm2022/nexterajs-ui-navigation.mjs.map +1 -0
  20. package/fesm2022/nexterajs-ui-notify.mjs +46 -44
  21. package/fesm2022/nexterajs-ui-notify.mjs.map +1 -1
  22. package/fesm2022/nexterajs-ui-overlay.mjs +1671 -0
  23. package/fesm2022/nexterajs-ui-overlay.mjs.map +1 -0
  24. package/fesm2022/nexterajs-ui-pivot.mjs +51 -26
  25. package/fesm2022/nexterajs-ui-pivot.mjs.map +1 -1
  26. package/fesm2022/nexterajs-ui-shell.mjs +542 -0
  27. package/fesm2022/nexterajs-ui-shell.mjs.map +1 -0
  28. package/fesm2022/nexterajs-ui-tree-view.mjs +5 -2
  29. package/fesm2022/nexterajs-ui-tree-view.mjs.map +1 -1
  30. package/fesm2022/nexterajs-ui-validation.mjs +42 -11
  31. package/fesm2022/nexterajs-ui-validation.mjs.map +1 -1
  32. package/fesm2022/nexterajs-ui.mjs +5 -0
  33. package/fesm2022/nexterajs-ui.mjs.map +1 -1
  34. package/package.json +33 -2
  35. package/styles/_dropdown.scss +5 -5
  36. package/styles/_editor.scss +52 -17
  37. package/styles/_mixins.scss +1 -1
  38. package/styles/_scrollbar.scss +5 -5
  39. package/styles/_status.scss +21 -0
  40. package/styles/_toast.scss +14 -14
  41. package/styles/_tokens.scss +420 -3
  42. package/styles/_widget.scss +14 -3
  43. package/styles/index.scss +6 -4
  44. package/types/nexterajs-ui-charts.d.ts +446 -0
  45. package/types/nexterajs-ui-core.d.ts +387 -22
  46. package/types/nexterajs-ui-display.d.ts +720 -0
  47. package/types/nexterajs-ui-dropdowns.d.ts +191 -48
  48. package/types/nexterajs-ui-file-uploader.d.ts +236 -7
  49. package/types/nexterajs-ui-forms.d.ts +675 -30
  50. package/types/nexterajs-ui-grid.d.ts +448 -93
  51. package/types/nexterajs-ui-intl.d.ts +39 -4
  52. package/types/nexterajs-ui-navigation.d.ts +531 -0
  53. package/types/nexterajs-ui-notify.d.ts +4 -2
  54. package/types/nexterajs-ui-overlay.d.ts +703 -0
  55. package/types/nexterajs-ui-pivot.d.ts +56 -48
  56. package/types/nexterajs-ui-shell.d.ts +294 -0
  57. package/types/nexterajs-ui-tree-view.d.ts +6 -3
  58. package/types/nexterajs-ui-validation.d.ts +20 -11
  59. package/types/nexterajs-ui.d.ts +5 -0
@@ -0,0 +1,703 @@
1
+ import { ComponentType } from '@angular/cdk/portal';
2
+ import * as _angular_core from '@angular/core';
3
+ import { InjectionToken, Injector, ViewContainerRef, TemplateRef, OnDestroy } from '@angular/core';
4
+ import { NxeButtonType, NxeButtonStylingMode } from '@nexterajs/ui/forms';
5
+ import { DialogRef } from '@angular/cdk/dialog';
6
+ import { Observable } from 'rxjs';
7
+ import { NxeMenuCloseTarget } from '@nexterajs/ui/dropdowns';
8
+ import { FocusableOption } from '@angular/cdk/a11y';
9
+ import { NxeMessageService } from '@nexterajs/ui/core';
10
+
11
+ /**
12
+ * Handle on an open dialog. Injectable in the content component (`inject(NxeDialogRef)`), and
13
+ * returned by `NxeDialogService.open`.
14
+ */
15
+ declare class NxeDialogRef<R = unknown, C = unknown> {
16
+ /** Unique id; the dialog's DOM id. */
17
+ readonly id: string;
18
+ /** Id the dialog's title element takes, and the dialog's `aria-labelledby`. */
19
+ readonly titleId: string;
20
+ private cdkRef;
21
+ private outlet;
22
+ private pendingClose;
23
+ private titleClaimed;
24
+ private readonly closedSubject;
25
+ private readonly resultSignal;
26
+ private readonly closedSignal;
27
+ private dismissable;
28
+ /** The result the dialog closed with; `undefined` until it closes (and if it closed without one). */
29
+ readonly result: _angular_core.Signal<R | undefined>;
30
+ /** `true` once the dialog has closed. */
31
+ readonly isClosed: _angular_core.Signal<boolean>;
32
+ constructor(
33
+ /** Unique id; the dialog's DOM id. */
34
+ id: string,
35
+ /** Id the dialog's title element takes, and the dialog's `aria-labelledby`. */
36
+ titleId: string);
37
+ /** Whether Esc and the backdrop may dismiss the dialog. Set `true` while the form is dirty. Explicit `close()` still works. */
38
+ get disableClose(): boolean;
39
+ set disableClose(value: boolean);
40
+ /** The content component instance; `null` for a template, or before it is created. */
41
+ get componentInstance(): C | null;
42
+ /** Close with a result. Safe to call more than once. */
43
+ close(result?: R): void;
44
+ /** Emits the result once, when the dialog closes, then completes. Late subscribers still get it. */
45
+ afterClosed(): Observable<R | undefined>;
46
+ /** The same as {@link afterClosed}, as a promise. */
47
+ whenClosed(): Promise<R | undefined>;
48
+ /** @internal Claimed by the first `nxe-dialog-title` in the dialog, which then carries {@link titleId}. */
49
+ _claimTitle(): string | null;
50
+ /** @internal */
51
+ _attach(cdkRef: DialogRef<R, unknown>): void;
52
+ /** @internal */
53
+ _setOutlet(outlet: () => C | null): void;
54
+ }
55
+
56
+ /** Dialog width. `sm` 400px, `md` 640px, `lg` 960px, `xl` 1200px, `fullscreen` fills the viewport. */
57
+ type NxeDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen';
58
+ /** ARIA role of the dialog. `alertdialog` is for a message that needs a response (confirm). */
59
+ type NxeDialogRole = 'dialog' | 'alertdialog';
60
+ /** The data a dialog was opened with, injected into the content component. */
61
+ declare const NXE_DIALOG_DATA: InjectionToken<unknown>;
62
+ /** A button in the dialog's actions bar, declared in the config rather than in the content. */
63
+ interface NxeDialogAction<R = unknown> {
64
+ /** Button label. */
65
+ text: string;
66
+ /** Closes the dialog with this value when the button is pressed. */
67
+ result?: R;
68
+ /** `nxe-button` type. `danger` for the destructive choice. Default `normal`. */
69
+ type?: NxeButtonType;
70
+ stylingMode?: NxeButtonStylingMode;
71
+ disabled?: boolean;
72
+ /** Receives initial focus when the dialog opens. */
73
+ autofocus?: boolean;
74
+ /** Runs before closing. Return `false` to keep the dialog open (for example a failed save). */
75
+ onClick?: (ref: NxeDialogRef<R>) => void | boolean;
76
+ }
77
+ interface NxeDialogConfig<D = unknown, R = unknown> {
78
+ /** Heading, rendered as the dialog's accessible name. Omit it if the content declares `nxe-dialog-title`. */
79
+ title?: string;
80
+ /** Default `md`. */
81
+ size?: NxeDialogSize;
82
+ /** Injected into the content as {@link NXE_DIALOG_DATA}. */
83
+ data?: D;
84
+ /** Buttons for the actions bar. The content can declare `nxe-dialog-actions` itself instead. */
85
+ actions?: readonly NxeDialogAction<R>[];
86
+ /** Blocks Esc and backdrop dismissal. Change it later through {@link NxeDialogRef.disableClose} (for example while dirty). */
87
+ disableClose?: boolean;
88
+ /** Whether a click on the backdrop dismisses the dialog. Default `true`; only applies while `disableClose` is off. */
89
+ backdropClose?: boolean;
90
+ /** Accessible name when there is no visible title. Replaces `aria-labelledby`. */
91
+ ariaLabel?: string;
92
+ /** Id of the element that describes the dialog. */
93
+ ariaDescribedBy?: string;
94
+ /** Default `dialog`. */
95
+ role?: NxeDialogRole;
96
+ /** Show the corner close button. Default `true`. */
97
+ showClose?: boolean;
98
+ /** What takes initial focus: `first-tabbable` (default), `first-heading`, `dialog` or a CSS selector. `[cdkFocusInitial]` always wins. */
99
+ autoFocus?: 'first-tabbable' | 'first-heading' | 'dialog' | string;
100
+ /** Extra class(es) for the overlay pane. */
101
+ panelClass?: string | string[];
102
+ /** Where dependency lookups of the content start. Default: the root injector. */
103
+ injector?: Injector;
104
+ viewContainerRef?: ViewContainerRef;
105
+ }
106
+ /** What `NxeDialogService.open` accepts as content. A template receives `{ $implicit: data, dialogRef }`. */
107
+ type NxeDialogContent<T> = ComponentType<T> | TemplateRef<T>;
108
+
109
+ /**
110
+ * Opens modal dialogs.
111
+ *
112
+ * ```ts
113
+ * const ref = this.dialog.open(RejectInvoiceDialogComponent, {
114
+ * title: 'Tolak faktur',
115
+ * size: 'sm',
116
+ * data: { invoiceId },
117
+ * actions: [
118
+ * { text: 'Batal', stylingMode: 'outlined', result: false },
119
+ * { text: 'Tolak', type: 'danger', result: true },
120
+ * ],
121
+ * });
122
+ * ref.afterClosed().subscribe((rejected) => rejected && this.reload());
123
+ * ```
124
+ *
125
+ * The content is a component (it injects `NXE_DIALOG_DATA` and `NxeDialogRef`) or a template (it
126
+ * receives `{ $implicit: data, dialogRef }`). Focus is trapped, starts on the first tabbable
127
+ * element (or `[cdkFocusInitial]`) and returns to the opener when the dialog closes. Esc and a
128
+ * backdrop click dismiss it unless `disableClose` is set; with dialogs stacked, Esc closes only
129
+ * the top one. The page behind does not scroll.
130
+ */
131
+ declare class NxeDialogService {
132
+ private readonly cdk;
133
+ private sequence;
134
+ open<R = unknown, D = unknown, T = unknown>(content: NxeDialogContent<T>, config?: NxeDialogConfig<D, R>): NxeDialogRef<R, T>;
135
+ /** Closes every open dialog, with no result. */
136
+ closeAll(): void;
137
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDialogService, never>;
138
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeDialogService>;
139
+ }
140
+
141
+ interface NxeConfirmOptions {
142
+ /** The question, as a heading: name the object ("Batalkan PO-HWG-2610-0042?"). */
143
+ title: string;
144
+ /** What happens, and whether it can be undone. Line breaks are kept. */
145
+ message?: string;
146
+ /** Default: the localized "Confirm". Prefer the verb ("Batalkan PO"). */
147
+ confirmText?: string;
148
+ /** Default: the localized "Cancel". */
149
+ cancelText?: string;
150
+ /** Styles the confirm button as destructive and starts focus on Cancel. */
151
+ danger?: boolean;
152
+ /** Default `sm`. */
153
+ size?: NxeDialogSize;
154
+ }
155
+ /**
156
+ * Asks the user to confirm before something destructive or irreversible. Resolves `true` on
157
+ * confirm, `false` on cancel or Esc.
158
+ *
159
+ * ```ts
160
+ * const go = await this.confirm.confirm({
161
+ * title: 'Batalkan PO-0042?',
162
+ * message: 'PO ini tidak dapat dibuka kembali.',
163
+ * confirmText: 'Batalkan PO',
164
+ * danger: true,
165
+ * });
166
+ * ```
167
+ *
168
+ * It is an `alertdialog` described by the message. A backdrop click does not dismiss it, so an
169
+ * answer is always deliberate.
170
+ */
171
+ declare class NxeConfirmService {
172
+ private readonly dialog;
173
+ private readonly messages;
174
+ confirm(options: NxeConfirmOptions): Promise<boolean>;
175
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeConfirmService, never>;
176
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeConfirmService>;
177
+ }
178
+
179
+ /**
180
+ * Marks the dialog's heading. It takes the dialog's title id, so the dialog is named by it
181
+ * (`aria-labelledby`). Use it in content that declares its own chrome instead of passing `title`.
182
+ *
183
+ * ```html
184
+ * <h2 nxe-dialog-title>Tolak faktur</h2>
185
+ * ```
186
+ *
187
+ * A dialog has one title: the first one claims the id. Outside a dialog it only adds the class.
188
+ */
189
+ declare class NxeDialogTitleDirective {
190
+ protected readonly id: string | null;
191
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDialogTitleDirective, never>;
192
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeDialogTitleDirective, "[nxe-dialog-title], [nxeDialogTitle]", never, {}, {}, never, never, true, never>;
193
+ }
194
+
195
+ /** The dialog's body: padded, and the part that scrolls (the title and actions stay in view). */
196
+ declare class NxeDialogContentDirective {
197
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDialogContentDirective, never>;
198
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeDialogContentDirective, "[nxe-dialog-content], [nxeDialogContent]", never, {}, {}, never, never, true, never>;
199
+ }
200
+
201
+ /**
202
+ * The dialog's button row, pinned to the bottom of the dialog. `align` is where the buttons sit
203
+ * (`end` by default, the primary action last).
204
+ *
205
+ * ```html
206
+ * <div nxe-dialog-actions>
207
+ * <nxe-button text="Batal" (onClick)="ref.close()" />
208
+ * <nxe-button type="default" text="Simpan" (onClick)="save()" />
209
+ * </div>
210
+ * ```
211
+ */
212
+ declare class NxeDialogActionsDirective {
213
+ readonly align: _angular_core.InputSignal<"start" | "end" | "between">;
214
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDialogActionsDirective, never>;
215
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeDialogActionsDirective, "[nxe-dialog-actions], [nxeDialogActions]", never, { "align": { "alias": "align"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
216
+ }
217
+
218
+ /**
219
+ * Opens an `nxe-menu` from the element it sits on.
220
+ *
221
+ * ```html
222
+ * <nxe-button icon="more" aria-label="Aksi" [nxeMenuTriggerFor]="menu" />
223
+ * <nxe-menu #menu>…</nxe-menu>
224
+ * ```
225
+ *
226
+ * The element gets `aria-haspopup="menu"`, `aria-expanded` and `aria-controls`. Click toggles;
227
+ * ArrowDown opens on the first item and ArrowUp on the last; Enter and Space open from hosts that
228
+ * are not buttons (`nxe-button`). The panel opens below the element and flips above (or aligns to
229
+ * the other edge) when there is no room. On an `nxe-menu-item` it opens a submenu to the side.
230
+ * Closing with Esc or by choosing an item returns focus to the element; clicking away does not.
231
+ */
232
+ declare class NxeMenuTriggerForDirective implements OnDestroy {
233
+ private readonly overlay;
234
+ private readonly viewContainer;
235
+ private readonly element;
236
+ /** @internal The menu this trigger sits in, when it opens a submenu. */
237
+ readonly parentMenu: NxeMenuCloseTarget | null;
238
+ /** The menu to open. */
239
+ readonly menu: _angular_core.InputSignal<NxeMenuComponent>;
240
+ /** @internal Id of the trigger; the panel is labelled by it. */
241
+ readonly id: string;
242
+ private readonly openState;
243
+ /** Whether the menu is showing. */
244
+ readonly isOpen: _angular_core.Signal<boolean>;
245
+ private overlayRef;
246
+ /** Opens the menu and moves focus to its first (or last) item. No-op while open. */
247
+ open(focus?: 'first' | 'last' | 'none'): void;
248
+ /** Closes the menu. `restoreFocus` returns focus to the trigger element (Esc, or an item was chosen). */
249
+ close(restoreFocus?: boolean): void;
250
+ toggle(): void;
251
+ ngOnDestroy(): void;
252
+ protected onClick(event: MouseEvent): void;
253
+ protected onKeydown(event: KeyboardEvent): void;
254
+ private createOverlay;
255
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeMenuTriggerForDirective, never>;
256
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeMenuTriggerForDirective, "[nxeMenuTriggerFor]", ["nxeMenuTrigger"], { "menu": { "alias": "nxeMenuTriggerFor"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
257
+ }
258
+
259
+ /**
260
+ * One action in an `nxe-menu`. Use it as an element (recommended, and the only way for apps that ban
261
+ * native buttons and `(click)` on non-interactive elements), or as an attribute on a
262
+ * `<button type="button">` or an `<a>`.
263
+ *
264
+ * ```html
265
+ * <nxe-menu-item (itemClick)="signOut()" [danger]="true">Sign out</nxe-menu-item>
266
+ * <nxe-menu-item routerLink="/profile">Profile</nxe-menu-item>
267
+ * <nxe-menu-item [nxeMenuTriggerFor]="more">Lainnya</nxe-menu-item>
268
+ *
269
+ * <!-- attribute form -->
270
+ * <button type="button" nxe-menu-item (click)="edit()">
271
+ * <svg nxeMenuItemIcon viewBox="0 0 16 16">…</svg>
272
+ * Ubah
273
+ * </button>
274
+ * <button type="button" nxe-menu-item danger (click)="remove()">Hapus</button>
275
+ * <button type="button" nxe-menu-item [nxeMenuTriggerFor]="more">Lainnya</button>
276
+ * ```
277
+ *
278
+ * `disabled` keeps the item visible but unreachable by arrow keys and ignored by clicks. `danger`
279
+ * colours a destructive item. `[nxeMenuItemIcon]` projects an icon before the label. An item with
280
+ * `[nxeMenuTriggerFor]` opens a submenu instead of closing the menu.
281
+ *
282
+ * The element form has `role="menuitem"`, a roving `tabindex`, Enter and Space activation, and
283
+ * `aria-disabled` when disabled. `itemClick` fires on every activation (pointer, Enter, Space) of an
284
+ * enabled item, and never on a disabled one; the attribute form emits it too.
285
+ */
286
+ declare class NxeMenuItemComponent implements FocusableOption {
287
+ private readonly element;
288
+ /** @internal The menu this item sits in. */
289
+ readonly menu: NxeMenuComponent | null;
290
+ /** @internal Set when the item opens a submenu. */
291
+ readonly trigger: NxeMenuTriggerForDirective | null;
292
+ protected readonly isButton: boolean;
293
+ /** Buttons and links turn Enter (and, for a button, Space) into a click themselves. */
294
+ private readonly isNative;
295
+ /** Shown but not actionable. */
296
+ readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
297
+ /** Destructive action: coloured with the danger status. */
298
+ readonly danger: _angular_core.InputSignalWithTransform<boolean, unknown>;
299
+ /** Emits when an enabled item is activated, before the menu closes. */
300
+ readonly itemClick: _angular_core.OutputEmitterRef<void>;
301
+ /** `FocusableOption`: the key manager skips disabled items. */
302
+ get disabled(): boolean;
303
+ focus(): void;
304
+ /** Typeahead matches the start of this. */
305
+ getLabel(): string;
306
+ protected onClick(event: Event): void;
307
+ protected onKeydown(event: KeyboardEvent): void;
308
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeMenuItemComponent, never>;
309
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeMenuItemComponent, "nxe-menu-item, [nxe-menu-item]", never, { "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "danger": { "alias": "danger"; "required": false; "isSignal": true; }; }, { "itemClick": "itemClick"; }, never, ["[nxeMenuItemIcon]", "*"], true, never>;
310
+ }
311
+
312
+ /**
313
+ * `nxe-menu` is the list of actions a trigger opens. It draws nothing where it is declared; the
314
+ * panel appears in a CDK overlay when a `[nxeMenuTriggerFor]` element opens it.
315
+ *
316
+ * ```html
317
+ * <nxe-button icon="more" aria-label="Aksi baris" [nxeMenuTriggerFor]="rowMenu" />
318
+ *
319
+ * <nxe-menu #rowMenu>
320
+ * <button type="button" nxe-menu-item (click)="edit(row)">Ubah</button>
321
+ * <button type="button" nxe-menu-item [disabled]="!row.canCopy" (click)="copy(row)">Salin</button>
322
+ * <nxe-menu-divider />
323
+ * <button type="button" nxe-menu-item danger (click)="remove(row)">Hapus</button>
324
+ * </nxe-menu>
325
+ * ```
326
+ *
327
+ * It follows the ARIA menu pattern. The panel is `role="menu"` and each item `role="menuitem"`;
328
+ * ArrowUp, ArrowDown, Home, End and typing a letter move between items (skipping disabled ones),
329
+ * Enter and Space choose, Esc closes and returns focus to the trigger, and Tab closes and carries on
330
+ * to the next control. An item inside a menu that has its own `[nxeMenuTriggerFor]` opens a submenu
331
+ * with ArrowRight (ArrowLeft or Esc closes it).
332
+ *
333
+ * The menu provides `NXE_MENU`, so `nxe-list` rows and `nxe-menu-item`s close it when chosen.
334
+ */
335
+ declare class NxeMenuComponent implements NxeMenuCloseTarget {
336
+ private readonly injector;
337
+ /** Accessible name. Defaults to the trigger's. */
338
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
339
+ /** Extra class(es) for the overlay pane. */
340
+ readonly panelClass: _angular_core.InputSignal<string | string[]>;
341
+ /** @internal Id of the panel; the trigger's `aria-controls`. */
342
+ readonly panelId: string;
343
+ /** @internal */
344
+ readonly template: _angular_core.Signal<TemplateRef<any>>;
345
+ private readonly descendantItems;
346
+ /** Only this menu's own items: a submenu declared inside this one brings its own. */
347
+ private readonly items;
348
+ /** @internal The trigger currently showing this menu. */
349
+ trigger: NxeMenuTriggerForDirective | null;
350
+ private keyManager;
351
+ /** @internal `aria-labelledby` of the panel: the trigger, unless an explicit label is given. */
352
+ labelledBy(): string | null;
353
+ /** Closes the menu (and any menu it was opened from). Called by items and `nxe-list` when chosen. */
354
+ closeMenu(): void;
355
+ /** @internal Called by the trigger once the panel is attached. */
356
+ _opened(focus: 'first' | 'last' | 'none'): void;
357
+ /** @internal Called by the trigger when the panel is detached. */
358
+ _closed(): void;
359
+ /** @internal Moves the active item under the pointer, and closes a sibling's submenu. */
360
+ _hovered(item: NxeMenuItemComponent): void;
361
+ private closeSubmenus;
362
+ /** @internal */
363
+ protected onKeydown(event: KeyboardEvent): void;
364
+ private closeChain;
365
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeMenuComponent, never>;
366
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeMenuComponent, "nxe-menu", ["nxeMenu"], { "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "panelClass": { "alias": "panelClass"; "required": false; "isSignal": true; }; }, {}, ["descendantItems"], ["*"], true, never>;
367
+ }
368
+
369
+ /** A rule between groups of items in an `nxe-menu`. */
370
+ declare class NxeMenuDividerComponent {
371
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeMenuDividerComponent, never>;
372
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeMenuDividerComponent, "nxe-menu-divider", never, {}, {}, never, never, true, never>;
373
+ }
374
+
375
+ /** The side of the trigger an overlay prefers. `start` and `end` follow the writing direction. */
376
+ type NxePlacement = 'top' | 'bottom' | 'start' | 'end';
377
+
378
+ /**
379
+ * Opens an `nxe-popover` from the element it sits on.
380
+ *
381
+ * ```html
382
+ * <nxe-button icon="filter" text="Filter" [nxePopoverTriggerFor]="filters" />
383
+ * <nxe-popover #filters heading="Filter PO">…</nxe-popover>
384
+ * ```
385
+ *
386
+ * The element gets `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`. Click toggles;
387
+ * Enter and Space do from hosts that are not buttons (`nxe-button`). The panel opens on the
388
+ * popover's `position` (below by default) and flips when there is no room. Opening moves focus to
389
+ * the first focusable control in the content, else the close button; Esc closes and returns focus
390
+ * to the element; a click outside the panel and the element closes it and leaves focus where the
391
+ * click went.
392
+ */
393
+ declare class NxePopoverTriggerForDirective implements OnDestroy {
394
+ private readonly overlay;
395
+ private readonly viewContainer;
396
+ private readonly injector;
397
+ private readonly element;
398
+ /** The popover to open. */
399
+ readonly popover: _angular_core.InputSignal<NxePopoverComponent>;
400
+ /** @internal Id of the trigger; the panel is labelled by it when it has no heading or label. */
401
+ readonly id: string;
402
+ private readonly openState;
403
+ /** Whether the popover is showing. */
404
+ readonly isOpen: _angular_core.Signal<boolean>;
405
+ private overlayRef;
406
+ /** Opens the popover and moves focus into it. No-op while open. */
407
+ open(): void;
408
+ /** Closes the popover. `restoreFocus` returns focus to the element (Esc, Tab off an end, the close button). */
409
+ close(restoreFocus?: boolean): void;
410
+ toggle(): void;
411
+ ngOnDestroy(): void;
412
+ protected onClick(event: MouseEvent): void;
413
+ protected onKeydown(event: KeyboardEvent): void;
414
+ /** The first control in the content, else the close button; nothing when the panel has neither. */
415
+ private focusInto;
416
+ private createOverlay;
417
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxePopoverTriggerForDirective, never>;
418
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxePopoverTriggerForDirective, "[nxePopoverTriggerFor]", ["nxePopoverTrigger"], { "popover": { "alias": "nxePopoverTriggerFor"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
419
+ }
420
+
421
+ /** Which side of the trigger the popover prefers. It flips to the opposite side when there is no room. */
422
+ type NxePopoverPosition = NxePlacement;
423
+ /**
424
+ * `nxe-popover` is a small panel of content a trigger opens: a filter form, a help text, a few
425
+ * details. It draws nothing where it is declared; the panel appears in a CDK overlay when a
426
+ * `[nxePopoverTriggerFor]` element opens it.
427
+ *
428
+ * ```html
429
+ * <nxe-button icon="filter" text="Filter" [nxePopoverTriggerFor]="filters" />
430
+ *
431
+ * <nxe-popover #filters heading="Filter PO" closable>
432
+ * <nxe-form-field label="Pemasok"><nxe-text-box /></nxe-form-field>
433
+ * <nxe-button text="Terapkan" (onClick)="apply(); filters.close()" />
434
+ * </nxe-popover>
435
+ * ```
436
+ *
437
+ * It is a non-modal dialog: `role="dialog"` named by its heading (else `aria-label`, else the
438
+ * trigger), and the page behind it stays usable. Click on the trigger toggles it. Focus moves to the
439
+ * first focusable control in the content when there is one (else the close button, else it stays on
440
+ * the trigger). Esc closes and returns focus to the trigger; so does Tab off either end. Clicking
441
+ * outside closes it and leaves focus where the click went.
442
+ */
443
+ declare class NxePopoverComponent {
444
+ protected readonly messages: NxeMessageService;
445
+ /** A title for the panel; it names the dialog. */
446
+ readonly heading: _angular_core.InputSignal<string | undefined>;
447
+ /** Draws a close button in the header. */
448
+ readonly closable: _angular_core.InputSignalWithTransform<boolean, unknown>;
449
+ /** Accessible name when there is no `heading`. Without either, the trigger names the panel. */
450
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
451
+ /** Preferred side of the trigger. */
452
+ readonly position: _angular_core.InputSignal<NxePlacement>;
453
+ /** Extra class(es) for the overlay pane. */
454
+ readonly panelClass: _angular_core.InputSignal<string | string[]>;
455
+ /** Emits when the panel opens. */
456
+ readonly opened: _angular_core.OutputEmitterRef<void>;
457
+ /** Emits when the panel closes, however it was closed. */
458
+ readonly closed: _angular_core.OutputEmitterRef<void>;
459
+ private readonly sequence;
460
+ /** @internal Id of the panel; the trigger's `aria-controls`. */
461
+ readonly panelId: string;
462
+ /** @internal */
463
+ protected readonly headingId: string;
464
+ /** @internal */
465
+ readonly template: _angular_core.Signal<TemplateRef<any>>;
466
+ /** @internal The trigger currently showing this popover. */
467
+ trigger: NxePopoverTriggerForDirective | null;
468
+ /** Whether the panel is showing. */
469
+ isOpen(): boolean;
470
+ /** Closes the panel and returns focus to its trigger. No-op while closed. */
471
+ close(): void;
472
+ /** @internal `aria-labelledby` of the panel: the heading, else the trigger unless an explicit label is given. */
473
+ labelledBy(): string | null;
474
+ /** @internal Tab off either end closes the panel, as a menu does, so focus is never stranded in an overlay at the end of the page. */
475
+ protected onKeydown(event: KeyboardEvent): void;
476
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxePopoverComponent, never>;
477
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxePopoverComponent, "nxe-popover", ["nxePopover"], { "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "panelClass": { "alias": "panelClass"; "required": false; "isSignal": true; }; }, { "opened": "opened"; "closed": "closed"; }, never, ["*"], true, never>;
478
+ }
479
+
480
+ /** Which side of the element the tooltip prefers. It flips to the opposite side when there is no room. */
481
+ type NxeTooltipPosition = NxePlacement;
482
+ /**
483
+ * Adds a short text tooltip to the element it sits on.
484
+ *
485
+ * ```html
486
+ * <nxe-button icon="edit" stylingMode="text" aria-label="Ubah" nxeTooltip="Ubah PO-0042" />
487
+ * <button type="button" nxeTooltip="Salin ke papan klip" nxeTooltipPosition="bottom">Salin</button>
488
+ * ```
489
+ *
490
+ * It shows after `nxeTooltipShowDelay` (500ms) when the pointer rests on the element, and at once when
491
+ * the element takes focus from the keyboard. It hides on Esc (first, before a dialog or menu under it
492
+ * sees the key), when focus leaves, when the pointer leaves for longer than `nxeTooltipHideDelay`
493
+ * (100ms, long enough to move onto the tooltip itself, so a reader can keep it open), and when the
494
+ * element is pressed. Touch does not show it: there is no long-press.
495
+ *
496
+ * The text is also the element's description. While hidden, it is a visually hidden description the
497
+ * element points at through `aria-describedby`, so a screen reader reads it on focus; while shown,
498
+ * `aria-describedby` points at the `role="tooltip"` element instead. The element's own name is never
499
+ * touched: an icon-only `nxe-button` keeps its `aria-label`, and the tooltip adds to it.
500
+ */
501
+ declare class NxeTooltipDirective implements OnDestroy {
502
+ private readonly overlay;
503
+ private readonly element;
504
+ private readonly ariaDescriber;
505
+ private readonly renderer;
506
+ private readonly focusMonitor;
507
+ /** The tooltip text. Empty, or a `nxeTooltipDisabled` element, shows nothing. */
508
+ readonly text: _angular_core.InputSignal<string | null | undefined>;
509
+ /** Preferred side. `start` and `end` follow the writing direction. */
510
+ readonly position: _angular_core.InputSignal<NxePlacement>;
511
+ /** Milliseconds the pointer rests before the tooltip shows. Focus from the keyboard ignores it. */
512
+ readonly showDelay: _angular_core.InputSignalWithTransform<number, unknown>;
513
+ /** Milliseconds between the pointer leaving and the tooltip hiding. */
514
+ readonly hideDelay: _angular_core.InputSignalWithTransform<number, unknown>;
515
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
516
+ private readonly message;
517
+ private readonly visibleState;
518
+ /** Whether the tooltip is showing. */
519
+ readonly isVisible: _angular_core.Signal<boolean>;
520
+ /** Id of the `role="tooltip"` element while it exists. */
521
+ readonly id: string;
522
+ private overlayRef;
523
+ private panel;
524
+ private showTimer;
525
+ private hideTimer;
526
+ private described;
527
+ private readonly unlisten;
528
+ constructor();
529
+ /** Shows the tooltip after `delay` milliseconds. No-op without text. */
530
+ show(delay?: number): void;
531
+ /** Hides the tooltip after `delay` milliseconds. */
532
+ hide(delay?: number): void;
533
+ ngOnDestroy(): void;
534
+ protected onPointerEnter(event: PointerEvent): void;
535
+ protected onPointerLeave(event: PointerEvent): void;
536
+ private attach;
537
+ private detach;
538
+ private createOverlay;
539
+ private positionStrategy;
540
+ private messageChanged;
541
+ /** The hidden description a screen reader reads on focus while no tooltip is showing. */
542
+ private describe;
543
+ private addDescribedBy;
544
+ private removeDescribedBy;
545
+ private describedByIds;
546
+ private clearTimers;
547
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeTooltipDirective, never>;
548
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeTooltipDirective, "[nxeTooltip]", ["nxeTooltip"], { "text": { "alias": "nxeTooltip"; "required": false; "isSignal": true; }; "position": { "alias": "nxeTooltipPosition"; "required": false; "isSignal": true; }; "showDelay": { "alias": "nxeTooltipShowDelay"; "required": false; "isSignal": true; }; "hideDelay": { "alias": "nxeTooltipHideDelay"; "required": false; "isSignal": true; }; "disabled": { "alias": "nxeTooltipDisabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
549
+ }
550
+
551
+ /** Which edge the drawer sits on. `start` and `end` follow the writing direction: `end` is the right in LTR and the left in RTL. */
552
+ type NxeDrawerSide = 'start' | 'end';
553
+ /**
554
+ * `overlay`: a modal panel over the page, with a scrim, a focus trap and Esc. `push`: a non-modal panel in
555
+ * the page's own layout that takes its width from the content beside it.
556
+ */
557
+ type NxeDrawerMode = 'overlay' | 'push';
558
+ /** Drawer width. `sm` 320px, `md` 420px (default), `lg` 560px, `xl` 760px, `full` the viewport. Never wider than the viewport. */
559
+ type NxeDrawerSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
560
+ /** The data a drawer was opened with, injected into the content component. */
561
+ declare const NXE_DRAWER_DATA: InjectionToken<unknown>;
562
+ /**
563
+ * What `NxeDrawerService.open` takes. The dialog's options, minus its `size` and `role`, plus the edge. The drawer is
564
+ * modal: `title` names it, `actions` fill the footer, Esc and the scrim dismiss it unless `disableClose`.
565
+ */
566
+ interface NxeDrawerConfig<D = unknown, R = unknown> extends Omit<NxeDialogConfig<D, R>, 'size' | 'role'> {
567
+ /** Edge of the screen. Default `end`. */
568
+ side?: NxeDrawerSide;
569
+ /** Default `md`. */
570
+ size?: NxeDrawerSize;
571
+ }
572
+ /** What `NxeDrawerService.open` accepts as content. A template receives `{ $implicit: data, dialogRef }`. */
573
+ type NxeDrawerContent<T> = ComponentType<T> | TemplateRef<T>;
574
+
575
+ /**
576
+ * Handle on an open drawer: the dialog's ref (`close(result)`, `afterClosed()`, `whenClosed()`, `result`,
577
+ * `isClosed`, `disableClose`, `componentInstance`), injectable in the content as `inject(NxeDrawerRef)` and
578
+ * returned by `NxeDrawerService.open`. It is also provided as `NxeDialogRef`, so the dialog directives
579
+ * (`nxe-dialog-title`, `nxe-dialog-content`, `nxe-dialog-actions`) work inside a drawer.
580
+ */
581
+ declare class NxeDrawerRef<R = unknown, C = unknown> extends NxeDialogRef<R, C> {
582
+ }
583
+
584
+ /**
585
+ * Opens modal drawers: a panel that slides in from the screen edge over the page, for a filter panel or a
586
+ * quick look at a document that should not leave the list.
587
+ *
588
+ * ```ts
589
+ * const ref = this.drawer.open(PoQuickViewComponent, {
590
+ * title: 'PO-2026-0412',
591
+ * size: 'lg',
592
+ * data: { id: 412 },
593
+ * actions: [{ text: 'Buka halaman penuh', type: 'default', result: 'open' }],
594
+ * });
595
+ * ref.afterClosed().subscribe((result) => result === 'open' && this.router.navigate(['/pos', 412]));
596
+ * ```
597
+ *
598
+ * It is the dialog service with a different shape, and uses the same parts. The content is a component (it
599
+ * injects `NXE_DRAWER_DATA` and `NxeDrawerRef`, or the dialog's `NXE_DIALOG_DATA` and `NxeDialogRef`) or a
600
+ * template (it receives `{ $implicit: data, dialogRef }`). Focus is trapped, starts on the first tabbable
601
+ * element (or `[cdkFocusInitial]`) and returns to the opener on close; Esc and a click on the scrim dismiss it
602
+ * unless `disableClose` is set; the page behind does not scroll. `side` is `end` by default and follows the
603
+ * writing direction. It slides in over 0.22s, and not under `prefers-reduced-motion: reduce`.
604
+ *
605
+ * For a panel that is part of the page and does not block it, use `nxe-drawer` with `mode="push"`.
606
+ */
607
+ declare class NxeDrawerService {
608
+ private readonly cdk;
609
+ private readonly overlay;
610
+ private sequence;
611
+ open<R = unknown, D = unknown, T = unknown>(content: NxeDrawerContent<T>, config?: NxeDrawerConfig<D, R>): NxeDrawerRef<R, T>;
612
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDrawerService, never>;
613
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeDrawerService>;
614
+ }
615
+
616
+ /**
617
+ * `nxe-drawer` is a panel at the edge of the screen: a filter panel, the details of the row you clicked.
618
+ *
619
+ * ```html
620
+ * <nxe-button text="Filter" (onClick)="filters.set(true)" />
621
+ *
622
+ * <nxe-drawer [(opened)]="filters" heading="Filter pesanan" side="end" size="sm">
623
+ * <nxe-form-field label="Pemasok"><nxe-text-box [formControl]="supplier" /></nxe-form-field>
624
+ * <div nxeDrawerFooter>
625
+ * <nxe-button text="Atur ulang" (onClick)="reset()" />
626
+ * <nxe-button type="default" text="Terapkan" (onClick)="apply(); filters.set(false)" />
627
+ * </div>
628
+ * </nxe-drawer>
629
+ * ```
630
+ *
631
+ * **Modes.** `overlay` (default) is modal: the panel opens in a CDK overlay over a scrim, `role="dialog"` with
632
+ * `aria-modal`, focus trapped and starting on the first tabbable element (`[cdkFocusInitial]` wins; `autoFocus`
633
+ * changes it), Esc and a click on the scrim close it, focus returns to the control that was focused when it
634
+ * opened, and the page behind does not scroll. `push` is not modal: the panel is an `<aside>` in the page's
635
+ * own layout, a flex item that opens by growing from no width, so the content beside it narrows instead of
636
+ * being covered. Put it inside a flex row. It takes focus when it opens and gives it back when it closes,
637
+ * and Esc inside it closes it. Changing `mode` while open (a panel that is a push drawer on a desktop and an
638
+ * overlay on a phone) moves the same content from one to the other.
639
+ *
640
+ * **Slots.** The heading is the `heading` input (the panel's accessible name; without one, set `aria-label`).
641
+ * The close button, named by `common.close`, shows with `closable` (default) unless `disableClose` is on. Everything else is the body,
642
+ * which scrolls, and `[nxeDrawerFooter]` is pinned under it.
643
+ *
644
+ * `opened` is a two-way model. `side` is `start` or `end` and follows the writing direction, `size` is `sm`,
645
+ * `md` (default), `lg`, `xl` or `full`. `disableClose` stops Esc and the scrim from closing it and hides the
646
+ * close button (a form that must be saved or discarded). For a drawer opened from code with a component, use
647
+ * `NxeDrawerService`.
648
+ */
649
+ declare class NxeDrawerComponent {
650
+ private readonly dialog;
651
+ private readonly overlay;
652
+ private readonly viewContainer;
653
+ private readonly injector;
654
+ private readonly messages;
655
+ private readonly panel;
656
+ private readonly aside;
657
+ /** Whether the drawer is open. Two-way: `[(opened)]`. */
658
+ readonly opened: _angular_core.ModelSignal<boolean>;
659
+ /** `overlay` (default, modal) or `push` (in the page's layout). */
660
+ readonly mode: _angular_core.InputSignal<NxeDrawerMode>;
661
+ /** `start` or `end` (default). */
662
+ readonly side: _angular_core.InputSignal<NxeDrawerSide>;
663
+ /** `sm`, `md` (default), `lg`, `xl` or `full`. */
664
+ readonly size: _angular_core.InputSignal<NxeDrawerSize>;
665
+ /** The title, which also names the panel. */
666
+ readonly heading: _angular_core.InputSignal<string>;
667
+ /** Accessible name when there is no `heading`. */
668
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
669
+ /** Show the close button. Default `true`. */
670
+ readonly closable: _angular_core.InputSignalWithTransform<boolean, unknown>;
671
+ /** Esc and the scrim do not close it, and the close button is hidden. */
672
+ readonly disableClose: _angular_core.InputSignalWithTransform<boolean, unknown>;
673
+ /** Whether a click on the scrim closes an overlay drawer. Default `true`; only applies while `disableClose` is off. */
674
+ readonly backdropClose: _angular_core.InputSignalWithTransform<boolean, unknown>;
675
+ /** What takes initial focus in overlay mode: `first-tabbable` (default), `first-heading`, `dialog` or a CSS selector. */
676
+ readonly autoFocus: _angular_core.InputSignal<string>;
677
+ /** Extra class(es) for the overlay pane. */
678
+ readonly panelClass: _angular_core.InputSignal<string | string[]>;
679
+ private readonly uid;
680
+ protected readonly titleId: string;
681
+ protected readonly closeLabel: _angular_core.Signal<string>;
682
+ protected readonly pushed: _angular_core.Signal<boolean>;
683
+ /** The close button is hidden, not disabled, while `disableClose` is on. */
684
+ protected readonly showClose: _angular_core.Signal<boolean>;
685
+ /** Modal and open: the part that lives in the CDK overlay. */
686
+ private readonly overlayShown;
687
+ private overlayRef;
688
+ private returnFocusTo;
689
+ constructor();
690
+ open(): void;
691
+ close(): void;
692
+ toggle(): void;
693
+ /** The close button and Esc go through here so `disableClose` is honoured in one place. */
694
+ protected requestClose(): void;
695
+ protected onKeydown(event: KeyboardEvent): void;
696
+ private attachOverlay;
697
+ private detachOverlay;
698
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeDrawerComponent, never>;
699
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NxeDrawerComponent, "nxe-drawer", ["nxeDrawer"], { "opened": { "alias": "opened"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "side": { "alias": "side"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "disableClose": { "alias": "disableClose"; "required": false; "isSignal": true; }; "backdropClose": { "alias": "backdropClose"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "panelClass": { "alias": "panelClass"; "required": false; "isSignal": true; }; }, { "opened": "openedChange"; }, never, ["*", "[nxeDrawerFooter]"], true, never>;
700
+ }
701
+
702
+ export { NXE_DIALOG_DATA, NXE_DRAWER_DATA, NxeConfirmService, NxeDialogActionsDirective, NxeDialogContentDirective, NxeDialogRef, NxeDialogService, NxeDialogTitleDirective, NxeDrawerComponent, NxeDrawerRef, NxeDrawerService, NxeMenuComponent, NxeMenuDividerComponent, NxeMenuItemComponent, NxeMenuTriggerForDirective, NxePopoverComponent, NxePopoverTriggerForDirective, NxeTooltipDirective };
703
+ export type { NxeConfirmOptions, NxeDialogAction, NxeDialogConfig, NxeDialogContent, NxeDialogRole, NxeDialogSize, NxeDrawerConfig, NxeDrawerContent, NxeDrawerMode, NxeDrawerSide, NxeDrawerSize, NxePopoverPosition, NxeTooltipPosition };