@nexterajs/ui 0.0.1 → 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 (63) 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 +835 -11
  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 +621 -69
  9. package/fesm2022/nexterajs-ui-dropdowns.mjs.map +1 -1
  10. package/fesm2022/nexterajs-ui-file-uploader.mjs +576 -11
  11. package/fesm2022/nexterajs-ui-file-uploader.mjs.map +1 -1
  12. package/fesm2022/nexterajs-ui-forms.mjs +2702 -452
  13. package/fesm2022/nexterajs-ui-forms.mjs.map +1 -1
  14. package/fesm2022/nexterajs-ui-grid.mjs +2350 -336
  15. package/fesm2022/nexterajs-ui-grid.mjs.map +1 -1
  16. package/fesm2022/nexterajs-ui-intl.mjs +117 -15
  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 +353 -0
  21. package/fesm2022/nexterajs-ui-notify.mjs.map +1 -0
  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 +191 -136
  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-styling.mjs +568 -3
  29. package/fesm2022/nexterajs-ui-styling.mjs.map +1 -1
  30. package/fesm2022/nexterajs-ui-tree-view.mjs +150 -18
  31. package/fesm2022/nexterajs-ui-tree-view.mjs.map +1 -1
  32. package/fesm2022/nexterajs-ui-validation.mjs +283 -97
  33. package/fesm2022/nexterajs-ui-validation.mjs.map +1 -1
  34. package/fesm2022/nexterajs-ui.mjs +6 -0
  35. package/fesm2022/nexterajs-ui.mjs.map +1 -1
  36. package/package.json +37 -2
  37. package/styles/_dropdown.scss +150 -1
  38. package/styles/_editor.scss +75 -21
  39. package/styles/_icons.scss +92 -0
  40. package/styles/_mixins.scss +104 -1
  41. package/styles/_scrollbar.scss +134 -0
  42. package/styles/_status.scss +21 -0
  43. package/styles/_toast.scss +243 -0
  44. package/styles/_tokens.scss +467 -2
  45. package/styles/_widget.scss +14 -3
  46. package/styles/index.scss +10 -4
  47. package/types/nexterajs-ui-charts.d.ts +446 -0
  48. package/types/nexterajs-ui-core.d.ts +515 -30
  49. package/types/nexterajs-ui-display.d.ts +720 -0
  50. package/types/nexterajs-ui-dropdowns.d.ts +318 -57
  51. package/types/nexterajs-ui-file-uploader.d.ts +240 -8
  52. package/types/nexterajs-ui-forms.d.ts +772 -43
  53. package/types/nexterajs-ui-grid.d.ts +878 -135
  54. package/types/nexterajs-ui-intl.d.ts +39 -4
  55. package/types/nexterajs-ui-navigation.d.ts +531 -0
  56. package/types/nexterajs-ui-notify.d.ts +149 -0
  57. package/types/nexterajs-ui-overlay.d.ts +703 -0
  58. package/types/nexterajs-ui-pivot.d.ts +91 -70
  59. package/types/nexterajs-ui-shell.d.ts +294 -0
  60. package/types/nexterajs-ui-styling.d.ts +163 -3
  61. package/types/nexterajs-ui-tree-view.d.ts +56 -4
  62. package/types/nexterajs-ui-validation.d.ts +110 -22
  63. package/types/nexterajs-ui.d.ts +6 -0
@@ -1,7 +1,8 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { InjectionToken, ElementRef, NgZone, TemplateRef } from '@angular/core';
2
+ import { InjectionToken, EnvironmentProviders, ElementRef, NgZone, TemplateRef } from '@angular/core';
3
3
  import * as _nexterajs_ui_core from '@nexterajs/ui/core';
4
4
  import { ControlValueAccessor } from '@angular/forms';
5
+ import { NxeNumberSeparators } from '@nexterajs/ui/intl';
5
6
 
6
7
  /**
7
8
  * DevExtreme-compatible value-change event payload.
@@ -22,6 +23,309 @@ interface NxeValueChangedEvent<T> {
22
23
  /** The component host element (DevExtreme `element`). */
23
24
  element: HTMLElement;
24
25
  }
