@craftzbay/ui 0.9.0 → 0.11.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 (208) hide show
  1. package/README.md +82 -10
  2. package/dist-lib/__tests__/helpers/color.d.ts +9 -0
  3. package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
  4. package/dist-lib/components/ui/Accordion.js +71 -0
  5. package/dist-lib/components/ui/Accordion.js.map +1 -0
  6. package/dist-lib/components/ui/Alert.d.ts +17 -1
  7. package/dist-lib/components/ui/Alert.js +79 -0
  8. package/dist-lib/components/ui/Alert.js.map +1 -0
  9. package/dist-lib/components/ui/Avatar.d.ts +3 -3
  10. package/dist-lib/components/ui/Avatar.js +94 -0
  11. package/dist-lib/components/ui/Avatar.js.map +1 -0
  12. package/dist-lib/components/ui/Badge.d.ts +4 -2
  13. package/dist-lib/components/ui/Badge.js +76 -0
  14. package/dist-lib/components/ui/Badge.js.map +1 -0
  15. package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
  16. package/dist-lib/components/ui/Breadcrumbs.js +52 -0
  17. package/dist-lib/components/ui/Breadcrumbs.js.map +1 -0
  18. package/dist-lib/components/ui/Button.d.ts +6 -4
  19. package/dist-lib/components/ui/Button.js +131 -0
  20. package/dist-lib/components/ui/Button.js.map +1 -0
  21. package/dist-lib/components/ui/Calendar.d.ts +7 -1
  22. package/dist-lib/components/ui/Calendar.js +139 -0
  23. package/dist-lib/components/ui/Calendar.js.map +1 -0
  24. package/dist-lib/components/ui/Card.d.ts +3 -1
  25. package/dist-lib/components/ui/Card.js +97 -0
  26. package/dist-lib/components/ui/Card.js.map +1 -0
  27. package/dist-lib/components/ui/Carousel.d.ts +11 -7
  28. package/dist-lib/components/ui/Carousel.js +174 -0
  29. package/dist-lib/components/ui/Carousel.js.map +1 -0
  30. package/dist-lib/components/ui/Chart.d.ts +68 -7
  31. package/dist-lib/components/ui/Chart.js +487 -0
  32. package/dist-lib/components/ui/Chart.js.map +1 -0
  33. package/dist-lib/components/ui/Checkbox.js +70 -0
  34. package/dist-lib/components/ui/Checkbox.js.map +1 -0
  35. package/dist-lib/components/ui/Combobox.d.ts +9 -0
  36. package/dist-lib/components/ui/Combobox.js +195 -0
  37. package/dist-lib/components/ui/Combobox.js.map +1 -0
  38. package/dist-lib/components/ui/CommandPalette.d.ts +9 -6
  39. package/dist-lib/components/ui/CommandPalette.js +179 -0
  40. package/dist-lib/components/ui/CommandPalette.js.map +1 -0
  41. package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
  42. package/dist-lib/components/ui/ContextMenu.js +165 -0
  43. package/dist-lib/components/ui/ContextMenu.js.map +1 -0
  44. package/dist-lib/components/ui/DataGrid.d.ts +17 -4
  45. package/dist-lib/components/ui/DataGrid.js +99 -0
  46. package/dist-lib/components/ui/DataGrid.js.map +1 -0
  47. package/dist-lib/components/ui/DatePicker.d.ts +16 -13
  48. package/dist-lib/components/ui/DatePicker.js +193 -0
  49. package/dist-lib/components/ui/DatePicker.js.map +1 -0
  50. package/dist-lib/components/ui/DesignSystemProvider.d.ts +102 -41
  51. package/dist-lib/components/ui/DesignSystemProvider.js +135 -0
  52. package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -0
  53. package/dist-lib/components/ui/Dialog.d.ts +19 -4
  54. package/dist-lib/components/ui/Dialog.js +165 -0
  55. package/dist-lib/components/ui/Dialog.js.map +1 -0
  56. package/dist-lib/components/ui/Drawer.d.ts +23 -2
  57. package/dist-lib/components/ui/Drawer.js +132 -0
  58. package/dist-lib/components/ui/Drawer.js.map +1 -0
  59. package/dist-lib/components/ui/DropdownMenu.js +169 -0
  60. package/dist-lib/components/ui/DropdownMenu.js.map +1 -0
  61. package/dist-lib/components/ui/EmptyState.d.ts +2 -0
  62. package/dist-lib/components/ui/EmptyState.js +46 -0
  63. package/dist-lib/components/ui/EmptyState.js.map +1 -0
  64. package/dist-lib/components/ui/ErrorState.d.ts +13 -2
  65. package/dist-lib/components/ui/ErrorState.js +69 -0
  66. package/dist-lib/components/ui/ErrorState.js.map +1 -0
  67. package/dist-lib/components/ui/FileUpload.d.ts +3 -0
  68. package/dist-lib/components/ui/FileUpload.js +111 -0
  69. package/dist-lib/components/ui/FileUpload.js.map +1 -0
  70. package/dist-lib/components/ui/Form.d.ts +16 -2
  71. package/dist-lib/components/ui/Form.js +131 -0
  72. package/dist-lib/components/ui/Form.js.map +1 -0
  73. package/dist-lib/components/ui/Icon.d.ts +1 -1
  74. package/dist-lib/components/ui/Icon.js +32 -0
  75. package/dist-lib/components/ui/Icon.js.map +1 -0
  76. package/dist-lib/components/ui/IconButton.d.ts +3 -3
  77. package/dist-lib/components/ui/IconButton.js +64 -0
  78. package/dist-lib/components/ui/IconButton.js.map +1 -0
  79. package/dist-lib/components/ui/Input.d.ts +9 -4
  80. package/dist-lib/components/ui/Input.js +149 -0
  81. package/dist-lib/components/ui/Input.js.map +1 -0
  82. package/dist-lib/components/ui/Kbd.js +24 -0
  83. package/dist-lib/components/ui/Kbd.js.map +1 -0
  84. package/dist-lib/components/ui/MultiSelect.d.ts +3 -1
  85. package/dist-lib/components/ui/MultiSelect.js +210 -0
  86. package/dist-lib/components/ui/MultiSelect.js.map +1 -0
  87. package/dist-lib/components/ui/Pagination.d.ts +23 -0
  88. package/dist-lib/components/ui/Pagination.js +153 -0
  89. package/dist-lib/components/ui/Pagination.js.map +1 -0
  90. package/dist-lib/components/ui/Popover.js +35 -0
  91. package/dist-lib/components/ui/Popover.js.map +1 -0
  92. package/dist-lib/components/ui/Progress.d.ts +3 -3
  93. package/dist-lib/components/ui/Progress.js +100 -0
  94. package/dist-lib/components/ui/Progress.js.map +1 -0
  95. package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
  96. package/dist-lib/components/ui/RadioGroup.js +81 -0
  97. package/dist-lib/components/ui/RadioGroup.js.map +1 -0
  98. package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
  99. package/dist-lib/components/ui/RelativeTime.js +31 -0
  100. package/dist-lib/components/ui/RelativeTime.js.map +1 -0
  101. package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
  102. package/dist-lib/components/ui/ScrollArea.js +60 -0
  103. package/dist-lib/components/ui/ScrollArea.js.map +1 -0
  104. package/dist-lib/components/ui/Select.d.ts +6 -1
  105. package/dist-lib/components/ui/Select.js +139 -0
  106. package/dist-lib/components/ui/Select.js.map +1 -0
  107. package/dist-lib/components/ui/Separator.js +26 -0
  108. package/dist-lib/components/ui/Separator.js.map +1 -0
  109. package/dist-lib/components/ui/Sheet.d.ts +10 -1
  110. package/dist-lib/components/ui/Sheet.js +136 -0
  111. package/dist-lib/components/ui/Sheet.js.map +1 -0
  112. package/dist-lib/components/ui/Sidebar.d.ts +29 -14
  113. package/dist-lib/components/ui/Sidebar.js +212 -0
  114. package/dist-lib/components/ui/Sidebar.js.map +1 -0
  115. package/dist-lib/components/ui/Skeleton.d.ts +13 -2
  116. package/dist-lib/components/ui/Skeleton.js +29 -0
  117. package/dist-lib/components/ui/Skeleton.js.map +1 -0
  118. package/dist-lib/components/ui/Slider.js +64 -0
  119. package/dist-lib/components/ui/Slider.js.map +1 -0
  120. package/dist-lib/components/ui/Snackbar.d.ts +1 -1
  121. package/dist-lib/components/ui/Snackbar.js +57 -0
  122. package/dist-lib/components/ui/Snackbar.js.map +1 -0
  123. package/dist-lib/components/ui/Spinner.js +54 -0
  124. package/dist-lib/components/ui/Spinner.js.map +1 -0
  125. package/dist-lib/components/ui/Stepper.d.ts +6 -0
  126. package/dist-lib/components/ui/Stepper.js +111 -0
  127. package/dist-lib/components/ui/Stepper.js.map +1 -0
  128. package/dist-lib/components/ui/Switch.js +80 -0
  129. package/dist-lib/components/ui/Switch.js.map +1 -0
  130. package/dist-lib/components/ui/Table.d.ts +41 -5
  131. package/dist-lib/components/ui/Table.js +179 -0
  132. package/dist-lib/components/ui/Table.js.map +1 -0
  133. package/dist-lib/components/ui/Tabs.d.ts +1 -1
  134. package/dist-lib/components/ui/Tabs.js +91 -0
  135. package/dist-lib/components/ui/Tabs.js.map +1 -0
  136. package/dist-lib/components/ui/TagInput.d.ts +17 -2
  137. package/dist-lib/components/ui/TagInput.js +111 -0
  138. package/dist-lib/components/ui/TagInput.js.map +1 -0
  139. package/dist-lib/components/ui/Textarea.js +88 -0
  140. package/dist-lib/components/ui/Textarea.js.map +1 -0
  141. package/dist-lib/components/ui/Timeline.d.ts +16 -6
  142. package/dist-lib/components/ui/Timeline.js +56 -0
  143. package/dist-lib/components/ui/Timeline.js.map +1 -0
  144. package/dist-lib/components/ui/Toast.d.ts +1 -1
  145. package/dist-lib/components/ui/Toast.js +158 -0
  146. package/dist-lib/components/ui/Toast.js.map +1 -0
  147. package/dist-lib/components/ui/Tooltip.d.ts +4 -1
  148. package/dist-lib/components/ui/Tooltip.js +60 -0
  149. package/dist-lib/components/ui/Tooltip.js.map +1 -0
  150. package/dist-lib/components/ui/TopNav.d.ts +7 -3
  151. package/dist-lib/components/ui/TopNav.js +62 -0
  152. package/dist-lib/components/ui/TopNav.js.map +1 -0
  153. package/dist-lib/components/ui/Tree.d.ts +34 -7
  154. package/dist-lib/components/ui/Tree.js +170 -0
  155. package/dist-lib/components/ui/Tree.js.map +1 -0
  156. package/dist-lib/hooks/use-debounce.d.ts +19 -0
  157. package/dist-lib/hooks/use-debounce.js +36 -0
  158. package/dist-lib/hooks/use-debounce.js.map +1 -0
  159. package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
  160. package/dist-lib/hooks/use-delayed-loading.js +20 -0
  161. package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
  162. package/dist-lib/hooks/use-field-ids.d.ts +30 -0
  163. package/dist-lib/hooks/use-field-ids.js +18 -0
  164. package/dist-lib/hooks/use-field-ids.js.map +1 -0
  165. package/dist-lib/hooks/use-media-query.d.ts +3 -1
  166. package/dist-lib/hooks/use-media-query.js +22 -0
  167. package/dist-lib/hooks/use-media-query.js.map +1 -0
  168. package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
  169. package/dist-lib/hooks/use-modifier-key.js +19 -0
  170. package/dist-lib/hooks/use-modifier-key.js.map +1 -0
  171. package/dist-lib/hooks/use-strings.d.ts +5 -0
  172. package/dist-lib/hooks/use-strings.js +12 -0
  173. package/dist-lib/hooks/use-strings.js.map +1 -0
  174. package/dist-lib/hooks/use-toast.d.ts +7 -2
  175. package/dist-lib/hooks/use-toast.js +67 -0
  176. package/dist-lib/hooks/use-toast.js.map +1 -0
  177. package/dist-lib/icon.d.ts +8 -0
  178. package/dist-lib/icon.js +7 -0
  179. package/dist-lib/icon.js.map +1 -0
  180. package/dist-lib/icons/index.d.ts +80 -88
  181. package/dist-lib/icons/index.js +163 -0
  182. package/dist-lib/icons/index.js.map +1 -0
  183. package/dist-lib/illustrations/index.d.ts +1 -0
  184. package/dist-lib/illustrations/index.js +114 -0
  185. package/dist-lib/illustrations/index.js.map +1 -0
  186. package/dist-lib/index.d.ts +68 -59
  187. package/dist-lib/index.js +288 -4530
  188. package/dist-lib/index.js.map +1 -1
  189. package/dist-lib/lib/format.d.ts +65 -0
  190. package/dist-lib/lib/format.js +95 -0
  191. package/dist-lib/lib/format.js.map +1 -0
  192. package/dist-lib/lib/return-focus.d.ts +11 -0
  193. package/dist-lib/lib/return-focus.js +12 -0
  194. package/dist-lib/lib/return-focus.js.map +1 -0
  195. package/dist-lib/lib/strings.d.ts +190 -0
  196. package/dist-lib/lib/strings.js +141 -0
  197. package/dist-lib/lib/strings.js.map +1 -0
  198. package/dist-lib/lib/strings.mn.d.ts +3 -0
  199. package/dist-lib/lib/strings.mn.js +115 -0
  200. package/dist-lib/lib/strings.mn.js.map +1 -0
  201. package/dist-lib/lib/utils.d.ts +0 -1
  202. package/dist-lib/lib/utils.js +10 -0
  203. package/dist-lib/lib/utils.js.map +1 -0
  204. package/dist-lib/styles.css +1 -1
  205. package/dist-lib/theme.css +840 -0
  206. package/package.json +38 -8
  207. package/dist-lib/index.cjs +0 -8
  208. package/dist-lib/index.cjs.map +0 -1
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Dependency-free locale helpers. Defaults target Mongolia (Asia/Ulaanbaatar,
3
+ * `₮` suffix, `,` thousands) but every option is overridable.
4
+ */
5
+ export interface FormatDateOptions {
6
+ /** IANA zone. Default `Asia/Ulaanbaatar`. */
7
+ tz?: string;
8
+ /**
9
+ * Tokens: `yyyy` `MM` `dd` `HH` `mm` `ss`, plus `M`/`d`/`H` (unpadded).
10
+ * Default `yyyy-MM-dd HH:mm`.
11
+ */
12
+ pattern?: string;
13
+ }
14
+ export declare function getDateTimeFormat(tz: string): Intl.DateTimeFormat;
15
+ /**
16
+ * Format a date in a fixed time zone with a small token pattern.
17
+ *
18
+ * @example
19
+ * formatDate(new Date('2026-08-20T02:05:00Z')) // "2026-08-20 10:05"
20
+ * formatDate(d, { pattern: 'dd.MM.yyyy', tz: 'UTC' }) // "20.08.2026"
21
+ */
22
+ export declare function formatDate(date: Date | number | string, { tz, pattern }?: FormatDateOptions): string;
23
+ export interface FormatNumberOptions {
24
+ /** Max fraction digits. Default 2. */
25
+ maximumFractionDigits?: number;
26
+ /** Min fraction digits. Default 0. */
27
+ minimumFractionDigits?: number;
28
+ /** Thousands separator. Default `,`. */
29
+ group?: string;
30
+ /** Decimal separator. Default `.`. */
31
+ decimal?: string;
32
+ }
33
+ /**
34
+ * Group thousands with a fixed separator (locale-independent, so SSR and
35
+ * client always agree).
36
+ *
37
+ * @example formatNumber(1250000) // "1,250,000"
38
+ */
39
+ export declare function formatNumber(n: number, { maximumFractionDigits, minimumFractionDigits, group, decimal, }?: FormatNumberOptions): string;
40
+ export interface FormatMNTOptions extends Omit<FormatNumberOptions, 'maximumFractionDigits'> {
41
+ /** Abbreviate ≥1,000 as `K` / `M` / `B` with one decimal: `12.4M₮`, `850K₮`. */
42
+ compact?: boolean;
43
+ }
44
+ /**
45
+ * Mongolian tögrög: grouped integer + `₮` suffix, no space.
46
+ *
47
+ * @example formatMNT(1250000) // "1,250,000₮"
48
+ * @example formatMNT(12400000, { compact: true }) // "12.4M₮"
49
+ * @example formatMNT(850000, { compact: true }) // "850K₮"
50
+ */
51
+ export declare function formatMNT(n: number, { compact, ...options }?: FormatMNTOptions): string;
52
+ /**
53
+ * Display form for Mongolian phone numbers. Accepts `XXXXXXXX`, `+976XXXXXXXX`,
54
+ * `976XXXXXXXX`, or already-spaced input; anything else is returned unchanged.
55
+ *
56
+ * @example formatPhone('99112233') // "+976 9911 2233"
57
+ * @example formatPhone('+97699112233') // "+976 9911 2233"
58
+ * @example formatPhone('+1 555 0100') // "+1 555 0100" (non-MN, untouched)
59
+ */
60
+ export declare function formatPhone(input: string): string;
61
+ /**
62
+ * Normalise a Mongolian phone number to E.164 (`+976XXXXXXXX`) for storage.
63
+ * Returns `null` when the input is not an 8-digit MN number.
64
+ */
65
+ export declare function parsePhoneMN(input: string): string | null;
@@ -0,0 +1,95 @@
1
+ "use client";
2
+ const o = (t, r = 2) => String(t).padStart(r, "0"), u = /* @__PURE__ */ new Map();
3
+ function f(t) {
4
+ let r = u.get(t);
5
+ return r || (r = new Intl.DateTimeFormat("en-US", {
6
+ timeZone: t,
7
+ hourCycle: "h23",
8
+ year: "numeric",
9
+ month: "2-digit",
10
+ day: "2-digit",
11
+ hour: "2-digit",
12
+ minute: "2-digit",
13
+ second: "2-digit"
14
+ }), u.set(t, r)), r;
15
+ }
16
+ function g(t, r) {
17
+ const n = f(r), i = {};
18
+ for (const e of n.formatToParts(t))
19
+ e.type !== "literal" && (i[e.type] = Number(e.value));
20
+ return i;
21
+ }
22
+ function l(t, { tz: r = "Asia/Ulaanbaatar", pattern: n = "yyyy-MM-dd HH:mm" } = {}) {
23
+ const i = t instanceof Date ? t : new Date(t);
24
+ if (Number.isNaN(i.getTime())) return "";
25
+ const e = g(i, r), c = e.hour === 24 ? 0 : e.hour;
26
+ return n.replace(/yyyy|MM|dd|HH|mm|ss|M|d|H/g, (a) => {
27
+ switch (a) {
28
+ case "yyyy":
29
+ return String(e.year);
30
+ case "MM":
31
+ return o(e.month);
32
+ case "dd":
33
+ return o(e.day);
34
+ case "HH":
35
+ return o(c);
36
+ case "mm":
37
+ return o(e.minute);
38
+ case "ss":
39
+ return o(e.second);
40
+ case "M":
41
+ return String(e.month);
42
+ case "d":
43
+ return String(e.day);
44
+ case "H":
45
+ return String(c);
46
+ default:
47
+ return a;
48
+ }
49
+ });
50
+ }
51
+ function m(t, {
52
+ maximumFractionDigits: r = 2,
53
+ minimumFractionDigits: n = 0,
54
+ group: i = ",",
55
+ decimal: e = "."
56
+ } = {}) {
57
+ if (!Number.isFinite(t)) return "";
58
+ const c = Math.abs(t).toFixed(r);
59
+ let [a, s = ""] = c.split(".");
60
+ s = s.replace(/0+$/, "");
61
+ const d = t < 0 && Number(c) !== 0 ? "-" : "";
62
+ for (; s.length < n; ) s += "0";
63
+ return a = a.replace(/\B(?=(\d{3})+(?!\d))/g, i), `${d}${a}${s ? e + s : ""}`;
64
+ }
65
+ function y(t, { compact: r, ...n } = {}) {
66
+ if (r && Number.isFinite(t) && Math.abs(t) >= 1e3) {
67
+ const i = [
68
+ [1e9, "B"],
69
+ [1e6, "M"],
70
+ [1e3, "K"]
71
+ ];
72
+ let e = i.findIndex(([s]) => Math.abs(t) >= s);
73
+ e > 0 && Math.abs(t / i[e][0]).toFixed(1) === "1000.0" && (e -= 1);
74
+ const [c, a] = i[e];
75
+ return `${m(t / c, { ...n, maximumFractionDigits: 1 })}${a}₮`;
76
+ }
77
+ return `${m(t, { ...n, maximumFractionDigits: 0 })}₮`;
78
+ }
79
+ function h(t) {
80
+ const r = t.replace(/[\s\-().]/g, ""), n = /^(?:\+?976)?(\d{8})$/.exec(r);
81
+ return n ? `+976 ${n[1].slice(0, 4)} ${n[1].slice(4)}` : t;
82
+ }
83
+ function M(t) {
84
+ const r = t.replace(/[\s\-().]/g, ""), n = /^(?:\+?976)?(\d{8})$/.exec(r);
85
+ return n ? `+976${n[1]}` : null;
86
+ }
87
+ export {
88
+ l as formatDate,
89
+ y as formatMNT,
90
+ m as formatNumber,
91
+ h as formatPhone,
92
+ f as getDateTimeFormat,
93
+ M as parsePhoneMN
94
+ };
95
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sources":["../../src/lib/format.ts"],"sourcesContent":["'use client';\n\n/**\n * Dependency-free locale helpers. Defaults target Mongolia (Asia/Ulaanbaatar,\n * `₮` suffix, `,` thousands) but every option is overridable.\n */\n\nexport interface FormatDateOptions {\n /** IANA zone. Default `Asia/Ulaanbaatar`. */\n tz?: string;\n /**\n * Tokens: `yyyy` `MM` `dd` `HH` `mm` `ss`, plus `M`/`d`/`H` (unpadded).\n * Default `yyyy-MM-dd HH:mm`.\n */\n pattern?: string;\n}\n\nconst pad = (n: number, w = 2) => String(n).padStart(w, '0');\n\n/** Intl.DateTimeFormat construction is expensive (~ms); cache per zone. */\nconst dtfCache = new Map<string, Intl.DateTimeFormat>();\n\nexport function getDateTimeFormat(tz: string): Intl.DateTimeFormat {\n let dtf = dtfCache.get(tz);\n if (!dtf) {\n dtf = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n hourCycle: 'h23',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n dtfCache.set(tz, dtf);\n }\n return dtf;\n}\n\nfunction parts(d: Date, tz: string) {\n const dtf = getDateTimeFormat(tz);\n const out: Record<string, number> = {};\n for (const p of dtf.formatToParts(d)) {\n if (p.type !== 'literal') out[p.type] = Number(p.value);\n }\n return out;\n}\n\n/**\n * Format a date in a fixed time zone with a small token pattern.\n *\n * @example\n * formatDate(new Date('2026-08-20T02:05:00Z')) // \"2026-08-20 10:05\"\n * formatDate(d, { pattern: 'dd.MM.yyyy', tz: 'UTC' }) // \"20.08.2026\"\n */\nexport function formatDate(\n date: Date | number | string,\n { tz = 'Asia/Ulaanbaatar', pattern = 'yyyy-MM-dd HH:mm' }: FormatDateOptions = {},\n): string {\n const d = date instanceof Date ? date : new Date(date);\n if (Number.isNaN(d.getTime())) return '';\n const p = parts(d, tz);\n const hour = p.hour === 24 ? 0 : p.hour;\n return pattern.replace(/yyyy|MM|dd|HH|mm|ss|M|d|H/g, (t) => {\n switch (t) {\n case 'yyyy':\n return String(p.year);\n case 'MM':\n return pad(p.month);\n case 'dd':\n return pad(p.day);\n case 'HH':\n return pad(hour);\n case 'mm':\n return pad(p.minute);\n case 'ss':\n return pad(p.second);\n case 'M':\n return String(p.month);\n case 'd':\n return String(p.day);\n case 'H':\n return String(hour);\n default:\n return t;\n }\n });\n}\n\nexport interface FormatNumberOptions {\n /** Max fraction digits. Default 2. */\n maximumFractionDigits?: number;\n /** Min fraction digits. Default 0. */\n minimumFractionDigits?: number;\n /** Thousands separator. Default `,`. */\n group?: string;\n /** Decimal separator. Default `.`. */\n decimal?: string;\n}\n\n/**\n * Group thousands with a fixed separator (locale-independent, so SSR and\n * client always agree).\n *\n * @example formatNumber(1250000) // \"1,250,000\"\n */\nexport function formatNumber(\n n: number,\n {\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n group = ',',\n decimal = '.',\n }: FormatNumberOptions = {},\n): string {\n if (!Number.isFinite(n)) return '';\n const fixed = Math.abs(n).toFixed(maximumFractionDigits);\n let [int, frac = ''] = fixed.split('.');\n frac = frac.replace(/0+$/, '');\n // Normalise -0 and values that round to zero (e.g. -0.001) → \"0\", not \"-0\".\n const sign = n < 0 && Number(fixed) !== 0 ? '-' : '';\n while (frac.length < minimumFractionDigits) frac += '0';\n int = int.replace(/\\B(?=(\\d{3})+(?!\\d))/g, group);\n return `${sign}${int}${frac ? decimal + frac : ''}`;\n}\n\nexport interface FormatMNTOptions extends Omit<FormatNumberOptions, 'maximumFractionDigits'> {\n /** Abbreviate ≥1,000 as `K` / `M` / `B` with one decimal: `12.4M₮`, `850K₮`. */\n compact?: boolean;\n}\n\n/**\n * Mongolian tögrög: grouped integer + `₮` suffix, no space.\n *\n * @example formatMNT(1250000) // \"1,250,000₮\"\n * @example formatMNT(12400000, { compact: true }) // \"12.4M₮\"\n * @example formatMNT(850000, { compact: true }) // \"850K₮\"\n */\nexport function formatMNT(n: number, { compact, ...options }: FormatMNTOptions = {}) {\n if (compact && Number.isFinite(n) && Math.abs(n) >= 1000) {\n const units: Array<[number, string]> = [\n [1e9, 'B'],\n [1e6, 'M'],\n [1e3, 'K'],\n ];\n let idx = units.findIndex(([d]) => Math.abs(n) >= d);\n // 999,999 → \"1000.0K\" after rounding; promote to the next unit instead.\n if (idx > 0 && Math.abs(n / units[idx][0]).toFixed(1) === '1000.0') idx -= 1;\n const [div, unit] = units[idx];\n return `${formatNumber(n / div, { ...options, maximumFractionDigits: 1 })}${unit}₮`;\n }\n return `${formatNumber(n, { ...options, maximumFractionDigits: 0 })}₮`;\n}\n\n/**\n * Display form for Mongolian phone numbers. Accepts `XXXXXXXX`, `+976XXXXXXXX`,\n * `976XXXXXXXX`, or already-spaced input; anything else is returned unchanged.\n *\n * @example formatPhone('99112233') // \"+976 9911 2233\"\n * @example formatPhone('+97699112233') // \"+976 9911 2233\"\n * @example formatPhone('+1 555 0100') // \"+1 555 0100\" (non-MN, untouched)\n */\nexport function formatPhone(input: string): string {\n const digits = input.replace(/[\\s\\-().]/g, '');\n const m = /^(?:\\+?976)?(\\d{8})$/.exec(digits);\n if (!m) return input;\n return `+976 ${m[1].slice(0, 4)} ${m[1].slice(4)}`;\n}\n\n/**\n * Normalise a Mongolian phone number to E.164 (`+976XXXXXXXX`) for storage.\n * Returns `null` when the input is not an 8-digit MN number.\n */\nexport function parsePhoneMN(input: string): string | null {\n const digits = input.replace(/[\\s\\-().]/g, '');\n const m = /^(?:\\+?976)?(\\d{8})$/.exec(digits);\n return m ? `+976${m[1]}` : null;\n}\n"],"names":["pad","n","w","dtfCache","getDateTimeFormat","tz","dtf","parts","d","out","p","formatDate","date","pattern","hour","t","formatNumber","maximumFractionDigits","minimumFractionDigits","group","decimal","fixed","int","frac","sign","formatMNT","compact","options","units","idx","div","unit","formatPhone","input","digits","m","parsePhoneMN"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { RefObject } from 'react';
2
+ /** Element that should receive focus when an overlay closes. */
3
+ export type ReturnFocusRef = RefObject<HTMLElement | null>;
4
+ /**
5
+ * Build an `onCloseAutoFocus` handler that moves focus to `returnFocusTo`
6
+ * instead of Radix's default (the element focused when the content mounted —
7
+ * which is `<body>` for controlled overlays opened from a pointer click on a
8
+ * non-focusable or tooltip-wrapped trigger). A consumer handler runs first
9
+ * and wins if it calls `preventDefault()`.
10
+ */
11
+ export declare function withReturnFocus(returnFocusTo: ReturnFocusRef | undefined, handler: ((e: Event) => void) | undefined): ((e: Event) => void) | undefined;
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ function r(e, t) {
3
+ return e ? (u) => {
4
+ if (t == null || t(u), u.defaultPrevented) return;
5
+ const f = e.current;
6
+ f && (u.preventDefault(), f.focus());
7
+ } : t;
8
+ }
9
+ export {
10
+ r as withReturnFocus
11
+ };
12
+ //# sourceMappingURL=return-focus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-focus.js","sources":["../../src/lib/return-focus.ts"],"sourcesContent":["import type { RefObject } from 'react';\n\n/** Element that should receive focus when an overlay closes. */\nexport type ReturnFocusRef = RefObject<HTMLElement | null>;\n\n/**\n * Build an `onCloseAutoFocus` handler that moves focus to `returnFocusTo`\n * instead of Radix's default (the element focused when the content mounted —\n * which is `<body>` for controlled overlays opened from a pointer click on a\n * non-focusable or tooltip-wrapped trigger). A consumer handler runs first\n * and wins if it calls `preventDefault()`.\n */\nexport function withReturnFocus(\n returnFocusTo: ReturnFocusRef | undefined,\n handler: ((e: Event) => void) | undefined,\n): ((e: Event) => void) | undefined {\n if (!returnFocusTo) return handler;\n return (e) => {\n handler?.(e);\n if (e.defaultPrevented) return;\n const el = returnFocusTo.current;\n if (!el) return;\n e.preventDefault();\n el.focus();\n };\n}\n"],"names":["withReturnFocus","returnFocusTo","handler","e","el"],"mappings":";AAYO,SAASA,EACdC,GACAC,GACkC;AAClC,SAAKD,IACE,CAACE,MAAM;AAEZ,QADAD,KAAA,QAAAA,EAAUC,IACNA,EAAE,iBAAkB;AACxB,UAAMC,IAAKH,EAAc;AACzB,IAAKG,MACLD,EAAE,eAAA,GACFC,EAAG,MAAA;AAAA,EACL,IAR2BF;AAS7B;"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Every user-facing string the library renders on its own (aria-labels,
3
+ * placeholders, empty states, …). Consumers override any subset through
4
+ * `<DesignSystemProvider strings={…}>`; per-component props still win.
5
+ *
6
+ * Placeholders use `{name}` and are expanded with `formatString`.
7
+ */
8
+ export interface UiStrings {
9
+ alert: {
10
+ dismiss: string;
11
+ };
12
+ snackbar: {
13
+ dismiss: string;
14
+ };
15
+ dialog: {
16
+ close: string;
17
+ };
18
+ sheet: {
19
+ close: string;
20
+ };
21
+ toast: {
22
+ close: string;
23
+ region: string;
24
+ };
25
+ drawer: {
26
+ close: string;
27
+ };
28
+ command: {
29
+ suggestions: string;
30
+ };
31
+ calendar: {
32
+ previous: string;
33
+ next: string;
34
+ chooseMonth: string;
35
+ chooseYear: string;
36
+ nav: string;
37
+ };
38
+ confirmationDialog: {
39
+ confirm: string;
40
+ cancel: string;
41
+ };
42
+ commandDialog: {
43
+ title: string;
44
+ };
45
+ carousel: {
46
+ label: string;
47
+ previous: string;
48
+ next: string;
49
+ slide: string;
50
+ };
51
+ pagination: {
52
+ showing: string;
53
+ rowsPerPage: string;
54
+ first: string;
55
+ last: string;
56
+ prev: string;
57
+ next: string;
58
+ page: string;
59
+ perPage: string;
60
+ nav: string;
61
+ };
62
+ breadcrumbs: {
63
+ label: string;
64
+ collapsed: string;
65
+ };
66
+ stepper: {
67
+ label: string;
68
+ complete: string;
69
+ current: string;
70
+ upcoming: string;
71
+ };
72
+ topNav: {
73
+ label: string;
74
+ };
75
+ sidebar: {
76
+ label: string;
77
+ collapse: string;
78
+ expand: string;
79
+ collapseShort: string;
80
+ };
81
+ select: {
82
+ placeholder: string;
83
+ };
84
+ combobox: {
85
+ placeholder: string;
86
+ searchPlaceholder: string;
87
+ empty: string;
88
+ clear: string;
89
+ loadError: string;
90
+ };
91
+ multiSelect: {
92
+ placeholder: string;
93
+ empty: string;
94
+ clearAll: string;
95
+ remove: string;
96
+ };
97
+ tagInput: {
98
+ placeholder: string;
99
+ remove: string;
100
+ };
101
+ dataGrid: {
102
+ filterPlaceholder: string;
103
+ empty: string;
104
+ /** Screen-reader label for an empty cell rendered as an em dash. */
105
+ emptyCell: string;
106
+ columns: string;
107
+ columnVisibility: string;
108
+ filterRows: string;
109
+ };
110
+ datePicker: {
111
+ pickDate: string;
112
+ pickRange: string;
113
+ };
114
+ fileUpload: {
115
+ drop: string;
116
+ remove: string;
117
+ bytes: string;
118
+ kilobytes: string;
119
+ megabytes: string;
120
+ };
121
+ input: {
122
+ clear: string;
123
+ showPassword: string;
124
+ hidePassword: string;
125
+ };
126
+ slider: {
127
+ minimum: string;
128
+ maximum: string;
129
+ value: string;
130
+ };
131
+ spinner: {
132
+ loading: string;
133
+ };
134
+ errorState: {
135
+ notFoundTitle: string;
136
+ notFoundDescription: string;
137
+ serverTitle: string;
138
+ serverDescription: string;
139
+ genericTitle: string;
140
+ genericDescription: string;
141
+ forbiddenTitle: string;
142
+ forbiddenDescription: string;
143
+ tryAgain: string;
144
+ };
145
+ avatar: {
146
+ status: string;
147
+ more: string;
148
+ };
149
+ tree: {
150
+ label: string;
151
+ };
152
+ /** Accessible name of the focusable scroll wrapper around the table. */
153
+ table: {
154
+ scrollRegion: string;
155
+ };
156
+ /** Accessible name of the focusable scroll viewport. */
157
+ scrollArea: {
158
+ region: string;
159
+ };
160
+ chart: {
161
+ series: string;
162
+ noData: string;
163
+ loading: string;
164
+ empty: string;
165
+ error: string;
166
+ viewAsTable: string;
167
+ hideTable: string;
168
+ tableCaption: string;
169
+ summary: string;
170
+ point: string;
171
+ seriesNav: string;
172
+ };
173
+ relativeTime: {
174
+ justNow: string;
175
+ minutesAgo: string;
176
+ hoursAgo: string;
177
+ daysAgo: string;
178
+ inMinutes: string;
179
+ inHours: string;
180
+ inDays: string;
181
+ };
182
+ }
183
+ export type DeepPartial<T> = {
184
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
185
+ };
186
+ export declare const defaultStrings: UiStrings;
187
+ /** Expand `{name}` placeholders. Unknown placeholders are left as-is. */
188
+ export declare function formatString(template: string, vars: Record<string, string | number | undefined>): string;
189
+ /** Deep-merge a partial override on top of a complete strings object. `undefined` leaves are ignored. */
190
+ export declare function mergeStrings(base: UiStrings, override?: DeepPartial<UiStrings>): UiStrings;
@@ -0,0 +1,141 @@
1
+ "use client";
2
+ const l = {
3
+ alert: { dismiss: "Dismiss" },
4
+ snackbar: { dismiss: "Dismiss" },
5
+ dialog: { close: "Close" },
6
+ sheet: { close: "Close" },
7
+ toast: { close: "Close", region: "Notifications" },
8
+ drawer: { close: "Close" },
9
+ command: { suggestions: "Suggestions" },
10
+ calendar: {
11
+ previous: "Previous month",
12
+ next: "Next month",
13
+ chooseMonth: "Choose the month",
14
+ chooseYear: "Choose the year",
15
+ nav: "Calendar navigation"
16
+ },
17
+ confirmationDialog: { confirm: "Confirm", cancel: "Cancel" },
18
+ commandDialog: { title: "Command palette" },
19
+ carousel: { label: "Carousel", previous: "Previous", next: "Next", slide: "{index} of {count}" },
20
+ pagination: {
21
+ showing: "Showing {from}–{to} of {total}",
22
+ rowsPerPage: "Rows per page",
23
+ first: "Go to first page",
24
+ last: "Go to last page",
25
+ prev: "Previous page",
26
+ next: "Next page",
27
+ page: "Page {n}",
28
+ perPage: "{n} / page",
29
+ nav: "Pagination"
30
+ },
31
+ breadcrumbs: { label: "Breadcrumb", collapsed: "Hidden items" },
32
+ stepper: { label: "Progress", complete: "Completed", current: "Current", upcoming: "Upcoming" },
33
+ topNav: { label: "Primary" },
34
+ sidebar: {
35
+ label: "Primary",
36
+ collapse: "Collapse sidebar",
37
+ expand: "Expand sidebar",
38
+ collapseShort: "Collapse"
39
+ },
40
+ select: { placeholder: "Select…" },
41
+ combobox: {
42
+ placeholder: "Select…",
43
+ searchPlaceholder: "Search…",
44
+ empty: "No results.",
45
+ clear: "Clear selection",
46
+ loadError: "Couldn't load options."
47
+ },
48
+ multiSelect: {
49
+ placeholder: "Select…",
50
+ empty: "No results.",
51
+ clearAll: "Clear all",
52
+ remove: "Remove {label}"
53
+ },
54
+ tagInput: { placeholder: "Add and press Enter", remove: "Remove {tag}" },
55
+ dataGrid: {
56
+ filterPlaceholder: "Filter…",
57
+ empty: "No results.",
58
+ emptyCell: "Empty",
59
+ columns: "Columns",
60
+ columnVisibility: "Column visibility",
61
+ filterRows: "Filter rows"
62
+ },
63
+ datePicker: { pickDate: "Pick a date", pickRange: "Pick a range" },
64
+ fileUpload: {
65
+ drop: "Drop files here, or click to browse",
66
+ remove: "Remove {name}",
67
+ bytes: "{n} B",
68
+ kilobytes: "{n} KB",
69
+ megabytes: "{n} MB"
70
+ },
71
+ input: { clear: "Clear input", showPassword: "Show password", hidePassword: "Hide password" },
72
+ slider: { minimum: "Minimum", maximum: "Maximum", value: "Value" },
73
+ spinner: { loading: "Loading" },
74
+ errorState: {
75
+ notFoundTitle: "Page not found",
76
+ notFoundDescription: "We couldn't find what you were looking for.",
77
+ serverTitle: "Something went wrong",
78
+ serverDescription: "We're looking into it. Please try again in a moment.",
79
+ genericTitle: "Unexpected error",
80
+ genericDescription: "Something interrupted this action.",
81
+ forbiddenTitle: "You don't have access",
82
+ forbiddenDescription: "Ask an admin to grant the permission.",
83
+ tryAgain: "Try again"
84
+ },
85
+ avatar: { status: "Status: {status}", more: "{n} more" },
86
+ tree: { label: "Tree" },
87
+ table: { scrollRegion: "Scrollable table" },
88
+ scrollArea: { region: "Scrollable content" },
89
+ chart: {
90
+ series: "Series {n}",
91
+ noData: "no data",
92
+ loading: "Loading chart…",
93
+ empty: "No data to display.",
94
+ error: "Couldn't load this chart.",
95
+ viewAsTable: "View as table",
96
+ hideTable: "Hide table",
97
+ tableCaption: "Data table for {name}",
98
+ summary: "{name}: {count} points, min {min}, max {max}, last {x}: {y}",
99
+ point: "{x}: {y}",
100
+ seriesNav: "{name}, {count} points. Use arrow keys to move between points."
101
+ },
102
+ relativeTime: {
103
+ justNow: "just now",
104
+ minutesAgo: "{n} min ago",
105
+ hoursAgo: "{n} h ago",
106
+ daysAgo: "{n} d ago",
107
+ inMinutes: "in {n} min",
108
+ inHours: "in {n} h",
109
+ inDays: "in {n} d"
110
+ }
111
+ };
112
+ function c(e, t) {
113
+ return e.replace(/\{(\w+)\}/g, (a, n) => {
114
+ const o = t[n];
115
+ return o === void 0 ? a : String(o);
116
+ });
117
+ }
118
+ function m(e, t) {
119
+ return t ? s(
120
+ e,
121
+ t
122
+ ) : e;
123
+ }
124
+ function i(e) {
125
+ return typeof e == "object" && e !== null && !Array.isArray(e);
126
+ }
127
+ function s(e, t) {
128
+ const a = { ...e };
129
+ for (const [n, o] of Object.entries(t)) {
130
+ if (o === void 0) continue;
131
+ const r = a[n];
132
+ a[n] = i(o) && i(r) ? s(r, o) : o;
133
+ }
134
+ return a;
135
+ }
136
+ export {
137
+ l as defaultStrings,
138
+ c as formatString,
139
+ m as mergeStrings
140
+ };
141
+ //# sourceMappingURL=strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.js","sources":["../../src/lib/strings.ts"],"sourcesContent":["'use client';\n\n/**\n * Every user-facing string the library renders on its own (aria-labels,\n * placeholders, empty states, …). Consumers override any subset through\n * `<DesignSystemProvider strings={…}>`; per-component props still win.\n *\n * Placeholders use `{name}` and are expanded with `formatString`.\n */\nexport interface UiStrings {\n alert: { dismiss: string };\n snackbar: { dismiss: string };\n dialog: { close: string };\n sheet: { close: string };\n toast: { close: string; region: string };\n drawer: { close: string };\n command: { suggestions: string };\n calendar: {\n previous: string;\n next: string;\n chooseMonth: string;\n chooseYear: string;\n nav: string;\n };\n confirmationDialog: { confirm: string; cancel: string };\n commandDialog: { title: string };\n carousel: { label: string; previous: string; next: string; slide: string };\n pagination: {\n showing: string;\n rowsPerPage: string;\n first: string;\n last: string;\n prev: string;\n next: string;\n page: string;\n perPage: string;\n nav: string;\n };\n breadcrumbs: { label: string; collapsed: string };\n stepper: { label: string; complete: string; current: string; upcoming: string };\n topNav: { label: string };\n sidebar: { label: string; collapse: string; expand: string; collapseShort: string };\n select: { placeholder: string };\n combobox: {\n placeholder: string;\n searchPlaceholder: string;\n empty: string;\n clear: string;\n loadError: string;\n };\n multiSelect: { placeholder: string; empty: string; clearAll: string; remove: string };\n tagInput: { placeholder: string; remove: string };\n dataGrid: {\n filterPlaceholder: string;\n empty: string;\n /** Screen-reader label for an empty cell rendered as an em dash. */\n emptyCell: string;\n columns: string;\n columnVisibility: string;\n filterRows: string;\n };\n datePicker: { pickDate: string; pickRange: string };\n fileUpload: { drop: string; remove: string; bytes: string; kilobytes: string; megabytes: string };\n input: { clear: string; showPassword: string; hidePassword: string };\n slider: { minimum: string; maximum: string; value: string };\n spinner: { loading: string };\n errorState: {\n notFoundTitle: string;\n notFoundDescription: string;\n serverTitle: string;\n serverDescription: string;\n genericTitle: string;\n genericDescription: string;\n forbiddenTitle: string;\n forbiddenDescription: string;\n tryAgain: string;\n };\n avatar: { status: string; more: string };\n tree: { label: string };\n /** Accessible name of the focusable scroll wrapper around the table. */\n table: { scrollRegion: string };\n /** Accessible name of the focusable scroll viewport. */\n scrollArea: { region: string };\n chart: {\n series: string;\n noData: string;\n loading: string;\n empty: string;\n error: string;\n viewAsTable: string;\n hideTable: string;\n tableCaption: string;\n summary: string;\n point: string;\n seriesNav: string;\n };\n relativeTime: {\n justNow: string;\n minutesAgo: string;\n hoursAgo: string;\n daysAgo: string;\n inMinutes: string;\n inHours: string;\n inDays: string;\n };\n}\n\nexport type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] };\n\nexport const defaultStrings: UiStrings = {\n alert: { dismiss: 'Dismiss' },\n snackbar: { dismiss: 'Dismiss' },\n dialog: { close: 'Close' },\n sheet: { close: 'Close' },\n toast: { close: 'Close', region: 'Notifications' },\n drawer: { close: 'Close' },\n command: { suggestions: 'Suggestions' },\n calendar: {\n previous: 'Previous month',\n next: 'Next month',\n chooseMonth: 'Choose the month',\n chooseYear: 'Choose the year',\n nav: 'Calendar navigation',\n },\n confirmationDialog: { confirm: 'Confirm', cancel: 'Cancel' },\n commandDialog: { title: 'Command palette' },\n carousel: { label: 'Carousel', previous: 'Previous', next: 'Next', slide: '{index} of {count}' },\n pagination: {\n showing: 'Showing {from}–{to} of {total}',\n rowsPerPage: 'Rows per page',\n first: 'Go to first page',\n last: 'Go to last page',\n prev: 'Previous page',\n next: 'Next page',\n page: 'Page {n}',\n perPage: '{n} / page',\n nav: 'Pagination',\n },\n breadcrumbs: { label: 'Breadcrumb', collapsed: 'Hidden items' },\n stepper: { label: 'Progress', complete: 'Completed', current: 'Current', upcoming: 'Upcoming' },\n topNav: { label: 'Primary' },\n sidebar: {\n label: 'Primary',\n collapse: 'Collapse sidebar',\n expand: 'Expand sidebar',\n collapseShort: 'Collapse',\n },\n select: { placeholder: 'Select…' },\n combobox: {\n placeholder: 'Select…',\n searchPlaceholder: 'Search…',\n empty: 'No results.',\n clear: 'Clear selection',\n loadError: \"Couldn't load options.\",\n },\n multiSelect: {\n placeholder: 'Select…',\n empty: 'No results.',\n clearAll: 'Clear all',\n remove: 'Remove {label}',\n },\n tagInput: { placeholder: 'Add and press Enter', remove: 'Remove {tag}' },\n dataGrid: {\n filterPlaceholder: 'Filter…',\n empty: 'No results.',\n emptyCell: 'Empty',\n columns: 'Columns',\n columnVisibility: 'Column visibility',\n filterRows: 'Filter rows',\n },\n datePicker: { pickDate: 'Pick a date', pickRange: 'Pick a range' },\n fileUpload: {\n drop: 'Drop files here, or click to browse',\n remove: 'Remove {name}',\n bytes: '{n} B',\n kilobytes: '{n} KB',\n megabytes: '{n} MB',\n },\n input: { clear: 'Clear input', showPassword: 'Show password', hidePassword: 'Hide password' },\n slider: { minimum: 'Minimum', maximum: 'Maximum', value: 'Value' },\n spinner: { loading: 'Loading' },\n errorState: {\n notFoundTitle: 'Page not found',\n notFoundDescription: \"We couldn't find what you were looking for.\",\n serverTitle: 'Something went wrong',\n serverDescription: \"We're looking into it. Please try again in a moment.\",\n genericTitle: 'Unexpected error',\n genericDescription: 'Something interrupted this action.',\n forbiddenTitle: \"You don't have access\",\n forbiddenDescription: 'Ask an admin to grant the permission.',\n tryAgain: 'Try again',\n },\n avatar: { status: 'Status: {status}', more: '{n} more' },\n tree: { label: 'Tree' },\n table: { scrollRegion: 'Scrollable table' },\n scrollArea: { region: 'Scrollable content' },\n chart: {\n series: 'Series {n}',\n noData: 'no data',\n loading: 'Loading chart…',\n empty: 'No data to display.',\n error: \"Couldn't load this chart.\",\n viewAsTable: 'View as table',\n hideTable: 'Hide table',\n tableCaption: 'Data table for {name}',\n summary: '{name}: {count} points, min {min}, max {max}, last {x}: {y}',\n point: '{x}: {y}',\n seriesNav: '{name}, {count} points. Use arrow keys to move between points.',\n },\n relativeTime: {\n justNow: 'just now',\n minutesAgo: '{n} min ago',\n hoursAgo: '{n} h ago',\n daysAgo: '{n} d ago',\n inMinutes: 'in {n} min',\n inHours: 'in {n} h',\n inDays: 'in {n} d',\n },\n};\n\n/** Expand `{name}` placeholders. Unknown placeholders are left as-is. */\nexport function formatString(\n template: string,\n vars: Record<string, string | number | undefined>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n const v = vars[key];\n return v === undefined ? match : String(v);\n });\n}\n\n/** Deep-merge a partial override on top of a complete strings object. `undefined` leaves are ignored. */\nexport function mergeStrings(base: UiStrings, override?: DeepPartial<UiStrings>): UiStrings {\n if (!override) return base;\n return deepMerge(\n base as unknown as Record<string, unknown>,\n override as Record<string, unknown>,\n ) as unknown as UiStrings;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction deepMerge(\n base: Record<string, unknown>,\n override: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n const current = out[key];\n out[key] = isPlainObject(value) && isPlainObject(current) ? deepMerge(current, value) : value;\n }\n return out;\n}\n"],"names":["defaultStrings","formatString","template","vars","match","key","v","mergeStrings","base","override","deepMerge","isPlainObject","out","value","current"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { UiStrings } from './strings.js';
2
+ /** Mongolian (Cyrillic) translation — pass to `<DesignSystemProvider strings={mnStrings}>`. */
3
+ export declare const mnStrings: UiStrings;