@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
@@ -9,10 +9,12 @@ import { InjectionToken } from '@angular/core';
9
9
  // #,##0.#####'%' — grouping, 0–5 fraction digits, literal '%' suffix (NO ×100)
10
10
  // #0 — integer, no grouping
11
11
  // #,##0 — integer with grouping
12
+ // #,##0.00;(#,##0.00) — a negative section: below zero renders as (1,234.50)
12
13
  // (empty) — raw number, no grouping
13
14
  //
14
15
  // Tokens: `#` optional digit, `0` required digit, `,` enable grouping (size 3), `.` decimal point
15
- // (count of `0` after it = min fraction digits, count of `0`+`#` = max), `'…'` verbatim literal.
16
+ // (count of `0` after it = min fraction digits, count of `0`+`#` = max), `'…'` verbatim literal,
17
+ // `;` (unquoted) starts the negative section.
16
18
  /** dx's cap on the significant digits a formatted number carries (ldml/number.js:21). */
17
19
  const MAXIMUM_NUMBER_LENGTH = 15;
18
20
  /** Parse an LDML pattern into a {@link NxeParsedNumberFormat}, or `null` for raw (no format). */
@@ -20,6 +22,13 @@ function parseNumberFormat(pattern) {
20
22
  if (!pattern) {
21
23
  return null;
22
24
  }
25
+ // dx getSignParts: `positive;negative`. Only an unquoted `;` splits, so `'a;b'#0` stays a literal.
26
+ const split = sectionBreak(pattern);
27
+ if (split !== -1) {
28
+ const positive = parseNumberFormat(pattern.slice(0, split));
29
+ const negative = positive && parseNumberFormat(pattern.slice(split + 1));
30
+ return positive && negative ? { ...positive, negative } : positive;
31
+ }
23
32
  let prefix = '';
24
33
  let suffix = '';
25
34
  let core = '';
@@ -67,6 +76,19 @@ function parseNumberFormat(pattern) {
67
76
  maxFrac: count(fracPart, /[#0]/g),
68
77
  };
69
78
  }
79
+ /** Index of the first `;` outside a quoted literal, or -1. */
80
+ function sectionBreak(pattern) {
81
+ let inQuote = false;
82
+ for (let i = 0; i < pattern.length; i++) {
83
+ if (pattern[i] === "'") {
84
+ inQuote = !inQuote;
85
+ }
86
+ else if (pattern[i] === ';' && !inQuote) {
87
+ return i;
88
+ }
89
+ }
90
+ return -1;
91
+ }
70
92
  /**
71
93
  * Insert `sep` every `size` digits from the right.
72
94
  *
@@ -120,7 +142,14 @@ function formatNumber(value, fmt, separators = NXE_EN_US_SEPARATORS) {
120
142
  return String(value);
121
143
  }
122
144
  const negative = value < 0;
123
- const abs = Math.abs(value);
145
+ if (negative && fmt.negative) {
146
+ const section = fmt.negative;
147
+ return `${section.prefix}${formatDigits(Math.abs(value), section, separators)}${section.suffix}`;
148
+ }
149
+ return `${fmt.prefix}${negative ? '-' : ''}${formatDigits(Math.abs(value), fmt, separators)}${fmt.suffix}`;
150
+ }
151
+ /** The digits of `abs` under `fmt`, without its prefix, suffix or sign. */
152
+ function formatDigits(abs, fmt, separators) {
124
153
  // dx MAXIMUM_NUMBER_LENGTH (ldml/number.js:21, :152-153): the fraction gets only what is left
125
154
  // of 15 significant digits after the integer part, `fitIntoRange(maxFloat, 0, 15 - intLen)`.
126
155
  // Without it a 15-place mask printed 10/3 % as 3.333333333333333 rather than dx's
@@ -145,8 +174,7 @@ function formatNumber(value, fmt, separators = NXE_EN_US_SEPARATORS) {
145
174
  if (fmt.useGrouping) {
146
175
  intStr = groupDigits(intStr, fmt.groupSize ?? 3, separators.group);
147
176
  }
148
- const body = fracStr ? `${intStr}${separators.decimal}${fracStr}` : intStr;
149
- return `${fmt.prefix}${negative ? '-' : ''}${body}${fmt.suffix}`;
177
+ return fracStr ? `${intStr}${separators.decimal}${fracStr}` : intStr;
150
178
  }
151
179
  /** Parse a (possibly formatted) string into a number; strips grouping/literals. Empty → `null`. */
152
180
  function parseNumber(text, separators = NXE_EN_US_SEPARATORS) {
@@ -170,7 +198,13 @@ function parseNumber(text, separators = NXE_EN_US_SEPARATORS) {
170
198
  return null;
171
199
  }
172
200
  const num = parseFloat(normalized);
173
- return isNaN(num) ? null : num;
201
+ if (isNaN(num)) {
202
+ return null;
203
+ }
204
+ // `(1,234.50)` is how a `#,##0.00;(#,##0.00)` pattern writes a negative, so it reads back as one.
205
+ const open = text.indexOf('(');
206
+ const close = text.lastIndexOf(')');
207
+ return open !== -1 && close > open ? -Math.abs(num) : num;
174
208
  }
175
209
 
176
210
  // Luxon-based date parsing/formatting/serialization for nxe-date-box.
@@ -243,11 +277,11 @@ function isAllDayRange(start, end) {
243
277
  return !hasTimeOfDay(start) && !hasTimeOfDay(end);
244
278
  }
245
279
  /** Format a DateTime for display per `displayFormat` (DevExtreme tokens map 1:1 to Luxon). */
246
- function formatDisplay(dt, displayFormat) {
280
+ function formatDisplay(dt, displayFormat, locale) {
247
281
  if (!dt) {
248
282
  return '';
249
283
  }
250
- return dt.toFormat(displayFormat || NXE_DEFAULT_DISPLAY_FORMAT);
284
+ return (locale ? dt.setLocale(locale) : dt).toFormat(displayFormat || NXE_DEFAULT_DISPLAY_FORMAT);
251
285
  }
252
286
  /**
253
287
  * Fixed-width tokens swapped for their variable-width twins in the lenient retry below. Luxon's
@@ -291,7 +325,7 @@ function dateOnlyFormat(format) {
291
325
  * rejects the text outright — nulls the whole field. Callers editing an existing value should pass
292
326
  * it; the parameter is optional so the date-only call sites need no change.
293
327
  */
294
- function parseDisplay(text, displayFormat, base) {
328
+ function parseDisplay(text, displayFormat, base, locale) {
295
329
  const trimmed = (text ?? '').trim();
296
330
  if (!trimmed) {
297
331
  return null;
@@ -299,7 +333,7 @@ function parseDisplay(text, displayFormat, base) {
299
333
  const format = displayFormat || NXE_DEFAULT_DISPLAY_FORMAT;
300
334
  const lenient = lenientFormat(format);
301
335
  for (const candidate of lenient === format ? [format] : [format, lenient]) {
302
- const dt = DateTime.fromFormat(trimmed, candidate);
336
+ const dt = DateTime.fromFormat(trimmed, candidate, locale ? { locale } : undefined);
303
337
  if (dt.isValid) {
304
338
  return dt;
305
339
  }
@@ -308,7 +342,7 @@ function parseDisplay(text, displayFormat, base) {
308
342
  if (dateOnly) {
309
343
  const lenientDateOnly = lenientFormat(dateOnly);
310
344
  for (const candidate of lenientDateOnly === dateOnly ? [dateOnly] : [dateOnly, lenientDateOnly]) {
311
- const dt = DateTime.fromFormat(trimmed, candidate);
345
+ const dt = DateTime.fromFormat(trimmed, candidate, locale ? { locale } : undefined);
312
346
  if (dt.isValid) {
313
347
  return base?.isValid ? dt.set({ hour: base.hour, minute: base.minute, second: base.second }) : dt;
314
348
  }
@@ -377,11 +411,69 @@ function buildCalendarWeeks(viewMonth) {
377
411
  */
378
412
  const NXE_NUMBER_SEPARATORS = new InjectionToken('NXE_NUMBER_SEPARATORS', { providedIn: 'root', factory: () => NXE_EN_US_SEPARATORS });
379
413
 
414
+ // Currency display for nxe-number-box, mirroring the StreamB2B `sbMoney` rules
415
+ // (docs/03-design-system/patterns.md section 9): `IDR 1.351.000`, `IDR 1.351.000,50` (id),
416
+ // `IDR 1,351,000.50` (en). The ISO 4217 code goes before the amount, rounding is half away from
417
+ // zero, a minus sign goes before the code (`-IDR 1.000`), and an amount that rounds to zero
418
+ // carries no sign.
419
+ const ZERO_DIGITS = ['BIF', 'CLP', 'DJF', 'GNF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'UGX', 'UYI', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'];
420
+ const THREE_DIGITS = ['BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND'];
421
+ const CURRENCIES = {
422
+ IDR: { digits: 2, trimZeroFraction: true },
423
+ ...Object.fromEntries(ZERO_DIGITS.map((code) => [code, { digits: 0, trimZeroFraction: false }])),
424
+ ...Object.fromEntries(THREE_DIGITS.map((code) => [code, { digits: 3, trimZeroFraction: false }])),
425
+ };
426
+ const DEFAULT_CURRENCY = { digits: 2, trimZeroFraction: false };
427
+ /** Normalise a currency code: trimmed and upper-cased; `''` when absent. */
428
+ function nxeCurrencyCode(code) {
429
+ return (code ?? '').trim().toUpperCase();
430
+ }
431
+ /**
432
+ * Display rules for a currency code. Unknown codes have 2 minor units. `decimals` (the currency's
433
+ * decimals from reference data, when the app knows them) overrides the built-in table.
434
+ */
435
+ function nxeCurrencyInfo(code, decimals) {
436
+ const known = CURRENCIES[nxeCurrencyCode(code)] ?? DEFAULT_CURRENCY;
437
+ if (decimals == null || !Number.isFinite(decimals)) {
438
+ return known;
439
+ }
440
+ const digits = Math.max(0, Math.min(10, Math.trunc(decimals)));
441
+ return { digits, trimZeroFraction: known.trimZeroFraction && digits > 0 };
442
+ }
443
+ /** The number pattern behind a currency: grouped, `digits` fraction digits at most. */
444
+ function nxeCurrencyNumberFormat(code, decimals) {
445
+ const info = nxeCurrencyInfo(code, decimals);
446
+ return parseNumberFormat(info.digits ? `#,##0.${'0'.repeat(info.digits)}` : '#,##0');
447
+ }
448
+ /**
449
+ * Format an amount as `CODE 1.234,50`. `null`/`NaN` give `''`. With a `pattern` (an already parsed
450
+ * number format) that pattern shapes the number instead of the currency's own digits.
451
+ */
452
+ function formatCurrency(value, code, separators = NXE_EN_US_SEPARATORS, options = {}) {
453
+ if (value == null || typeof value !== 'number' || isNaN(value)) {
454
+ return '';
455
+ }
456
+ const info = nxeCurrencyInfo(code, options.decimals);
457
+ let fmt = options.pattern ?? nxeCurrencyNumberFormat(code, options.decimals);
458
+ const rounded = roundHalfAwayFromZero(value, fmt.maxFrac);
459
+ if (!options.pattern && info.trimZeroFraction && Number.isInteger(rounded)) {
460
+ fmt = { ...fmt, minFrac: 0, maxFrac: 0 };
461
+ }
462
+ const currency = nxeCurrencyCode(code);
463
+ const negative = rounded < 0;
464
+ // A pattern with a negative section (`#,##0.00;(#,##0.00)`) writes its own sign: `USD (1,234.50)`.
465
+ if (negative && fmt.negative) {
466
+ return `${currency ? `${currency} ` : ''}${formatNumber(rounded, fmt, separators)}`;
467
+ }
468
+ const body = formatNumber(Math.abs(rounded), fmt, separators);
469
+ return `${negative ? '-' : ''}${currency ? `${currency} ` : ''}${body}`;
470
+ }
471
+
380
472
  // @nexterajs/ui/intl — public API.
381
473
 
382
474
  /**
383
475
  * Generated bundle index. Do not edit.
384
476
  */
385
477
 
386
- export { NXE_DATE_SERIALIZATION_FORMAT, NXE_DEFAULT_DATETIME_DISPLAY_FORMAT, NXE_DEFAULT_DISPLAY_FORMAT, NXE_DEFAULT_TIME_DISPLAY_FORMAT, NXE_EN_US_SEPARATORS, NXE_ID_SEPARATORS, NXE_NUMBER_SEPARATORS, buildCalendarWeeks, buildPeriodCells, formatDisplay, formatNumber, hasTimeOfDay, isAllDayRange, parseDateValue, parseDisplay, parseNumber, parseNumberFormat, roundHalfAwayFromZero, serializeDate };
478
+ export { NXE_DATE_SERIALIZATION_FORMAT, NXE_DEFAULT_DATETIME_DISPLAY_FORMAT, NXE_DEFAULT_DISPLAY_FORMAT, NXE_DEFAULT_TIME_DISPLAY_FORMAT, NXE_EN_US_SEPARATORS, NXE_ID_SEPARATORS, NXE_NUMBER_SEPARATORS, buildCalendarWeeks, buildPeriodCells, formatCurrency, formatDisplay, formatNumber, hasTimeOfDay, isAllDayRange, nxeCurrencyCode, nxeCurrencyInfo, nxeCurrencyNumberFormat, parseDateValue, parseDisplay, parseNumber, parseNumberFormat, roundHalfAwayFromZero, serializeDate };
387
479
  //# sourceMappingURL=nexterajs-ui-intl.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"nexterajs-ui-intl.mjs","sources":["../../../projects/nextera-ui/intl/src/lib/number-box/nxe-number-format.ts","../../../projects/nextera-ui/intl/src/lib/date-box/nxe-date-format.ts","../../../projects/nextera-ui/intl/src/lib/number-box/nxe-number-locale.ts","../../../projects/nextera-ui/intl/src/public-api.ts","../../../projects/nextera-ui/intl/src/nexterajs-ui-intl.ts"],"sourcesContent":["// DevExtreme LDML-style number format engine for nxe-number-box.\r\n//\r\n// Supports the patterns actually used in this codebase:\r\n// #,##0.00 — grouping, exactly 2 fraction digits\r\n// #,##0.00000 — grouping, exactly 5 fraction digits\r\n// #,##0.#####'%' — grouping, 0–5 fraction digits, literal '%' suffix (NO ×100)\r\n// #0 — integer, no grouping\r\n// #,##0 — integer with grouping\r\n// (empty) — raw number, no grouping\r\n//\r\n// Tokens: `#` optional digit, `0` required digit, `,` enable grouping (size 3), `.` decimal point\r\n// (count of `0` after it = min fraction digits, count of `0`+`#` = max), `'…'` verbatim literal.\r\n\r\nexport interface NxeParsedNumberFormat {\r\n prefix: string;\r\n suffix: string;\r\n useGrouping: boolean;\r\n /**\r\n * Digits per group, read from the pattern: `#,##0` is 3, `#,#0` is 2. Optional because\r\n * callers construct this shape by hand as well as through {@link parseNumberFormat};\r\n * omitted means dx's usual 3.\r\n */\r\n groupSize?: number;\r\n minInt: number;\r\n minFrac: number;\r\n maxFrac: number;\r\n}\r\n\r\n/** dx's cap on the significant digits a formatted number carries (ldml/number.js:21). */\r\nconst MAXIMUM_NUMBER_LENGTH = 15;\r\n\r\n/** Parse an LDML pattern into a {@link NxeParsedNumberFormat}, or `null` for raw (no format). */\r\nexport function parseNumberFormat(pattern: string | undefined | null): NxeParsedNumberFormat | null {\r\n if (!pattern) {\r\n return null;\r\n }\r\n let prefix = '';\r\n let suffix = '';\r\n let core = '';\r\n let inQuote = false;\r\n let seenCore = false;\r\n for (const ch of pattern) {\r\n if (ch === \"'\") {\r\n inQuote = !inQuote;\r\n continue;\r\n }\r\n const isToken = !inQuote && (ch === '#' || ch === '0' || ch === ',' || ch === '.');\r\n if (isToken) {\r\n core += ch;\r\n seenCore = true;\r\n } else if (!seenCore) {\r\n prefix += ch;\r\n } else {\r\n suffix += ch;\r\n }\r\n }\r\n if (!core) {\r\n return null;\r\n }\r\n const dot = core.indexOf('.');\r\n const intPart = dot === -1 ? core : core.slice(0, dot);\r\n const fracPart = dot === -1 ? '' : core.slice(dot + 1);\r\n const count = (s: string, re: RegExp) => (s.match(re) || []).length;\r\n // The grouping SIZE comes from the pattern, not from a constant 3: dx reads the digits after\r\n // the last comma, so `#,##0` groups by 3 and `#,#0` groups by 2 (which renders 1234.5 as\r\n // \"12,34.5\"). Several consumer columns use the latter, most likely by accident - but it is\r\n // what their screens show today, so parity means reproducing it.\r\n const useGrouping = intPart.includes(',');\r\n const groupSize = useGrouping\r\n ? Math.max(1, count(intPart.slice(intPart.lastIndexOf(',') + 1), /[#0]/g))\r\n : 3;\r\n return {\r\n prefix,\r\n suffix,\r\n useGrouping,\r\n groupSize,\r\n minInt: Math.max(1, count(intPart, /0/g)),\r\n minFrac: count(fracPart, /0/g),\r\n maxFrac: count(fracPart, /[#0]/g),\r\n };\r\n}\r\n\r\n/**\r\n * Insert `sep` every `size` digits from the right.\r\n *\r\n * Written as a loop rather than a dynamic RegExp on purpose: the group size varies with the\r\n * pattern, and building a regex by interpolating into a template literal puts `\\B` and `\\d` one\r\n * missing backslash away from silently matching nothing.\r\n */\r\nfunction groupDigits(digits: string, size: number, sep: string): string {\r\n let out = '';\r\n for (let i = 0; i < digits.length; i++) {\r\n if (i > 0 && (digits.length - i) % size === 0) {\r\n out += sep;\r\n }\r\n out += digits[i];\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Render `value` with exactly `frac` fraction digits, from its SHORTEST decimal form.\r\n *\r\n * `toFixed` expands the binary value instead, so 1234567.891 at 14 digits becomes\r\n * \"1234567.89100000006147\" — the true double, and not what dx prints. Taking `String(value)`\r\n * (the shortest round-tripping decimal) and padding matches dx and is what a reader expects.\r\n * Exponential notation, which `String` produces below 1e-6, falls back to `toFixed`.\r\n */\r\nfunction toDecimalString(value: number, frac: number): string {\r\n const s = String(value);\r\n if (s.includes('e') || s.includes('E')) {\r\n return value.toFixed(frac);\r\n }\r\n const dot = s.indexOf('.');\r\n const intPart = dot === -1 ? s : s.slice(0, dot);\r\n const fracPart = dot === -1 ? '' : s.slice(dot + 1);\r\n return frac === 0 ? intPart : `${intPart}.${fracPart.slice(0, frac).padEnd(frac, '0')}`;\r\n}\r\n\r\n/** Round half-away-from-zero to `frac` fraction digits (DevExtreme rounding), fp-safe. */\r\nexport function roundHalfAwayFromZero(value: number, frac: number): number {\r\n const factor = Math.pow(10, frac);\r\n const rounded = Math.round(Math.abs(value) * factor + 1e-9) / factor;\r\n return value < 0 ? -rounded : rounded;\r\n}\r\n\r\n/** Format a number with the parsed pattern. `null`/`NaN` → `''`. */\r\n/**\r\n * The characters that separate groups and the fraction.\r\n *\r\n * The LDML pattern always writes `,` for grouping and `.` for the decimal point — that is the\r\n * pattern language, not the output. Which characters actually get rendered is a locale decision,\r\n * and it is the one that split this file: one consuming app needs `1,234.50`, another needs\r\n * `1.250.000,50`, and hardcoding either forces the other to fork.\r\n */\r\nexport interface NxeNumberSeparators {\r\n readonly group: string;\r\n readonly decimal: string;\r\n}\r\n\r\n/** DevExtreme's default, and this library's. */\r\nexport const NXE_EN_US_SEPARATORS: NxeNumberSeparators = { group: ',', decimal: '.' };\r\n\r\n/** Indonesian house style, used by several of the consuming applications. */\r\nexport const NXE_ID_SEPARATORS: NxeNumberSeparators = { group: '.', decimal: ',' };\r\n\r\nexport function formatNumber(\r\n value: number | null | undefined,\r\n fmt: NxeParsedNumberFormat | null,\r\n separators: NxeNumberSeparators = NXE_EN_US_SEPARATORS,\r\n): string {\r\n if (value == null || typeof value !== 'number' || isNaN(value)) {\r\n return '';\r\n }\r\n if (!fmt) {\r\n return String(value);\r\n }\r\n const negative = value < 0;\r\n const abs = Math.abs(value);\r\n // dx MAXIMUM_NUMBER_LENGTH (ldml/number.js:21, :152-153): the fraction gets only what is left\r\n // of 15 significant digits after the integer part, `fitIntoRange(maxFloat, 0, 15 - intLen)`.\r\n // Without it a 15-place mask printed 10/3 % as 3.333333333333333 rather than dx's\r\n // 3.33333333333333.\r\n const frac = Math.min(fmt.maxFrac, Math.max(0, MAXIMUM_NUMBER_LENGTH - String(Math.floor(abs)).length));\r\n const rounded = roundHalfAwayFromZero(abs, frac);\r\n const fixed = toDecimalString(rounded, frac);\r\n const parts = fixed.split('.');\r\n let intStr = parts[0];\r\n let fracStr = parts[1] ?? '';\r\n if (fmt.maxFrac > fmt.minFrac) {\r\n fracStr = fracStr.replace(/0+$/, '');\r\n }\r\n // Always, not only for optional digits: the cap can leave fewer places than the mask requires,\r\n // and dx's normalizeValueString pads those back with zeros.\r\n while (fracStr.length < fmt.minFrac) {\r\n fracStr += '0';\r\n }\r\n while (intStr.length < fmt.minInt) {\r\n intStr = '0' + intStr;\r\n }\r\n if (fmt.useGrouping) {\r\n intStr = groupDigits(intStr, fmt.groupSize ?? 3, separators.group);\r\n }\r\n const body = fracStr ? `${intStr}${separators.decimal}${fracStr}` : intStr;\r\n return `${fmt.prefix}${negative ? '-' : ''}${body}${fmt.suffix}`;\r\n}\r\n\r\n/** Parse a (possibly formatted) string into a number; strips grouping/literals. Empty → `null`. */\r\nexport function parseNumber(\r\n text: string | null | undefined,\r\n separators: NxeNumberSeparators = NXE_EN_US_SEPARATORS,\r\n): number | null {\r\n if (text == null) {\r\n return null;\r\n }\r\n // Strip everything that is not a digit, a sign, or one of this locale's separators, then\r\n // drop the group separator and normalise the decimal one to `.` for parseFloat.\r\n const keep = new Set([separators.group, separators.decimal]);\r\n let cleaned = '';\r\n for (const ch of text) {\r\n if ((ch >= '0' && ch <= '9') || ch === '-' || keep.has(ch)) {\r\n cleaned += ch;\r\n }\r\n }\r\n const normalized = cleaned\r\n .split(separators.group)\r\n .join('')\r\n .replace(separators.decimal, '.');\r\n\r\n if (normalized === '' || normalized === '-' || normalized === '.' || normalized === '-.') {\r\n return null;\r\n }\r\n const num = parseFloat(normalized);\r\n return isNaN(num) ? null : num;\r\n}\r\n","// Luxon-based date parsing/formatting/serialization for nxe-date-box.\r\n//\r\n// The app sets a global DevExtreme `dateSerializationFormat: \"yyyy-MM-ddTHH:mm:ss\"`, so the value\r\n// stored in the form control is an ISO-like wall-clock string (no zone, no millis). nxe-date-box\r\n// preserves that contract: it accepts such strings (and tolerates Date / full-ISO-with-Z from the\r\n// `defaultSystemSettings` directive) and emits the same `\"yyyy-MM-ddTHH:mm:ss\"` string.\r\n\r\nimport { DateTime } from 'luxon';\r\n\r\n/** The app-wide serialization format (matches DevExtreme `dateSerializationFormat`). */\r\nexport const NXE_DATE_SERIALIZATION_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss\";\r\n/** DevExtreme global default `displayFormat` (`dxDateBox.defaultOptions`). */\r\nexport const NXE_DEFAULT_DISPLAY_FORMAT = 'dd-MMM-yyyy';\r\n/** Default `displayFormat` for `type=\"datetime\"`. */\r\nexport const NXE_DEFAULT_DATETIME_DISPLAY_FORMAT = 'dd-MMM-yyyy HH:mm';\r\n/** Default `displayFormat` for `type=\"time\"`. */\r\nexport const NXE_DEFAULT_TIME_DISPLAY_FORMAT = 'HH:mm';\r\n\r\n/** Parse a bound value (wall-clock ISO string, full ISO, Date, or DateTime) into a Luxon DateTime. */\r\nexport function parseDateValue(value: unknown): DateTime | null {\r\n if (value == null || value === '') {\r\n return null;\r\n }\r\n // Passthrough rather than the null this used to return: hasTimeOfDay below is called both on\r\n // raw row values and on values a caller has already parsed, and it must answer the same either way.\r\n if (DateTime.isDateTime(value)) {\r\n return value.isValid ? value : null;\r\n }\r\n if (value instanceof Date) {\r\n const dt = DateTime.fromJSDate(value);\r\n return dt.isValid ? dt : null;\r\n }\r\n if (typeof value === 'string') {\r\n // Strip millis / trailing Z / numeric offset → treat as local wall-clock (date-preserving).\r\n const cleaned = value\r\n .replace(/\\.\\d+/, '')\r\n .replace(/Z$/i, '')\r\n .replace(/[+-]\\d{2}:?\\d{2}$/, '');\r\n const dt = DateTime.fromISO(cleaned);\r\n return dt.isValid ? dt : null;\r\n }\r\n return null;\r\n}\r\n\r\n/** Serialize a DateTime back to the `\"yyyy-MM-ddTHH:mm:ss\"` string the rest of the app expects. */\r\nexport function serializeDate(dt: DateTime): string {\r\n return dt.toFormat(NXE_DATE_SERIALIZATION_FORMAT);\r\n}\r\n\r\n/**\r\n * Whether a value carries a real time of day.\r\n *\r\n * This is the one place that states what `00:00:00` MEANS in the app's serialization format: not\r\n * \"midnight\", but \"no time was chosen\". Every date-only editor in the app writes exactly midnight,\r\n * so the calendar's all-day-vs-timed split, the grid's display format and anything else that has to\r\n * tell the two apart all read it from here and cannot drift.\r\n */\r\nexport function hasTimeOfDay(value: unknown): boolean {\r\n const dt = parseDateValue(value);\r\n return !!dt && (dt.hour !== 0 || dt.minute !== 0 || dt.second !== 0 || dt.millisecond !== 0);\r\n}\r\n\r\n/**\r\n * Whether a start/end pair describes a whole-day range.\r\n *\r\n * Deliberately \"every end that is PRESENT is midnight\", not \"start is midnight AND end is midnight\".\r\n * Half-filled pairs are a supported shape — the calendar endpoint folds `start ?? end` and treats a\r\n * row carrying only one of the two as a single-day event — and a rule that demanded both would call\r\n * such a row timed on the strength of the end that is not there.\r\n *\r\n * A pair with neither end is all-day by this reading. Degenerate, and unreachable in practice: a row\r\n * with no dates at all cannot overlap a window, so the endpoint never returns one.\r\n */\r\nexport function isAllDayRange(start: unknown, end: unknown): boolean {\r\n return !hasTimeOfDay(start) && !hasTimeOfDay(end);\r\n}\r\n\r\n/** Format a DateTime for display per `displayFormat` (DevExtreme tokens map 1:1 to Luxon). */\r\nexport function formatDisplay(dt: DateTime | null, displayFormat: string): string {\r\n if (!dt) {\r\n return '';\r\n }\r\n return dt.toFormat(displayFormat || NXE_DEFAULT_DISPLAY_FORMAT);\r\n}\r\n\r\n/**\r\n * Fixed-width tokens swapped for their variable-width twins in the lenient retry below. Luxon's\r\n * `dd` demands exactly two digits and `HH` exactly two, so `1-Aug-2026` and `9:00` are both rejected\r\n * outright by the strict pass — which is a parse failure the user has no way to diagnose.\r\n *\r\n * Month tokens are deliberately absent. Degrading `MM` to `M` mangles `MMM` — the very token every\r\n * orbit format uses — so `dd-MMM-yyyy` would become `dd-MM-yyyy` and then fail to read a\r\n * three-letter month name as a number. Numeric months stay strict; nothing in the app uses them.\r\n */\r\nconst NXE_LENIENT_TOKENS: [RegExp, string][] = [\r\n [/dd/g, 'd'],\r\n [/HH/g, 'H'],\r\n [/hh/g, 'h'],\r\n [/mm/g, 'm'],\r\n [/ss/g, 's'],\r\n];\r\n\r\nfunction lenientFormat(format: string): string {\r\n return NXE_LENIENT_TOKENS.reduce((result, [token, replacement]) => result.replace(token, replacement), format);\r\n}\r\n\r\n/**\r\n * The date-only head of a format carrying time tokens, or null when it carries none.\r\n *\r\n * Known limitation, stated rather than handled: quoted literals are not stripped before the scan, so\r\n * a format like `d 'at' HH:mm` would cut at the `a`. No orbit format uses them.\r\n */\r\nfunction dateOnlyFormat(format: string): string | null {\r\n const match = /[Hhmsa]/.exec(format);\r\n if (!match || match.index === 0) {\r\n return null;\r\n }\r\n const head = format.slice(0, match.index).replace(/[\\s,:/.\\-]+$/, '');\r\n return head || null;\r\n}\r\n\r\n/**\r\n * Parse user-typed text, trying in order: the display format; a lenient variant of it; for a format\r\n * carrying time tokens, its date-only head (keeping `base`'s time); then ISO.\r\n *\r\n * `base` is what stops a datetime field from being destructive. Without it, typing just the date\r\n * into a `dd-MMM-yyyy HH:mm` box either resets the time to midnight or — because the strict pass\r\n * rejects the text outright — nulls the whole field. Callers editing an existing value should pass\r\n * it; the parameter is optional so the date-only call sites need no change.\r\n */\r\nexport function parseDisplay(text: string, displayFormat: string, base?: DateTime | null): DateTime | null {\r\n const trimmed = (text ?? '').trim();\r\n if (!trimmed) {\r\n return null;\r\n }\r\n\r\n const format = displayFormat || NXE_DEFAULT_DISPLAY_FORMAT;\r\n const lenient = lenientFormat(format);\r\n for (const candidate of lenient === format ? [format] : [format, lenient]) {\r\n const dt = DateTime.fromFormat(trimmed, candidate);\r\n if (dt.isValid) {\r\n return dt;\r\n }\r\n }\r\n\r\n const dateOnly = dateOnlyFormat(format);\r\n if (dateOnly) {\r\n const lenientDateOnly = lenientFormat(dateOnly);\r\n for (const candidate of lenientDateOnly === dateOnly ? [dateOnly] : [dateOnly, lenientDateOnly]) {\r\n const dt = DateTime.fromFormat(trimmed, candidate);\r\n if (dt.isValid) {\r\n return base?.isValid ? dt.set({ hour: base.hour, minute: base.minute, second: base.second }) : dt;\r\n }\r\n }\r\n }\r\n\r\n const iso = DateTime.fromISO(trimmed);\r\n return iso.isValid ? iso : null;\r\n}\r\n\r\n/** Calendar zoom level (DevExtreme `dxCalendar.zoomLevel`). */\r\nexport type NxeCalendarZoom = 'month' | 'year' | 'decade' | 'century';\r\n\r\nexport interface NxePeriodCell {\r\n /** First day of the period (month / year / decade). */\r\n anchor: DateTime;\r\n label: string;\r\n /** Belongs to the adjacent decade/century (rendered dimmed, DevExtreme `other-view`). */\r\n other: boolean;\r\n}\r\n\r\n/**\r\n * Build the 4×3 period grid for a zoomed-out calendar view (mirrors DevExtreme):\r\n * `year` → Jan..Dec, `decade` → decadeStart−1..decadeStart+10, `century` → 12 decades\r\n * from centuryStart−10, labelled `\"2020 - 2029\"`.\r\n */\r\nexport function buildPeriodCells(zoom: Exclude<NxeCalendarZoom, 'month'>, view: DateTime): NxePeriodCell[] {\r\n if (zoom === 'year') {\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const anchor = view.set({ month: i + 1 }).startOf('month');\r\n return { anchor, label: anchor.toFormat('MMM'), other: false };\r\n });\r\n }\r\n if (zoom === 'decade') {\r\n const start = view.year - (view.year % 10);\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const year = start - 1 + i;\r\n return { anchor: DateTime.local(year, 1, 1), label: String(year), other: year < start || year > start + 9 };\r\n });\r\n }\r\n const start = view.year - (view.year % 100);\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const year = start - 10 + i * 10;\r\n return { anchor: DateTime.local(year, 1, 1), label: `${year} - ${year + 9}`, other: year < start || year > start + 90 };\r\n });\r\n}\r\n\r\n/** Build the 6×7 day grid (Sunday-first) for the calendar popup of `viewMonth`. */\r\nexport function buildCalendarWeeks(viewMonth: DateTime): DateTime[][] {\r\n const firstOfMonth = viewMonth.startOf('month');\r\n const offset = firstOfMonth.weekday % 7; // luxon: Mon=1..Sun=7 → Sunday-first offset\r\n let cursor = firstOfMonth.minus({ days: offset }).startOf('day');\r\n const weeks: DateTime[][] = [];\r\n for (let w = 0; w < 6; w++) {\r\n const days: DateTime[] = [];\r\n for (let d = 0; d < 7; d++) {\r\n days.push(cursor);\r\n cursor = cursor.plus({ days: 1 });\r\n }\r\n weeks.push(days);\r\n }\r\n return weeks;\r\n}\r\n","import { InjectionToken } from '@angular/core';\r\nimport { NXE_EN_US_SEPARATORS, type NxeNumberSeparators } from './nxe-number-format';\r\n\r\nexport { NXE_EN_US_SEPARATORS, NXE_ID_SEPARATORS } from './nxe-number-format';\r\nexport type { NxeNumberSeparators } from './nxe-number-format';\r\n\r\n/**\r\n * The grouping and decimal characters every number editor renders with.\r\n *\r\n * DevExtreme solves this with a global `DevExpress.localization.locale()`; the Angular equivalent\r\n * is a provider, so an application states it once at bootstrap:\r\n *\r\n * ```ts\r\n * providers: [{ provide: NXE_NUMBER_SEPARATORS, useValue: NXE_ID_SEPARATORS }]\r\n * ```\r\n *\r\n * This exists because the alternative already happened: with the separators hardcoded, an\r\n * application that needed `1.250.000,50` instead of `1,234.50` forked the format engine to get\r\n * them, and that single file is why its copy of the library could not be merged back.\r\n *\r\n * Defaults to en-US, which is DevExtreme's default and what the pattern language itself writes.\r\n */\r\nexport const NXE_NUMBER_SEPARATORS = new InjectionToken<NxeNumberSeparators>(\r\n 'NXE_NUMBER_SEPARATORS',\r\n { providedIn: 'root', factory: () => NXE_EN_US_SEPARATORS },\r\n);\r\n","// @nexterajs/ui/intl — public API.\r\nexport * from './lib/number-box/nxe-number-format';\r\nexport * from './lib/date-box/nxe-date-format';\r\nexport * from './lib/number-box/nxe-number-locale';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nexterajs-ui-intl.mjs","sources":["../../../projects/nextera-ui/intl/src/lib/number-box/nxe-number-format.ts","../../../projects/nextera-ui/intl/src/lib/date-box/nxe-date-format.ts","../../../projects/nextera-ui/intl/src/lib/number-box/nxe-number-locale.ts","../../../projects/nextera-ui/intl/src/lib/number-box/nxe-currency-format.ts","../../../projects/nextera-ui/intl/src/public-api.ts","../../../projects/nextera-ui/intl/src/nexterajs-ui-intl.ts"],"sourcesContent":["// DevExtreme LDML-style number format engine for nxe-number-box.\r\n//\r\n// Supports the patterns actually used in this codebase:\r\n// #,##0.00 — grouping, exactly 2 fraction digits\r\n// #,##0.00000 — grouping, exactly 5 fraction digits\r\n// #,##0.#####'%' — grouping, 0–5 fraction digits, literal '%' suffix (NO ×100)\r\n// #0 — integer, no grouping\r\n// #,##0 — integer with grouping\r\n// #,##0.00;(#,##0.00) — a negative section: below zero renders as (1,234.50)\r\n// (empty) — raw number, no grouping\r\n//\r\n// Tokens: `#` optional digit, `0` required digit, `,` enable grouping (size 3), `.` decimal point\r\n// (count of `0` after it = min fraction digits, count of `0`+`#` = max), `'…'` verbatim literal,\r\n// `;` (unquoted) starts the negative section.\r\n\r\nexport interface NxeParsedNumberFormat {\r\n prefix: string;\r\n suffix: string;\r\n useGrouping: boolean;\r\n /**\r\n * Digits per group, read from the pattern: `#,##0` is 3, `#,#0` is 2. Optional because\r\n * callers construct this shape by hand as well as through {@link parseNumberFormat};\r\n * omitted means dx's usual 3.\r\n */\r\n groupSize?: number;\r\n minInt: number;\r\n minFrac: number;\r\n maxFrac: number;\r\n /**\r\n * The pattern's negative section, from `positive;negative` (`#,##0.00;(#,##0.00)`). A value\r\n * below zero renders through it from its absolute value, and gets no `-` of its own: the\r\n * section's prefix and suffix are the sign. Absent means dx's default, a `-` before the\r\n * positive pattern.\r\n */\r\n negative?: NxeParsedNumberFormat;\r\n}\r\n\r\n/** dx's cap on the significant digits a formatted number carries (ldml/number.js:21). */\r\nconst MAXIMUM_NUMBER_LENGTH = 15;\r\n\r\n/** Parse an LDML pattern into a {@link NxeParsedNumberFormat}, or `null` for raw (no format). */\r\nexport function parseNumberFormat(pattern: string | undefined | null): NxeParsedNumberFormat | null {\r\n if (!pattern) {\r\n return null;\r\n }\r\n // dx getSignParts: `positive;negative`. Only an unquoted `;` splits, so `'a;b'#0` stays a literal.\r\n const split = sectionBreak(pattern);\r\n if (split !== -1) {\r\n const positive = parseNumberFormat(pattern.slice(0, split));\r\n const negative = positive && parseNumberFormat(pattern.slice(split + 1));\r\n return positive && negative ? { ...positive, negative } : positive;\r\n }\r\n let prefix = '';\r\n let suffix = '';\r\n let core = '';\r\n let inQuote = false;\r\n let seenCore = false;\r\n for (const ch of pattern) {\r\n if (ch === \"'\") {\r\n inQuote = !inQuote;\r\n continue;\r\n }\r\n const isToken = !inQuote && (ch === '#' || ch === '0' || ch === ',' || ch === '.');\r\n if (isToken) {\r\n core += ch;\r\n seenCore = true;\r\n } else if (!seenCore) {\r\n prefix += ch;\r\n } else {\r\n suffix += ch;\r\n }\r\n }\r\n if (!core) {\r\n return null;\r\n }\r\n const dot = core.indexOf('.');\r\n const intPart = dot === -1 ? core : core.slice(0, dot);\r\n const fracPart = dot === -1 ? '' : core.slice(dot + 1);\r\n const count = (s: string, re: RegExp) => (s.match(re) || []).length;\r\n // The grouping SIZE comes from the pattern, not from a constant 3: dx reads the digits after\r\n // the last comma, so `#,##0` groups by 3 and `#,#0` groups by 2 (which renders 1234.5 as\r\n // \"12,34.5\"). Several consumer columns use the latter, most likely by accident - but it is\r\n // what their screens show today, so parity means reproducing it.\r\n const useGrouping = intPart.includes(',');\r\n const groupSize = useGrouping\r\n ? Math.max(1, count(intPart.slice(intPart.lastIndexOf(',') + 1), /[#0]/g))\r\n : 3;\r\n return {\r\n prefix,\r\n suffix,\r\n useGrouping,\r\n groupSize,\r\n minInt: Math.max(1, count(intPart, /0/g)),\r\n minFrac: count(fracPart, /0/g),\r\n maxFrac: count(fracPart, /[#0]/g),\r\n };\r\n}\r\n\r\n/** Index of the first `;` outside a quoted literal, or -1. */\r\nfunction sectionBreak(pattern: string): number {\r\n let inQuote = false;\r\n for (let i = 0; i < pattern.length; i++) {\r\n if (pattern[i] === \"'\") {\r\n inQuote = !inQuote;\r\n } else if (pattern[i] === ';' && !inQuote) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n}\r\n\r\n/**\r\n * Insert `sep` every `size` digits from the right.\r\n *\r\n * Written as a loop rather than a dynamic RegExp on purpose: the group size varies with the\r\n * pattern, and building a regex by interpolating into a template literal puts `\\B` and `\\d` one\r\n * missing backslash away from silently matching nothing.\r\n */\r\nfunction groupDigits(digits: string, size: number, sep: string): string {\r\n let out = '';\r\n for (let i = 0; i < digits.length; i++) {\r\n if (i > 0 && (digits.length - i) % size === 0) {\r\n out += sep;\r\n }\r\n out += digits[i];\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Render `value` with exactly `frac` fraction digits, from its SHORTEST decimal form.\r\n *\r\n * `toFixed` expands the binary value instead, so 1234567.891 at 14 digits becomes\r\n * \"1234567.89100000006147\" — the true double, and not what dx prints. Taking `String(value)`\r\n * (the shortest round-tripping decimal) and padding matches dx and is what a reader expects.\r\n * Exponential notation, which `String` produces below 1e-6, falls back to `toFixed`.\r\n */\r\nfunction toDecimalString(value: number, frac: number): string {\r\n const s = String(value);\r\n if (s.includes('e') || s.includes('E')) {\r\n return value.toFixed(frac);\r\n }\r\n const dot = s.indexOf('.');\r\n const intPart = dot === -1 ? s : s.slice(0, dot);\r\n const fracPart = dot === -1 ? '' : s.slice(dot + 1);\r\n return frac === 0 ? intPart : `${intPart}.${fracPart.slice(0, frac).padEnd(frac, '0')}`;\r\n}\r\n\r\n/** Round half-away-from-zero to `frac` fraction digits (DevExtreme rounding), fp-safe. */\r\nexport function roundHalfAwayFromZero(value: number, frac: number): number {\r\n const factor = Math.pow(10, frac);\r\n const rounded = Math.round(Math.abs(value) * factor + 1e-9) / factor;\r\n return value < 0 ? -rounded : rounded;\r\n}\r\n\r\n/** Format a number with the parsed pattern. `null`/`NaN` → `''`. */\r\n/**\r\n * The characters that separate groups and the fraction.\r\n *\r\n * The LDML pattern always writes `,` for grouping and `.` for the decimal point — that is the\r\n * pattern language, not the output. Which characters actually get rendered is a locale decision,\r\n * and it is the one that split this file: one consuming app needs `1,234.50`, another needs\r\n * `1.250.000,50`, and hardcoding either forces the other to fork.\r\n */\r\nexport interface NxeNumberSeparators {\r\n readonly group: string;\r\n readonly decimal: string;\r\n}\r\n\r\n/** DevExtreme's default, and this library's. */\r\nexport const NXE_EN_US_SEPARATORS: NxeNumberSeparators = { group: ',', decimal: '.' };\r\n\r\n/** Indonesian house style, used by several of the consuming applications. */\r\nexport const NXE_ID_SEPARATORS: NxeNumberSeparators = { group: '.', decimal: ',' };\r\n\r\nexport function formatNumber(\r\n value: number | null | undefined,\r\n fmt: NxeParsedNumberFormat | null,\r\n separators: NxeNumberSeparators = NXE_EN_US_SEPARATORS,\r\n): string {\r\n if (value == null || typeof value !== 'number' || isNaN(value)) {\r\n return '';\r\n }\r\n if (!fmt) {\r\n return String(value);\r\n }\r\n const negative = value < 0;\r\n if (negative && fmt.negative) {\r\n const section = fmt.negative;\r\n return `${section.prefix}${formatDigits(Math.abs(value), section, separators)}${section.suffix}`;\r\n }\r\n return `${fmt.prefix}${negative ? '-' : ''}${formatDigits(Math.abs(value), fmt, separators)}${fmt.suffix}`;\r\n}\r\n\r\n/** The digits of `abs` under `fmt`, without its prefix, suffix or sign. */\r\nfunction formatDigits(abs: number, fmt: NxeParsedNumberFormat, separators: NxeNumberSeparators): string {\r\n // dx MAXIMUM_NUMBER_LENGTH (ldml/number.js:21, :152-153): the fraction gets only what is left\r\n // of 15 significant digits after the integer part, `fitIntoRange(maxFloat, 0, 15 - intLen)`.\r\n // Without it a 15-place mask printed 10/3 % as 3.333333333333333 rather than dx's\r\n // 3.33333333333333.\r\n const frac = Math.min(fmt.maxFrac, Math.max(0, MAXIMUM_NUMBER_LENGTH - String(Math.floor(abs)).length));\r\n const rounded = roundHalfAwayFromZero(abs, frac);\r\n const fixed = toDecimalString(rounded, frac);\r\n const parts = fixed.split('.');\r\n let intStr = parts[0];\r\n let fracStr = parts[1] ?? '';\r\n if (fmt.maxFrac > fmt.minFrac) {\r\n fracStr = fracStr.replace(/0+$/, '');\r\n }\r\n // Always, not only for optional digits: the cap can leave fewer places than the mask requires,\r\n // and dx's normalizeValueString pads those back with zeros.\r\n while (fracStr.length < fmt.minFrac) {\r\n fracStr += '0';\r\n }\r\n while (intStr.length < fmt.minInt) {\r\n intStr = '0' + intStr;\r\n }\r\n if (fmt.useGrouping) {\r\n intStr = groupDigits(intStr, fmt.groupSize ?? 3, separators.group);\r\n }\r\n return fracStr ? `${intStr}${separators.decimal}${fracStr}` : intStr;\r\n}\r\n\r\n/** Parse a (possibly formatted) string into a number; strips grouping/literals. Empty → `null`. */\r\nexport function parseNumber(\r\n text: string | null | undefined,\r\n separators: NxeNumberSeparators = NXE_EN_US_SEPARATORS,\r\n): number | null {\r\n if (text == null) {\r\n return null;\r\n }\r\n // Strip everything that is not a digit, a sign, or one of this locale's separators, then\r\n // drop the group separator and normalise the decimal one to `.` for parseFloat.\r\n const keep = new Set([separators.group, separators.decimal]);\r\n let cleaned = '';\r\n for (const ch of text) {\r\n if ((ch >= '0' && ch <= '9') || ch === '-' || keep.has(ch)) {\r\n cleaned += ch;\r\n }\r\n }\r\n const normalized = cleaned\r\n .split(separators.group)\r\n .join('')\r\n .replace(separators.decimal, '.');\r\n\r\n if (normalized === '' || normalized === '-' || normalized === '.' || normalized === '-.') {\r\n return null;\r\n }\r\n const num = parseFloat(normalized);\r\n if (isNaN(num)) {\r\n return null;\r\n }\r\n // `(1,234.50)` is how a `#,##0.00;(#,##0.00)` pattern writes a negative, so it reads back as one.\r\n const open = text.indexOf('(');\r\n const close = text.lastIndexOf(')');\r\n return open !== -1 && close > open ? -Math.abs(num) : num;\r\n}\r\n","// Luxon-based date parsing/formatting/serialization for nxe-date-box.\r\n//\r\n// The app sets a global DevExtreme `dateSerializationFormat: \"yyyy-MM-ddTHH:mm:ss\"`, so the value\r\n// stored in the form control is an ISO-like wall-clock string (no zone, no millis). nxe-date-box\r\n// preserves that contract: it accepts such strings (and tolerates Date / full-ISO-with-Z from the\r\n// `defaultSystemSettings` directive) and emits the same `\"yyyy-MM-ddTHH:mm:ss\"` string.\r\n\r\nimport { DateTime } from 'luxon';\r\n\r\n/** The app-wide serialization format (matches DevExtreme `dateSerializationFormat`). */\r\nexport const NXE_DATE_SERIALIZATION_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss\";\r\n/** DevExtreme global default `displayFormat` (`dxDateBox.defaultOptions`). */\r\nexport const NXE_DEFAULT_DISPLAY_FORMAT = 'dd-MMM-yyyy';\r\n/** Default `displayFormat` for `type=\"datetime\"`. */\r\nexport const NXE_DEFAULT_DATETIME_DISPLAY_FORMAT = 'dd-MMM-yyyy HH:mm';\r\n/** Default `displayFormat` for `type=\"time\"`. */\r\nexport const NXE_DEFAULT_TIME_DISPLAY_FORMAT = 'HH:mm';\r\n\r\n/** Parse a bound value (wall-clock ISO string, full ISO, Date, or DateTime) into a Luxon DateTime. */\r\nexport function parseDateValue(value: unknown): DateTime | null {\r\n if (value == null || value === '') {\r\n return null;\r\n }\r\n // Passthrough rather than the null this used to return: hasTimeOfDay below is called both on\r\n // raw row values and on values a caller has already parsed, and it must answer the same either way.\r\n if (DateTime.isDateTime(value)) {\r\n return value.isValid ? value : null;\r\n }\r\n if (value instanceof Date) {\r\n const dt = DateTime.fromJSDate(value);\r\n return dt.isValid ? dt : null;\r\n }\r\n if (typeof value === 'string') {\r\n // Strip millis / trailing Z / numeric offset → treat as local wall-clock (date-preserving).\r\n const cleaned = value\r\n .replace(/\\.\\d+/, '')\r\n .replace(/Z$/i, '')\r\n .replace(/[+-]\\d{2}:?\\d{2}$/, '');\r\n const dt = DateTime.fromISO(cleaned);\r\n return dt.isValid ? dt : null;\r\n }\r\n return null;\r\n}\r\n\r\n/** Serialize a DateTime back to the `\"yyyy-MM-ddTHH:mm:ss\"` string the rest of the app expects. */\r\nexport function serializeDate(dt: DateTime): string {\r\n return dt.toFormat(NXE_DATE_SERIALIZATION_FORMAT);\r\n}\r\n\r\n/**\r\n * Whether a value carries a real time of day.\r\n *\r\n * This is the one place that states what `00:00:00` MEANS in the app's serialization format: not\r\n * \"midnight\", but \"no time was chosen\". Every date-only editor in the app writes exactly midnight,\r\n * so the calendar's all-day-vs-timed split, the grid's display format and anything else that has to\r\n * tell the two apart all read it from here and cannot drift.\r\n */\r\nexport function hasTimeOfDay(value: unknown): boolean {\r\n const dt = parseDateValue(value);\r\n return !!dt && (dt.hour !== 0 || dt.minute !== 0 || dt.second !== 0 || dt.millisecond !== 0);\r\n}\r\n\r\n/**\r\n * Whether a start/end pair describes a whole-day range.\r\n *\r\n * Deliberately \"every end that is PRESENT is midnight\", not \"start is midnight AND end is midnight\".\r\n * Half-filled pairs are a supported shape — the calendar endpoint folds `start ?? end` and treats a\r\n * row carrying only one of the two as a single-day event — and a rule that demanded both would call\r\n * such a row timed on the strength of the end that is not there.\r\n *\r\n * A pair with neither end is all-day by this reading. Degenerate, and unreachable in practice: a row\r\n * with no dates at all cannot overlap a window, so the endpoint never returns one.\r\n */\r\nexport function isAllDayRange(start: unknown, end: unknown): boolean {\r\n return !hasTimeOfDay(start) && !hasTimeOfDay(end);\r\n}\r\n\r\n/** Format a DateTime for display per `displayFormat` (DevExtreme tokens map 1:1 to Luxon). */\r\nexport function formatDisplay(dt: DateTime | null, displayFormat: string, locale?: string): string {\r\n if (!dt) {\r\n return '';\r\n }\r\n return (locale ? dt.setLocale(locale) : dt).toFormat(displayFormat || NXE_DEFAULT_DISPLAY_FORMAT);\r\n}\r\n\r\n/**\r\n * Fixed-width tokens swapped for their variable-width twins in the lenient retry below. Luxon's\r\n * `dd` demands exactly two digits and `HH` exactly two, so `1-Aug-2026` and `9:00` are both rejected\r\n * outright by the strict pass — which is a parse failure the user has no way to diagnose.\r\n *\r\n * Month tokens are deliberately absent. Degrading `MM` to `M` mangles `MMM` — the very token every\r\n * orbit format uses — so `dd-MMM-yyyy` would become `dd-MM-yyyy` and then fail to read a\r\n * three-letter month name as a number. Numeric months stay strict; nothing in the app uses them.\r\n */\r\nconst NXE_LENIENT_TOKENS: [RegExp, string][] = [\r\n [/dd/g, 'd'],\r\n [/HH/g, 'H'],\r\n [/hh/g, 'h'],\r\n [/mm/g, 'm'],\r\n [/ss/g, 's'],\r\n];\r\n\r\nfunction lenientFormat(format: string): string {\r\n return NXE_LENIENT_TOKENS.reduce((result, [token, replacement]) => result.replace(token, replacement), format);\r\n}\r\n\r\n/**\r\n * The date-only head of a format carrying time tokens, or null when it carries none.\r\n *\r\n * Known limitation, stated rather than handled: quoted literals are not stripped before the scan, so\r\n * a format like `d 'at' HH:mm` would cut at the `a`. No orbit format uses them.\r\n */\r\nfunction dateOnlyFormat(format: string): string | null {\r\n const match = /[Hhmsa]/.exec(format);\r\n if (!match || match.index === 0) {\r\n return null;\r\n }\r\n const head = format.slice(0, match.index).replace(/[\\s,:/.\\-]+$/, '');\r\n return head || null;\r\n}\r\n\r\n/**\r\n * Parse user-typed text, trying in order: the display format; a lenient variant of it; for a format\r\n * carrying time tokens, its date-only head (keeping `base`'s time); then ISO.\r\n *\r\n * `base` is what stops a datetime field from being destructive. Without it, typing just the date\r\n * into a `dd-MMM-yyyy HH:mm` box either resets the time to midnight or — because the strict pass\r\n * rejects the text outright — nulls the whole field. Callers editing an existing value should pass\r\n * it; the parameter is optional so the date-only call sites need no change.\r\n */\r\nexport function parseDisplay(\r\n text: string,\r\n displayFormat: string,\r\n base?: DateTime | null,\r\n locale?: string,\r\n): DateTime | null {\r\n const trimmed = (text ?? '').trim();\r\n if (!trimmed) {\r\n return null;\r\n }\r\n\r\n const format = displayFormat || NXE_DEFAULT_DISPLAY_FORMAT;\r\n const lenient = lenientFormat(format);\r\n for (const candidate of lenient === format ? [format] : [format, lenient]) {\r\n const dt = DateTime.fromFormat(trimmed, candidate, locale ? { locale } : undefined);\r\n if (dt.isValid) {\r\n return dt;\r\n }\r\n }\r\n\r\n const dateOnly = dateOnlyFormat(format);\r\n if (dateOnly) {\r\n const lenientDateOnly = lenientFormat(dateOnly);\r\n for (const candidate of lenientDateOnly === dateOnly ? [dateOnly] : [dateOnly, lenientDateOnly]) {\r\n const dt = DateTime.fromFormat(trimmed, candidate, locale ? { locale } : undefined);\r\n if (dt.isValid) {\r\n return base?.isValid ? dt.set({ hour: base.hour, minute: base.minute, second: base.second }) : dt;\r\n }\r\n }\r\n }\r\n\r\n const iso = DateTime.fromISO(trimmed);\r\n return iso.isValid ? iso : null;\r\n}\r\n\r\n/** Calendar zoom level (DevExtreme `dxCalendar.zoomLevel`). */\r\nexport type NxeCalendarZoom = 'month' | 'year' | 'decade' | 'century';\r\n\r\nexport interface NxePeriodCell {\r\n /** First day of the period (month / year / decade). */\r\n anchor: DateTime;\r\n label: string;\r\n /** Belongs to the adjacent decade/century (rendered dimmed, DevExtreme `other-view`). */\r\n other: boolean;\r\n}\r\n\r\n/**\r\n * Build the 4×3 period grid for a zoomed-out calendar view (mirrors DevExtreme):\r\n * `year` → Jan..Dec, `decade` → decadeStart−1..decadeStart+10, `century` → 12 decades\r\n * from centuryStart−10, labelled `\"2020 - 2029\"`.\r\n */\r\nexport function buildPeriodCells(zoom: Exclude<NxeCalendarZoom, 'month'>, view: DateTime): NxePeriodCell[] {\r\n if (zoom === 'year') {\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const anchor = view.set({ month: i + 1 }).startOf('month');\r\n return { anchor, label: anchor.toFormat('MMM'), other: false };\r\n });\r\n }\r\n if (zoom === 'decade') {\r\n const start = view.year - (view.year % 10);\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const year = start - 1 + i;\r\n return { anchor: DateTime.local(year, 1, 1), label: String(year), other: year < start || year > start + 9 };\r\n });\r\n }\r\n const start = view.year - (view.year % 100);\r\n return Array.from({ length: 12 }, (_, i) => {\r\n const year = start - 10 + i * 10;\r\n return { anchor: DateTime.local(year, 1, 1), label: `${year} - ${year + 9}`, other: year < start || year > start + 90 };\r\n });\r\n}\r\n\r\n/** Build the 6×7 day grid (Sunday-first) for the calendar popup of `viewMonth`. */\r\nexport function buildCalendarWeeks(viewMonth: DateTime): DateTime[][] {\r\n const firstOfMonth = viewMonth.startOf('month');\r\n const offset = firstOfMonth.weekday % 7; // luxon: Mon=1..Sun=7 → Sunday-first offset\r\n let cursor = firstOfMonth.minus({ days: offset }).startOf('day');\r\n const weeks: DateTime[][] = [];\r\n for (let w = 0; w < 6; w++) {\r\n const days: DateTime[] = [];\r\n for (let d = 0; d < 7; d++) {\r\n days.push(cursor);\r\n cursor = cursor.plus({ days: 1 });\r\n }\r\n weeks.push(days);\r\n }\r\n return weeks;\r\n}\r\n","import { InjectionToken } from '@angular/core';\nimport { NXE_EN_US_SEPARATORS, type NxeNumberSeparators } from './nxe-number-format';\n\nexport { NXE_EN_US_SEPARATORS, NXE_ID_SEPARATORS } from './nxe-number-format';\nexport type { NxeNumberSeparators } from './nxe-number-format';\n\n/**\n * The grouping and decimal characters every number editor renders with.\n *\n * DevExtreme solves this with a global `DevExpress.localization.locale()`; the Angular equivalent\n * is a provider, so an application states it once at bootstrap:\n *\n * ```ts\n * providers: [{ provide: NXE_NUMBER_SEPARATORS, useValue: NXE_ID_SEPARATORS }]\n * ```\n *\n * This exists because the alternative already happened: with the separators hardcoded, an\n * application that needed `1.250.000,50` instead of `1,234.50` forked the format engine to get\n * them, and that single file is why its copy of the library could not be merged back.\n *\n * Defaults to en-US, which is DevExtreme's default and what the pattern language itself writes.\n */\nexport const NXE_NUMBER_SEPARATORS = new InjectionToken<NxeNumberSeparators>(\n 'NXE_NUMBER_SEPARATORS',\n { providedIn: 'root', factory: () => NXE_EN_US_SEPARATORS },\n);\n","// Currency display for nxe-number-box, mirroring the StreamB2B `sbMoney` rules\n// (docs/03-design-system/patterns.md section 9): `IDR 1.351.000`, `IDR 1.351.000,50` (id),\n// `IDR 1,351,000.50` (en). The ISO 4217 code goes before the amount, rounding is half away from\n// zero, a minus sign goes before the code (`-IDR 1.000`), and an amount that rounds to zero\n// carries no sign.\n\nimport {\n formatNumber,\n NXE_EN_US_SEPARATORS,\n parseNumberFormat,\n roundHalfAwayFromZero,\n type NxeNumberSeparators,\n type NxeParsedNumberFormat,\n} from './nxe-number-format';\n\n/** How one currency is displayed. */\nexport interface NxeCurrencyInfo {\n /** Minor units: fraction digits the currency has (ISO 4217). */\n readonly digits: number;\n /**\n * Drop an all-zero fraction (`IDR 1.351.000`), but keep the full one when it is not zero\n * (`IDR 1.351.000,50`). Currencies with fixed minor units always show them (`USD 1,234.00`).\n */\n readonly trimZeroFraction: boolean;\n}\n\nconst ZERO_DIGITS = ['BIF', 'CLP', 'DJF', 'GNF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'UGX', 'UYI', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'];\nconst THREE_DIGITS = ['BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND'];\n\nconst CURRENCIES: Readonly<Record<string, NxeCurrencyInfo>> = {\n IDR: { digits: 2, trimZeroFraction: true },\n ...Object.fromEntries(ZERO_DIGITS.map((code) => [code, { digits: 0, trimZeroFraction: false }])),\n ...Object.fromEntries(THREE_DIGITS.map((code) => [code, { digits: 3, trimZeroFraction: false }])),\n};\n\nconst DEFAULT_CURRENCY: NxeCurrencyInfo = { digits: 2, trimZeroFraction: false };\n\n/** Normalise a currency code: trimmed and upper-cased; `''` when absent. */\nexport function nxeCurrencyCode(code: string | null | undefined): string {\n return (code ?? '').trim().toUpperCase();\n}\n\n/**\n * Display rules for a currency code. Unknown codes have 2 minor units. `decimals` (the currency's\n * decimals from reference data, when the app knows them) overrides the built-in table.\n */\nexport function nxeCurrencyInfo(code: string | null | undefined, decimals?: number | null): NxeCurrencyInfo {\n const known = CURRENCIES[nxeCurrencyCode(code)] ?? DEFAULT_CURRENCY;\n if (decimals == null || !Number.isFinite(decimals)) {\n return known;\n }\n const digits = Math.max(0, Math.min(10, Math.trunc(decimals)));\n return { digits, trimZeroFraction: known.trimZeroFraction && digits > 0 };\n}\n\n/** The number pattern behind a currency: grouped, `digits` fraction digits at most. */\nexport function nxeCurrencyNumberFormat(code: string | null | undefined, decimals?: number | null): NxeParsedNumberFormat {\n const info = nxeCurrencyInfo(code, decimals);\n return (\n parseNumberFormat(info.digits ? `#,##0.${'0'.repeat(info.digits)}` : '#,##0') as NxeParsedNumberFormat\n );\n}\n\n/**\n * Format an amount as `CODE 1.234,50`. `null`/`NaN` give `''`. With a `pattern` (an already parsed\n * number format) that pattern shapes the number instead of the currency's own digits.\n */\nexport function formatCurrency(\n value: number | null | undefined,\n code: string | null | undefined,\n separators: NxeNumberSeparators = NXE_EN_US_SEPARATORS,\n options: { decimals?: number | null; pattern?: NxeParsedNumberFormat | null } = {},\n): string {\n if (value == null || typeof value !== 'number' || isNaN(value)) {\n return '';\n }\n const info = nxeCurrencyInfo(code, options.decimals);\n let fmt = options.pattern ?? nxeCurrencyNumberFormat(code, options.decimals);\n const rounded = roundHalfAwayFromZero(value, fmt.maxFrac);\n if (!options.pattern && info.trimZeroFraction && Number.isInteger(rounded)) {\n fmt = { ...fmt, minFrac: 0, maxFrac: 0 };\n }\n const currency = nxeCurrencyCode(code);\n const negative = rounded < 0;\n // A pattern with a negative section (`#,##0.00;(#,##0.00)`) writes its own sign: `USD (1,234.50)`.\n if (negative && fmt.negative) {\n return `${currency ? `${currency} ` : ''}${formatNumber(rounded, fmt, separators)}`;\n }\n const body = formatNumber(Math.abs(rounded), fmt, separators);\n return `${negative ? '-' : ''}${currency ? `${currency} ` : ''}${body}`;\n}\n","// @nexterajs/ui/intl — public API.\r\nexport * from './lib/number-box/nxe-number-format';\r\nexport * from './lib/date-box/nxe-date-format';\r\nexport * from './lib/number-box/nxe-number-locale';\r\nexport * from './lib/number-box/nxe-currency-format';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}