26
+ /** Which native event an editor is re-emitting in dx's shape. */
27
+ type NxeEditorEventKind = 'keydown' | 'keyup' | 'input' | 'change' | 'focusin' | 'focusout';
28
+ /**
29
+ * dx's payload for the keyboard, focus and input events: the native event plus the widget and
30
+ * its host element, which is what handlers written against DevExtreme expect to receive.
31
+ */
32
+ interface NxeEditorEvent {
33
+ event: Event;
34
+ component: unknown;
35
+ element: HTMLElement;
36
+ }
37
+
38
+ /**
39
+ * Every user-visible string the library renders, in English.
40
+ *
41
+ * Flat keys, namespaced by component (`grid.pager.info`). `{0}`, `{1}`... are positional
42
+ * arguments filled by `NxeMessageService.t(key, ...args)`. English is the default bundle and
43
+ * the fallback for any key a custom bundle leaves out, so the library renders exactly what it
44
+ * always did until an application opts into another locale.
45
+ *
46
+ * The key set is the type: `NxeMessageKey` is derived from it and the Indonesian bundle is
47
+ * checked against it, so a key added here without a translation fails to compile.
48
+ */
49
+ declare const NXE_MESSAGES_EN: {
50
+ readonly 'common.search': "Search";
51
+ readonly 'common.clear': "Clear";
52
+ readonly 'common.close': "Close";
53
+ readonly 'common.ok': "OK";
54
+ readonly 'common.cancel': "Cancel";
55
+ readonly 'common.confirm': "Confirm";
56
+ readonly 'common.yes': "Yes";
57
+ readonly 'common.no': "No";
58
+ readonly 'common.all': "(All)";
59
+ readonly 'common.selectAll': "Select All";
60
+ readonly 'common.blanks': "(Blanks)";
61
+ readonly 'grid.noData': "No data";
62
+ readonly 'grid.groupPanel': "Drag a column header here to group by that column";
63
+ readonly 'grid.edit': "Edit";
64
+ readonly 'grid.save': "Save";
65
+ readonly 'grid.cancel': "Cancel";
66
+ readonly 'grid.expand': "Expand";
67
+ readonly 'grid.collapse': "Collapse";
68
+ readonly 'grid.expandedRow': "Expanded row";
69
+ readonly 'grid.collapsedRow': "Collapsed row";
70
+ readonly 'grid.editableCell': "Editable";
71
+ readonly 'grid.filterRow.operation': "Filter operation";
72
+ readonly 'grid.filterRow.reset': "Reset";
73
+ readonly 'grid.filterRow.true': "true";
74
+ readonly 'grid.filterRow.false': "false";
75
+ readonly 'grid.op.contains': "Contains";
76
+ readonly 'grid.op.notContains': "Does not contain";
77
+ readonly 'grid.op.startsWith': "Starts with";
78
+ readonly 'grid.op.endsWith': "Ends with";
79
+ readonly 'grid.op.equals': "Equals";
80
+ readonly 'grid.op.notEquals': "Does not equal";
81
+ readonly 'grid.op.lessThan': "Less than";
82
+ readonly 'grid.op.greaterThan': "Greater than";
83
+ readonly 'grid.op.lessThanOrEqual': "Less than or equal to";
84
+ readonly 'grid.op.greaterThanOrEqual': "Greater than or equal to";
85
+ readonly 'grid.op.between': "Between";
86
+ readonly 'grid.pager.info': "Page {0} of {1} ({2} items)";
87
+ readonly 'grid.pager.navigation': "Page navigation";
88
+ readonly 'grid.pager.pageSize': "Page size";
89
+ readonly 'grid.pager.itemsPerPage': "Items per page: {0}";
90
+ readonly 'grid.pager.previous': "Previous page";
91
+ readonly 'grid.pager.next': "Next page";
92
+ readonly 'grid.pager.page': "Page {0}";
93
+ readonly 'grid.pager.first': "First page";
94
+ readonly 'grid.pager.last': "Last page";
95
+ readonly 'grid.pager.total': "{0} items";
96
+ readonly 'grid.remote.loading': "Loading";
97
+ readonly 'grid.remote.error': "The data could not be loaded.";
98
+ readonly 'grid.remote.retry': "Retry";
99
+ readonly 'uploader.selectFile': "Select File";
100
+ readonly 'uploader.dropHere': "or Drop here";
101
+ readonly 'uploader.cancel': "Cancel";
102
+ readonly 'uploader.sizeB': "{0} b";
103
+ readonly 'uploader.sizeKb': "{0} Kb";
104
+ readonly 'uploader.sizeMb': "{0} Mb";
105
+ readonly 'validation.rule.required': "Required";
106
+ readonly 'validation.rule.email': "Email is invalid";
107
+ readonly 'validation.rule.pattern': "Value does not match pattern";
108
+ readonly 'validation.rule.range': "Value is out of range";
109
+ readonly 'validation.rule.compare': "Values do not match";
110
+ readonly 'validation.rule.custom': "Value is invalid";
111
+ readonly 'validation.field.required': "This field is required.";
112
+ readonly 'validation.field.email': "Enter a valid email address.";
113
+ readonly 'validation.field.minlength': "Enter at least {0} characters.";
114
+ readonly 'validation.field.maxlength': "Enter no more than {0} characters.";
115
+ readonly 'validation.field.min': "Must be at least {0}.";
116
+ readonly 'validation.field.max': "Must be at most {0}.";
117
+ readonly 'validation.field.pattern': "Enter a value in the expected format.";
118
+ readonly 'validation.field.invalid': "This value is not valid.";
119
+ readonly 'date.now': "Now";
120
+ readonly 'date.done': "Done";
121
+ readonly 'date.hour': "Hour";
122
+ readonly 'date.minute': "Minute";
123
+ readonly 'dateRange.start': "Start date";
124
+ readonly 'dateRange.end': "End date";
125
+ readonly 'dateRange.startPlaceholder': "Start date";
126
+ readonly 'dateRange.endPlaceholder': "End date";
127
+ readonly 'dateRange.dialog': "Choose a date range";
128
+ readonly 'dateRange.previousMonth': "Previous month";
129
+ readonly 'dateRange.nextMonth': "Next month";
130
+ readonly 'dateRange.presets': "Quick ranges";
131
+ readonly 'dateRange.pickStart': "Select the start date";
132
+ readonly 'dateRange.pickEnd': "Select the end date";
133
+ readonly 'dateRange.preset.today': "Today";
134
+ readonly 'dateRange.preset.yesterday': "Yesterday";
135
+ readonly 'dateRange.preset.last7Days': "Last 7 days";
136
+ readonly 'dateRange.preset.last30Days': "Last 30 days";
137
+ readonly 'dateRange.preset.thisMonth': "This month";
138
+ readonly 'dateRange.preset.lastMonth': "Last month";
139
+ readonly 'dateRange.preset.thisYear': "This year";
140
+ readonly 'dropdown.noData': "No data to display";
141
+ readonly 'dropdown.selectAll': "Select All";
142
+ readonly 'uploader.selectFiles': "Select files";
143
+ readonly 'uploader.dropFiles': "or drop files here";
144
+ readonly 'uploader.listLabel': "Attached files";
145
+ readonly 'uploader.acceptHint': "Accepted: {0}";
146
+ readonly 'uploader.maxSizeHint': "Up to {0} each";
147
+ readonly 'uploader.maxFilesHint': "Up to {0} files";
148
+ readonly 'uploader.statusPending': "Waiting to upload";
149
+ readonly 'uploader.statusUploading': "Uploading {0}%";
150
+ readonly 'uploader.statusUploaded': "Uploaded";
151
+ readonly 'uploader.statusFailed': "Upload failed";
152
+ readonly 'uploader.uploadingFile': "Uploading {0}";
153
+ readonly 'uploader.uploadFailed': "The upload failed.";
154
+ readonly 'uploader.cancelled': "Upload cancelled.";
155
+ readonly 'uploader.cancelFile': "Cancel upload of {0}";
156
+ readonly 'uploader.retryFile': "Retry upload of {0}";
157
+ readonly 'uploader.removeFile': "Remove {0}";
158
+ readonly 'uploader.retry': "Retry";
159
+ readonly 'uploader.remove': "Remove";
160
+ readonly 'uploader.rejectType': "{0} is not an accepted file type.";
161
+ readonly 'uploader.rejectSize': "{0} is larger than {1}.";
162
+ readonly 'uploader.rejectCount': "{0} is over the limit of {1} files.";
163
+ readonly 'uploader.announceAdded': "{0} added";
164
+ readonly 'uploader.announceRemoved': "{0} removed";
165
+ readonly 'validation.field.fileType': "Only these file types are accepted: {0}.";
166
+ readonly 'validation.field.fileSize': "Each file must be {0} or smaller.";
167
+ readonly 'validation.field.maxFiles': "Attach at most {0} files.";
168
+ readonly 'validation.field.uploading': "Wait for the uploads to finish.";
169
+ readonly 'validation.field.uploadFailed': "Retry or remove the files that failed to upload.";
170
+ readonly 'timeline.pending': "Pending";
171
+ readonly 'stepper.listLabel': "Steps";
172
+ readonly 'stepper.stepOf': "Step {0} of {1}: {2}";
173
+ readonly 'stepper.completed': "Completed";
174
+ readonly 'stepper.error': "Has errors";
175
+ readonly 'stepper.optional': "Optional";
176
+ readonly 'stepper.blocked': "Step {0} is not complete. Fix the highlighted fields to continue.";
177
+ readonly 'notify.close': "Close notification";
178
+ readonly 'shell.skipToContent': "Skip to content";
179
+ readonly 'shell.mainNavigation': "Main navigation";
180
+ readonly 'shell.toggleNavigation': "Toggle navigation";
181
+ readonly 'shell.closeNavigation': "Close navigation";
182
+ readonly 'shell.collapseSidebar': "Collapse sidebar";
183
+ readonly 'shell.expandSidebar': "Expand sidebar";
184
+ readonly 'pivot.grandTotal': "Grand Total";
185
+ readonly 'pivot.total': "{0} Total";
186
+ readonly 'pivot.noData': "No data";
187
+ readonly 'pivot.showFieldChooser': "Show Field Chooser";
188
+ readonly 'pivot.chooser.title': "Field Chooser";
189
+ readonly 'pivot.chooser.allFields': "All Fields";
190
+ readonly 'pivot.chooser.rowFields': "Row Fields";
191
+ readonly 'pivot.chooser.columnFields': "Column Fields";
192
+ readonly 'pivot.chooser.filterFields': "Filter Fields";
193
+ readonly 'pivot.chooser.dataFields': "Data Fields";
194
+ readonly 'pivot.chooser.checkState': "Check state";
195
+ readonly 'pivot.panel.dropFilter': "Drop Filter Fields Here";
196
+ readonly 'pivot.panel.dropData': "Drop Data Fields Here";
197
+ readonly 'pivot.panel.dropColumn': "Drop Column Fields Here";
198
+ readonly 'pivot.panel.dropRow': "Drop Row Fields Here";
199
+ readonly 'forms.password.show': "Show password";
200
+ readonly 'forms.password.hide': "Hide password";
201
+ readonly 'forms.textArea.charactersLeft': "{0} characters left";
202
+ readonly 'forms.textArea.charactersOver': "{0} characters over the limit";
203
+ readonly 'forms.numberBox.increase': "Increase";
204
+ readonly 'forms.numberBox.decrease': "Decrease";
205
+ readonly 'display.noValue': "No value";
206
+ readonly 'charts.other': "Other";
207
+ readonly 'charts.total': "Total";
208
+ readonly 'charts.empty': "No data to chart";
209
+ readonly 'charts.legend': "Legend";
210
+ readonly 'charts.viewAsTable': "View as table";
211
+ readonly 'charts.viewAsChart': "View as chart";
212
+ readonly 'charts.navigate': "Chart data. Use the arrow keys to move between points, Escape to leave.";
213
+ readonly 'charts.navigateSegments': "Chart segments. Use the arrow keys to move between segments, Escape to leave.";
214
+ readonly 'charts.summary.line': "Line chart, {0} series, {1} points from {2} to {3}.";
215
+ readonly 'charts.summary.area': "Area chart, {0} series, {1} points from {2} to {3}.";
216
+ readonly 'charts.summary.stackedArea': "Stacked area chart, {0} series, {1} points from {2} to {3}.";
217
+ readonly 'charts.summary.series': "{0}: from {1} to {2}, lowest {3}, highest {4}.";
218
+ readonly 'charts.summary.donut': "Donut chart, {0} segments, total {1}.";
219
+ readonly 'charts.summary.segment': "{0}: {1}, {2}.";
220
+ readonly 'charts.table.category': "Category";
221
+ readonly 'charts.table.segment': "Segment";
222
+ readonly 'charts.table.value': "Value";
223
+ readonly 'charts.table.share': "Share";
224
+ readonly 'avatar.status.online': "Online";
225
+ readonly 'avatar.status.away': "Away";
226
+ readonly 'avatar.status.busy': "Busy";
227
+ readonly 'avatar.status.offline': "Offline";
228
+ readonly 'avatar.more': "{0} more";
229
+ readonly 'breadcrumb.label': "Breadcrumb";
230
+ readonly 'breadcrumb.more': "Show hidden levels";
231
+ };
232
+ /** A key of the message bundle. */
233
+ type NxeMessageKey = keyof typeof NXE_MESSAGES_EN;
234
+ /** A complete message bundle: every key, one string each. */
235
+ type NxeMessages = Readonly<Record<NxeMessageKey, string>>;
236
+
237
+ /** What an application states once at bootstrap; see {@link provideNxeMessages}. */
238
+ interface NxeMessagesConfig {
239
+ /** Initial locale (`'en'`, `'id'`, `'id-ID'`...). Default `'en'`. */
240
+ locale?: string;
241
+ /** Partial bundle layered over the active language's bundle, whatever the language. */
242
+ overrides?: Partial<NxeMessages>;
243
+ /**
244
+ * Extra or replacement bundles by language (`{ fr: { 'common.cancel': 'Annuler' } }`). A bundle
245
+ * may be partial: keys it leaves out fall back to English.
246
+ */
247
+ bundles?: Readonly<Record<string, Partial<NxeMessages>>>;
248
+ /**
249
+ * Set Luxon's `Settings.defaultLocale` to the active locale, so month and weekday names (and
250
+ * every `MMM` in a display format) follow the language. Default `true`; `false` leaves Luxon
251
+ * alone. Luxon's previous default is restored when the service is destroyed.
252
+ */
253
+ luxon?: boolean;
254
+ /**
255
+ * Make number separators follow the locale: `true` uses `1.234,5` for `id` and `1,234.5`
256
+ * otherwise, or pass your own `{ [language]: separators }` map. It takes effect through
257
+ * {@link provideNxeMessages}, which then provides {@link NXE_NUMBER_SEPARATORS} as a live view
258
+ * of the active locale. Default off: numbers keep whatever `NXE_NUMBER_SEPARATORS` says.
259
+ */
260
+ separators?: boolean | Readonly<Record<string, NxeNumberSeparators>>;
261
+ }
262
+ /**
263
+ * The library's initial message configuration, provided by {@link provideNxeMessages}. Absent,
264
+ * the service starts in English with nothing overridden.
265
+ */
266
+ declare const NXE_MESSAGES: InjectionToken<NxeMessagesConfig>;
267
+ /**
268
+ * Runtime-switchable messages for every `nxe-*` component.
269
+ *
270
+ * State is signals, so a component that reads {@link t} (or {@link messages}) inside a template or
271
+ * a `computed` re-renders when the language changes: no reload, no recreation. That is also what
272
+ * makes it safe under zoneless OnPush, because the template's reactive consumer tracks the read.
273
+ *
274
+ * ```ts
275
+ * const messages = inject(NxeMessageService);
276
+ * messages.use('id');
277
+ * messages.t('grid.pager.info', 1, 5, 42); // 'Halaman 1 dari 5 (42 item)'
278
+ * ```
279
+ */
280
+ declare class NxeMessageService {
281
+ private readonly config;
282
+ private readonly localeState;
283
+ private readonly customBundle;
284
+ private readonly overrideState;
285
+ /** The active locale as the application stated it (`'id'`, `'en-US'`...). */
286
+ readonly locale: _angular_core.Signal<string>;
287
+ /** The active language (`'id'` for `'id-ID'`); what picks the bundle. */
288
+ readonly language: _angular_core.Signal<string>;
289
+ /** The bundle in force: English, under the language's bundle, under the overrides. */
290
+ readonly messages: _angular_core.Signal<Readonly<Record<"common.search" | "common.clear" | "common.close" | "common.ok" | "common.cancel" | "common.confirm" | "common.yes" | "common.no" | "common.all" | "common.selectAll" | "common.blanks" | "grid.noData" | "grid.groupPanel" | "grid.edit" | "grid.save" | "grid.cancel" | "grid.expand" | "grid.collapse" | "grid.expandedRow" | "grid.collapsedRow" | "grid.editableCell" | "grid.filterRow.operation" | "grid.filterRow.reset" | "grid.filterRow.true" | "grid.filterRow.false" | "grid.op.contains" | "grid.op.notContains" | "grid.op.startsWith" | "grid.op.endsWith" | "grid.op.equals" | "grid.op.notEquals" | "grid.op.lessThan" | "grid.op.greaterThan" | "grid.op.lessThanOrEqual" | "grid.op.greaterThanOrEqual" | "grid.op.between" | "grid.pager.info" | "grid.pager.navigation" | "grid.pager.pageSize" | "grid.pager.itemsPerPage" | "grid.pager.previous" | "grid.pager.next" | "grid.pager.page" | "grid.pager.first" | "grid.pager.last" | "grid.pager.total" | "grid.remote.loading" | "grid.remote.error" | "grid.remote.retry" | "uploader.selectFile" | "uploader.dropHere" | "uploader.cancel" | "uploader.sizeB" | "uploader.sizeKb" | "uploader.sizeMb" | "validation.rule.required" | "validation.rule.email" | "validation.rule.pattern" | "validation.rule.range" | "validation.rule.compare" | "validation.rule.custom" | "validation.field.required" | "validation.field.email" | "validation.field.minlength" | "validation.field.maxlength" | "validation.field.min" | "validation.field.max" | "validation.field.pattern" | "validation.field.invalid" | "date.now" | "date.done" | "date.hour" | "date.minute" | "dateRange.start" | "dateRange.end" | "dateRange.startPlaceholder" | "dateRange.endPlaceholder" | "dateRange.dialog" | "dateRange.previousMonth" | "dateRange.nextMonth" | "dateRange.presets" | "dateRange.pickStart" | "dateRange.pickEnd" | "dateRange.preset.today" | "dateRange.preset.yesterday" | "dateRange.preset.last7Days" | "dateRange.preset.last30Days" | "dateRange.preset.thisMonth" | "dateRange.preset.lastMonth" | "dateRange.preset.thisYear" | "dropdown.noData" | "dropdown.selectAll" | "uploader.selectFiles" | "uploader.dropFiles" | "uploader.listLabel" | "uploader.acceptHint" | "uploader.maxSizeHint" | "uploader.maxFilesHint" | "uploader.statusPending" | "uploader.statusUploading" | "uploader.statusUploaded" | "uploader.statusFailed" | "uploader.uploadingFile" | "uploader.uploadFailed" | "uploader.cancelled" | "uploader.cancelFile" | "uploader.retryFile" | "uploader.removeFile" | "uploader.retry" | "uploader.remove" | "uploader.rejectType" | "uploader.rejectSize" | "uploader.rejectCount" | "uploader.announceAdded" | "uploader.announceRemoved" | "validation.field.fileType" | "validation.field.fileSize" | "validation.field.maxFiles" | "validation.field.uploading" | "validation.field.uploadFailed" | "timeline.pending" | "stepper.listLabel" | "stepper.stepOf" | "stepper.completed" | "stepper.error" | "stepper.optional" | "stepper.blocked" | "notify.close" | "shell.skipToContent" | "shell.mainNavigation" | "shell.toggleNavigation" | "shell.closeNavigation" | "shell.collapseSidebar" | "shell.expandSidebar" | "pivot.grandTotal" | "pivot.total" | "pivot.noData" | "pivot.showFieldChooser" | "pivot.chooser.title" | "pivot.chooser.allFields" | "pivot.chooser.rowFields" | "pivot.chooser.columnFields" | "pivot.chooser.filterFields" | "pivot.chooser.dataFields" | "pivot.chooser.checkState" | "pivot.panel.dropFilter" | "pivot.panel.dropData" | "pivot.panel.dropColumn" | "pivot.panel.dropRow" | "forms.password.show" | "forms.password.hide" | "forms.textArea.charactersLeft" | "forms.textArea.charactersOver" | "forms.numberBox.increase" | "forms.numberBox.decrease" | "display.noValue" | "charts.other" | "charts.total" | "charts.empty" | "charts.legend" | "charts.viewAsTable" | "charts.viewAsChart" | "charts.navigate" | "charts.navigateSegments" | "charts.summary.line" | "charts.summary.area" | "charts.summary.stackedArea" | "charts.summary.series" | "charts.summary.donut" | "charts.summary.segment" | "charts.table.category" | "charts.table.segment" | "charts.table.value" | "charts.table.share" | "avatar.status.online" | "avatar.status.away" | "avatar.status.busy" | "avatar.status.offline" | "avatar.more" | "breadcrumb.label" | "breadcrumb.more", string>>>;
291
+ /** Separators for the active locale; en-US for a language with none. */
292
+ readonly separators: _angular_core.Signal<NxeNumberSeparators>;
293
+ private readonly luxonSync;
294
+ private readonly luxonBefore;
295
+ constructor();
296
+ /**
297
+ * Switch language. A string picks a built-in or configured bundle (`'id'`, `'en'`); a bundle
298
+ * object replaces the language's bundle outright (keys it leaves out fall back to English),
299
+ * under the locale named by the second argument, or the current one.
300
+ */
301
+ use(locale: string): void;
302
+ use(bundle: Partial<NxeMessages>, locale?: string): void;
303
+ /** Layer messages over the active bundle. They merge with earlier overrides and survive {@link use}. */
304
+ override(messages: Partial<NxeMessages>): void;
305
+ /** Drop every override added since bootstrap; the ones in the configuration stay. */
306
+ clearOverrides(): void;
307
+ /**
308
+ * One message, with `{0}`, `{1}`... replaced by `args`. Reactive: reading it in a template or a
309
+ * `computed` subscribes that consumer to the language.
310
+ */
311
+ t(key: NxeMessageKey, ...args: readonly unknown[]): string;
312
+ /** Fill `{n}` placeholders; one without an argument is left as written. */
313
+ static format(template: string, args: readonly unknown[]): string;
314
+ private setLocale;
315
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeMessageService, never>;
316
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeMessageService>;
317
+ }
318
+ /**
319
+ * Registers the library's messages for the application:
320
+ *
321
+ * ```ts
322
+ * provideNxeMessages({ locale: 'id', overrides: { 'grid.noData': 'Belum ada data' } })
323
+ * ```
324
+ *
325
+ * With `separators` set it also provides {@link NXE_NUMBER_SEPARATORS} as a live view of the active
326
+ * locale's separators, so grids and number boxes go from `1,234.5` to `1.234,5` with the language.
327
+ */
328
+ declare function provideNxeMessages(config?: NxeMessagesConfig): EnvironmentProviders;
25
329
 
26
330
  /** A single failed validation rule. */
27
331
  interface NxeBrokenRule {
@@ -47,35 +351,40 @@ interface NxeValidationTarget {
47
351
  getValue(): unknown;
48
352
  validationGroup(): string | undefined;
49
353
  setValidationError(message: string | null): void;
354
+ /**
355
+ * Tell the editor whether a `required` rule applies, so it can render `aria-required`.
356
+ * Optional: a target predating this simply does not advertise the requirement.
357
+ */
358
+ setRequired?(required: boolean): void;
50
359
  }
51
360
  /** DI token the editor provides so its nested `nxe-validator` can adapt it. */
52
361
  declare const NXE_VALIDATION_TARGET: InjectionToken<NxeValidationTarget>;
53
362
  /** A member registered in a validation group (an `nxe-validator`). */
54
363
  interface NxeValidationGroupMember {
55
364
  validate(): NxeValidationResult;
365
+ /** Clear the member's error state without validating. Optional for older members. */
366
+ reset?(): void;
56
367
  }
57
-
58
368
  /**
59
- * Signal-based `ControlValueAccessor` base for every nxe form editor
60
- * (`nxe-text-box`, `nxe-number-box`, `nxe-date-box`, `nxe-check-box`, `nxe-text-area`,
61
- * `nxe-select-box`, `nxe-tag-box`, `nxe-radio`, ...).
62
- *
63
- * It supports BOTH template-driven (`[(ngModel)]`) and reactive (`formControlName`) forms
64
- * transparently, as well as DevExtreme-style `[value]` / `[(value)]` two-way binding, and
65
- * emits the DevExtreme-shaped {@link NxeValueChangedEvent} from `onValueChanged`.
66
- *
67
- * Concrete components MUST register themselves as the value accessor, e.g.:
68
- * ```ts
69
- * @Component({
70
- * selector: 'nxe-text-box',
71
- * providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NxeTextBoxComponent), multi: true }],
72
- * ...
73
- * })
74
- * export class NxeTextBoxComponent extends NxeFormControlBase<string> { ... }
75
- * ```
369
+ * An `nxe-validation-group` ancestor, exposed so a validator or a button inside it can join it
370
+ * without naming a group.
76
371
  *
77
- * Subclasses call {@link commitValue} on user interaction and {@link markAsTouched} on blur.
372
+ * DevExtreme lets a group be addressed two ways: by a string name shared between a validator and
373
+ * a button, or structurally by wrapping both in a `dxValidationGroup`. The string form is what
374
+ * the consuming applications use; this token is the structural one, and an explicit string
375
+ * always wins over it, as in dx.
78
376
  */
377
+ interface NxeValidationGroupScope {
378
+ /** Opaque, unique per instance — never collides with an application's own group names. */
379
+ readonly groupKey: string;
380
+ }
381
+ declare const NXE_VALIDATION_GROUP: InjectionToken<NxeValidationGroupScope>;
382
+ /** DevExtreme-shaped `onValidated` payload. */
383
+ interface NxeValidatedEvent extends NxeValidationResult {
384
+ value: unknown;
385
+ validationGroup: string;
386
+ }
387
+
79
388
  declare abstract class NxeFormControlBase<T> implements ControlValueAccessor, NxeValidationTarget {
80
389
  protected readonly elementRef: ElementRef<HTMLElement>;
81
390
  /**
@@ -85,28 +394,128 @@ declare abstract class NxeFormControlBase<T> implements ControlValueAccessor, Nx
85
394
  protected readonly ngZone: NgZone;
86
395
  /** Application-wide defaults; each editor resolves `binding ?? this ?? literal`. */
87
396
  protected readonly nxeDefaults: _nexterajs_ui_core.NxeDefaultOptions;
397
+ /** The library's runtime-switchable messages; read them in a template or a computed. */
398
+ protected readonly nxeMessages: NxeMessageService;
88
399
  /**
89
400
  * The current value — single source of truth. Two-way bindable as `[(value)]` (DevExtreme
90
401
  * parity) and also driven by `writeValue` for `ngModel`/`formControlName`.
91
402
  */
92
- readonly value: _angular_core.ModelSignal<T>;
403
+ readonly value: _angular_core.ModelSignal<T | null>;
93
404
  /** Disabled via the `[disabled]` input (DevExtreme parity); OR-combined with forms disabled. */
94
405
  readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
95
406
  private readonly disabledByForm;
96
407
  /** Effective disabled state (input OR reactive-forms `setDisabledState`). */
97
408
  readonly disabled: _angular_core.Signal<boolean>;
98
409
  /** Read-only state (DevExtreme `[readOnly]`). */
99
- readonly readOnly: _angular_core.InputSignalWithTransform<boolean, unknown>;
410
+ readonly readOnlyInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
411
+ /**
412
+ * Lower-case spelling of {@link readOnlyInput}: it is the name Signal Forms (`[formField]`)
413
+ * binds a `readonly()` rule to, and the HTML attribute name.
414
+ */
415
+ readonly readonlyInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
416
+ /** Effective read-only state: `readOnly` OR `readonly`. */
417
+ readonly readOnly: _angular_core.Signal<boolean>;
418
+ /**
419
+ * Signal Forms hides a field with `hidden()` and binds it by this name; also usable on its own.
420
+ * Hides the host, like `visible=false`.
421
+ */
422
+ readonly hiddenInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
423
+ /**
424
+ * Signal Forms state, bound by name when the editor carries `[formField]` (and settable by hand).
425
+ * `invalid` and `errors` put the editor in its invalid state (`nxe-invalid`, `aria-invalid`) once
426
+ * it is {@link touched}; the message text is `nxe-form-field`'s job.
427
+ */
428
+ readonly invalidInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
429
+ readonly errorsInput: _angular_core.InputSignal<readonly {
430
+ readonly kind: string;
431
+ readonly message?: string;
432
+ }[] | null | undefined>;
433
+ protected readonly touchedInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
100
434
  /** Validation group this editor belongs to (its nested `nxe-validator` registers here). */
101
- readonly validationGroupInput: _angular_core.InputSignal<string>;
435
+ readonly validationGroupInput: _angular_core.InputSignal<string | undefined>;
436
+ /**
437
+ * `id` for the INNER control, not the host.
438
+ *
439
+ * A caption written as `<label for="x">` has to reach the focusable element, and the host of
440
+ * a custom element is not it. Without this an editor cannot be labelled at all, which is why
441
+ * `aria-label` sits beside it: one of the two has to be available.
442
+ */
443
+ readonly inputId: _angular_core.InputSignal<string | undefined>;
444
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
445
+ readonly ariaLabelledBy: _angular_core.InputSignal<string | undefined>;
446
+ /** Stable per instance, so the inner control always has an id something can point at. */
447
+ private readonly fallbackId;
448
+ readonly controlId: _angular_core.Signal<string>;
449
+ /**
450
+ * Ids for a popup listbox and its options.
451
+ *
452
+ * `aria-activedescendant` is how a combobox says which option is current while focus stays in
453
+ * the text field, and it can only point at an id — so the options need stable ones.
454
+ */
455
+ panelId(): string;
456
+ optionId(index: number): string;
457
+ /**
458
+ * Whether a nested validator carries a `required` rule.
459
+ *
460
+ * Set by the validator rather than declared on the editor: the rule is where the requirement
461
+ * is actually stated, and duplicating it as an input would let the two disagree.
462
+ */
463
+ private readonly requiredByRule;
464
+ /**
465
+ * A `required` input, which is what Signal Forms binds a `required()` rule to, so a form that
466
+ * is not driven by `nxe-validator` can state it too.
467
+ */
468
+ readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
469
+ /** Whether the editor is required: the `required` input OR a nested validator's `required` rule. */
470
+ readonly required: _angular_core.Signal<boolean>;
471
+ setRequired(value: boolean): void;
102
472
  /** The current validation error message (set by a nested `nxe-validator`), or null. */
103
- readonly validationError: _angular_core.WritableSignal<string>;
104
- /** Whether the control has been blurred at least once. */
105
- readonly touched: _angular_core.WritableSignal<boolean>;
473
+ readonly validationError: _angular_core.WritableSignal<string | null>;
474
+ private readonly touchedByUser;
475
+ /** Whether the control has been blurred at least once, or a form says the field was touched. */
476
+ readonly touched: _angular_core.Signal<boolean>;
477
+ /**
478
+ * Whether the editor shows its invalid look: a nested validator's message, or a form's
479
+ * `invalid`/`errors` once the field is touched (so an untouched, empty required field is not red).
480
+ */
481
+ readonly invalidState: _angular_core.Signal<boolean>;
106
482
  /** Whether the value has been changed by the user at least once. */
107
483
  readonly dirty: _angular_core.WritableSignal<boolean>;
108
484
  /** DevExtreme-compatible value-change event. */
109
485
  readonly onValueChanged: _angular_core.OutputEmitterRef<NxeValueChangedEvent<T>>;
486
+ /**
487
+ * dx's keyboard, focus and input events.
488
+ *
489
+ * Native events already reach the host, so these are not about capability — they are about
490
+ * the call site. A migrated `(onEnterKey)` handler should keep working without being
491
+ * rewritten as a `(keydown)` with a key check, and `onEnterKey` in particular has no native
492
+ * equivalent at all.
493
+ */
494
+ readonly onKeyDown: _angular_core.OutputEmitterRef<NxeEditorEvent>;
495
+ readonly onKeyUp: _angular_core.OutputEmitterRef<NxeEditorEvent>;
496
+ readonly onEnterKey: _angular_core.OutputEmitterRef<NxeEditorEvent>;
497
+ readonly onInput: _angular_core.OutputEmitterRef<NxeEditorEvent>;
498
+ readonly onChange: _angular_core.OutputEmitterRef<NxeEditorEvent>;
499
+ readonly onFocusIn: _angular_core.OutputEmitterRef<NxeEditorEvent>;
500
+ readonly onFocusOut: _angular_core.OutputEmitterRef<NxeEditorEvent>;
501
+ /**
502
+ * When a typed value is committed: dx's `'change'` (on blur), `'input'` (per keystroke) or
503
+ * `'keyup'`.
504
+ *
505
+ * Honoured by the text editors. The number and date boxes stay on `'change'` whatever this
506
+ * says, because their displayed text is derived from the parsed value: committing mid-entry
507
+ * would rewrite the field while the user is still typing into it.
508
+ */
509
+ readonly valueChangeEvent: _angular_core.InputSignal<"keyup" | "input" | "change">;
510
+ /** dx universal widget options. */
511
+ readonly hint: _angular_core.InputSignal<string | undefined>;
512
+ readonly width: _angular_core.InputSignal<string | number | undefined>;
513
+ readonly visible: _angular_core.InputSignalWithTransform<boolean, unknown>;
514
+ readonly tabIndex: _angular_core.InputSignal<number | undefined>;
515
+ readonly elementAttr: _angular_core.InputSignal<Record<string, string> | undefined>;
516
+ protected readonly widthStyle: _angular_core.Signal<string | null>;
517
+ protected readonly elementAttrClass: _angular_core.Signal<string | null>;
518
+ protected readonly elementAttrId: _angular_core.Signal<string | null>;
110
519
  private _onChange;
111
520
  private _onTouched;
112
521
  /** Host element (the DevExtreme event payload `element`). */
@@ -124,10 +533,42 @@ declare abstract class NxeFormControlBase<T> implements ControlValueAccessor, Nx
124
533
  * DevExtreme-shaped `onValueChanged`. No-op when the value is unchanged.
125
534
  */
126
535
  protected commitValue(next: T | null, event?: Event | null): void;
536
+ /**
537
+ * Commit whatever the user has typed but not yet committed, now and synchronously.
538
+ *
539
+ * With the default `valueChangeEvent` a typed value commits on blur, so a programmatic submit
540
+ * (or anything else that reads the model while the field still has focus) would see the old
541
+ * value. Call this first. It is a no-op when nothing is pending, so it never emits
542
+ * `onValueChanged` twice for one change, and it does not blur the field or mark it touched.
543
+ */
544
+ commit(): void;
545
+ /** Alias of {@link commit}. */
546
+ flush(): void;
547
+ /**
548
+ * Editors with text that can be typed but not yet committed override this to commit it through
549
+ * {@link commitValue}. The default is for editors that commit on every interaction.
550
+ */
551
+ protected commitPending(_event: Event | null): void;
552
+ /** Whether Enter in this editor commits the pending text. Multi-line editors narrow it. */
553
+ protected commitsOnEnter(_event: KeyboardEvent): boolean;
554
+ /**
555
+ * Re-emit a native event in dx's shape.
556
+ *
557
+ * `onEnterKey` is the one that earns its keep: it has no native equivalent, so every call
558
+ * site would otherwise carry its own key check.
559
+ */
560
+ protected emitEditorEvent(kind: NxeEditorEventKind, event: Event): void;
561
+ /**
562
+ * Commit `next` if `valueChangeEvent` says this is the moment.
563
+ *
564
+ * Blur always commits, whatever the mode: a value the user typed and then left must not be
565
+ * discarded because the configured event never fired.
566
+ */
567
+ protected commitOn(kind: 'input' | 'keyup' | 'change', next: T | null, event: Event): void;
127
568
  /** Mark the control as touched (e.g. on blur), notifying Angular forms exactly once. */
128
569
  protected markAsTouched(): void;
129
570
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeFormControlBase<any>, never>;
130
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeFormControlBase<any>, never, never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "validationGroupInput": { "alias": "validationGroup"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onValueChanged": "onValueChanged"; }, never, never, true, never>;
571
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NxeFormControlBase<any>, never, never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "readOnlyInput": { "alias": "readOnly"; "required": false; "isSignal": true; }; "readonlyInput": { "alias": "readonly"; "required": false; "isSignal": true; }; "hiddenInput": { "alias": "hidden"; "required": false; "isSignal": true; }; "invalidInput": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorsInput": { "alias": "errors"; "required": false; "isSignal": true; }; "touchedInput": { "alias": "touched"; "required": false; "isSignal": true; }; "validationGroupInput": { "alias": "validationGroup"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledBy": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "valueChangeEvent": { "alias": "valueChangeEvent"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "elementAttr": { "alias": "elementAttr"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onValueChanged": "onValueChanged"; "onKeyDown": "onKeyDown"; "onKeyUp": "onKeyUp"; "onEnterKey": "onEnterKey"; "onInput": "onInput"; "onChange": "onChange"; "onFocusIn": "onFocusIn"; "onFocusOut": "onFocusOut"; }, never, never, true, never>;
131
572
  }
132
573
 
133
574
  /**
@@ -196,6 +637,12 @@ interface NxeGridDefaultOptions {
196
637
  showBorders?: boolean;
197
638
  wordWrapEnabled?: boolean;
198
639
  noDataText?: string;
640
+ /**
641
+ * Widget-mode column resizing: when a manual resize leaves the columns narrower than the grid,
642
+ * the trailing column takes the rest, while dragging and after, so no blank strip shows on the
643
+ * right. dx (and the default) lets the table end short of the grid.
644
+ */
645
+ resizeFillsGrid?: boolean;
199
646
  }
200
647
  interface NxePickerDefaultOptions {
201
648
  displayExpr?: string;
@@ -219,10 +666,12 @@ interface NxeDefaultOptions {
219
666
  readonly dateBox?: {
220
667
  displayFormat?: string;
221
668
  placeholder?: string;
669
+ showClearButton?: boolean;
222
670
  };
223
671
  readonly textBox?: {
224
672
  placeholder?: string;
225
673
  hoverStateEnabled?: boolean;
674
+ showClearButton?: boolean;
226
675
  };
227
676
  readonly textArea?: {
228
677
  placeholder?: string;
@@ -230,6 +679,7 @@ interface NxeDefaultOptions {
230
679
  };
231
680
  readonly numberBox?: {
232
681
  format?: string;
682
+ showClearButton?: boolean;
233
683
  };
234
684
  readonly button?: {
235
685
  focusStateEnabled?: boolean;
@@ -277,7 +727,7 @@ declare class NxeTemplateDirective {
277
727
  /** Attribute-form name (`nxeTemplate="name"`); empty in microsyntax usage. */
278
728
  readonly attrName: _angular_core.InputSignal<string>;
279
729
  /** Microsyntax-form name (`*nxeTemplate="let x of 'name'"` binds `nxeTemplateOf`). */
280
- readonly ofName: _angular_core.InputSignal<string>;
730
+ readonly ofName: _angular_core.InputSignal<string | undefined>;
281
731
  /** The template's lookup name, whichever form supplied it. */
282
732
  readonly name: _angular_core.Signal<string>;
283
733
  readonly templateRef: TemplateRef<unknown>;
@@ -306,6 +756,24 @@ declare function coerceArray<T>(value: T | readonly T[] | null | undefined): T[]
306
756
  */
307
757
  declare function nxeOptionalBoolean(value: unknown): boolean | undefined;
308
758
 
759
+ /**
760
+ * DevExtreme's `displayExpr` / `valueExpr` / `searchExpr` accessor.
761
+ *
762
+ * dx accepts four spellings and the library accepted one — a flat property name — so a dotted
763
+ * path silently read `item['user.name']` and returned undefined. Silent, because an accessor
764
+ * that misses looks exactly like a field that is empty.
765
+ *
766
+ * undefined / '' the item itself (dx: no expression)
767
+ * 'this' the item itself (dx's documented sentinel)
768
+ * 'user.name' a dotted path
769
+ * (item) => ... a function accessor
770
+ */
771
+ type NxeExpr<T = unknown> = string | ((item: T) => unknown) | undefined | null;
772
+ /** Resolve `expr` against `item`. */
773
+ declare function nxeResolveExpr<T = unknown>(expr: NxeExpr<T>, item: T): unknown;
774
+ /** Resolve `expr` and render it as display text: `null`/`undefined` become the empty string. */
775
+ declare function nxeResolveText<T = unknown>(expr: NxeExpr<T>, item: T): string;
776
+
309
777
  /**
310
778
  * Root registry mapping a `validationGroup` string to the `nxe-validator`s in it, mirroring
311
779
  * DevExtreme's global ValidationEngine.
@@ -318,11 +786,28 @@ declare class NxeValidationGroupRegistry {
318
786
  private readonly groups;
319
787
  register(group: string, member: NxeValidationGroupMember): void;
320
788
  unregister(group: string, member: NxeValidationGroupMember): void;
789
+ /**
790
+ * Clear every member's error state without validating.
791
+ *
792
+ * dx's `ValidationGroup.reset()`. The distinction from `validate()` matters after a Cancel:
793
+ * the fields should stop showing errors, not be re-checked and light up again.
794
+ */
795
+ reset(group: string): void;
321
796
  /** Validate every member of the group; valid (and empty) groups return `isValid: true`. */
322
797
  validate(group: string): NxeValidationResult;
323
798
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NxeValidationGroupRegistry, never>;
324
799
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<NxeValidationGroupRegistry>;
325
800
  }
326
801
 
327
- export { NXE_DEFAULT_OPTIONS, NXE_OPTION, NXE_VALIDATION_TARGET, NxeConfigOptionBase, NxeFormControlBase, NxeTemplateDirective, NxeValidationGroupRegistry, coerceArray, nxeOptionalBoolean };
328
- export type { NxeBrokenRule, NxeConfigOption, NxeDefaultOptions, NxeGridDefaultOptions, NxePickerDefaultOptions, NxeValidationGroupMember, NxeValidationResult, NxeValidationTarget, NxeValueChangedEvent };
802
+ /** Indonesian bundle (Bahasa Indonesia), checked against the English key set. */
803
+ declare const NXE_MESSAGES_ID: NxeMessages;
804
+
805
+ /**
806
+ * A byte count as the library writes it in the active language: "512 b", "1.5 Kb", "2.0 Mb" in English,
807
+ * "512 B", "1,5 KB" in Indonesian (the `uploader.size*` messages). Used by the file input and by the
808
+ * file-size message of `nxe-form-field`.
809
+ */
810
+ declare function nxeFormatFileSize(bytes: number, messages: NxeMessageService): string;
811
+
812
+ export { NXE_DEFAULT_OPTIONS, NXE_MESSAGES, NXE_MESSAGES_EN, NXE_MESSAGES_ID, NXE_OPTION, NXE_VALIDATION_GROUP, NXE_VALIDATION_TARGET, NxeConfigOptionBase, NxeFormControlBase, NxeMessageService, NxeTemplateDirective, NxeValidationGroupRegistry, coerceArray, nxeFormatFileSize, nxeOptionalBoolean, nxeResolveExpr, nxeResolveText, provideNxeMessages };
813
+ export type { NxeBrokenRule, NxeConfigOption, NxeDefaultOptions, NxeEditorEvent, NxeEditorEventKind, NxeExpr, NxeGridDefaultOptions, NxeMessageKey, NxeMessages, NxeMessagesConfig, NxePickerDefaultOptions, NxeValidatedEvent, NxeValidationGroupMember, NxeValidationGroupScope, NxeValidationResult, NxeValidationTarget, NxeValueChangedEvent };