@nibapp/ui 0.0.0-stage → 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 (292) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +21 -0
  3. package/README.md +124 -2
  4. package/TRADEMARKS.md +22 -0
  5. package/dist/_bundled/money/index.d.ts +98 -0
  6. package/dist/_bundled/money/index.js +152 -0
  7. package/dist/_bundled/tokens/index.d.ts +2 -0
  8. package/dist/_bundled/tokens/index.js +2 -0
  9. package/dist/_bundled/tokens/palette.gen.d.ts +51 -0
  10. package/dist/_bundled/tokens/palette.gen.js +206 -0
  11. package/dist/_bundled/tokens/spec.d.ts +291 -0
  12. package/dist/_bundled/tokens/spec.js +221 -0
  13. package/dist/components/accordion.d.ts +27 -0
  14. package/dist/components/accordion.js +66 -0
  15. package/dist/components/alert-dialog.d.ts +59 -0
  16. package/dist/components/alert-dialog.js +82 -0
  17. package/dist/components/alert.d.ts +141 -0
  18. package/dist/components/alert.js +55 -0
  19. package/dist/components/appear.d.ts +21 -0
  20. package/dist/components/appear.js +42 -0
  21. package/dist/components/avatar.d.ts +196 -0
  22. package/dist/components/avatar.js +135 -0
  23. package/dist/components/badge.d.ts +183 -0
  24. package/dist/components/badge.js +68 -0
  25. package/dist/components/block-stack.d.ts +33 -0
  26. package/dist/components/block-stack.js +197 -0
  27. package/dist/components/button.d.ts +327 -0
  28. package/dist/components/button.js +101 -0
  29. package/dist/components/card.d.ts +131 -0
  30. package/dist/components/card.js +100 -0
  31. package/dist/components/checkbox.d.ts +34 -0
  32. package/dist/components/checkbox.js +37 -0
  33. package/dist/components/choice-row.d.ts +104 -0
  34. package/dist/components/choice-row.js +56 -0
  35. package/dist/components/clamped-text.d.ts +17 -0
  36. package/dist/components/clamped-text.js +47 -0
  37. package/dist/components/code-block.d.ts +48 -0
  38. package/dist/components/code-block.js +124 -0
  39. package/dist/components/code-input.d.ts +49 -0
  40. package/dist/components/code-input.js +59 -0
  41. package/dist/components/combobox.d.ts +194 -0
  42. package/dist/components/combobox.js +176 -0
  43. package/dist/components/command-palette.d.ts +57 -0
  44. package/dist/components/command-palette.js +83 -0
  45. package/dist/components/context-menu.d.ts +24 -0
  46. package/dist/components/context-menu.js +30 -0
  47. package/dist/components/copy-button.d.ts +9 -0
  48. package/dist/components/copy-button.js +20 -0
  49. package/dist/components/copy-command.d.ts +18 -0
  50. package/dist/components/copy-command.js +19 -0
  51. package/dist/components/data-table.d.ts +240 -0
  52. package/dist/components/data-table.js +63 -0
  53. package/dist/components/dialog.d.ts +80 -0
  54. package/dist/components/dialog.js +85 -0
  55. package/dist/components/diff-lines.d.ts +20 -0
  56. package/dist/components/diff-lines.js +10 -0
  57. package/dist/components/diff-view.d.ts +128 -0
  58. package/dist/components/diff-view.js +675 -0
  59. package/dist/components/disclosure.d.ts +33 -0
  60. package/dist/components/disclosure.js +51 -0
  61. package/dist/components/drawn-check.d.ts +8 -0
  62. package/dist/components/drawn-check.js +16 -0
  63. package/dist/components/edge-resizer.d.ts +26 -0
  64. package/dist/components/edge-resizer.js +53 -0
  65. package/dist/components/empty-state.d.ts +112 -0
  66. package/dist/components/empty-state.js +56 -0
  67. package/dist/components/expand-toggle.d.ts +19 -0
  68. package/dist/components/expand-toggle.js +10 -0
  69. package/dist/components/field.d.ts +48 -0
  70. package/dist/components/field.js +60 -0
  71. package/dist/components/filter-chip.d.ts +47 -0
  72. package/dist/components/filter-chip.js +33 -0
  73. package/dist/components/group.d.ts +10 -0
  74. package/dist/components/group.js +9 -0
  75. package/dist/components/icon-text.d.ts +11 -0
  76. package/dist/components/icon-text.js +10 -0
  77. package/dist/components/image-sources.d.ts +57 -0
  78. package/dist/components/image-sources.js +58 -0
  79. package/dist/components/image-thumbnail.d.ts +34 -0
  80. package/dist/components/image-thumbnail.js +58 -0
  81. package/dist/components/image-viewer.d.ts +60 -0
  82. package/dist/components/image-viewer.js +411 -0
  83. package/dist/components/inline-edit.d.ts +22 -0
  84. package/dist/components/inline-edit.js +51 -0
  85. package/dist/components/input.d.ts +155 -0
  86. package/dist/components/input.js +109 -0
  87. package/dist/components/item-label.d.ts +11 -0
  88. package/dist/components/item-label.js +5 -0
  89. package/dist/components/item-row.d.ts +23 -0
  90. package/dist/components/item-row.js +19 -0
  91. package/dist/components/kbd.d.ts +55 -0
  92. package/dist/components/kbd.js +86 -0
  93. package/dist/components/link-policy.d.ts +24 -0
  94. package/dist/components/link-policy.js +32 -0
  95. package/dist/components/linked-text.d.ts +15 -0
  96. package/dist/components/linked-text.js +48 -0
  97. package/dist/components/loading-region.d.ts +18 -0
  98. package/dist/components/loading-region.js +17 -0
  99. package/dist/components/markdown.d.ts +34 -0
  100. package/dist/components/markdown.js +307 -0
  101. package/dist/components/menu.d.ts +132 -0
  102. package/dist/components/menu.js +102 -0
  103. package/dist/components/message-bubble.d.ts +57 -0
  104. package/dist/components/message-bubble.js +28 -0
  105. package/dist/components/meta-line.d.ts +28 -0
  106. package/dist/components/meta-line.js +36 -0
  107. package/dist/components/money-input.d.ts +23 -0
  108. package/dist/components/money-input.js +34 -0
  109. package/dist/components/native-select.d.ts +120 -0
  110. package/dist/components/native-select.js +85 -0
  111. package/dist/components/page-trail.d.ts +30 -0
  112. package/dist/components/page-trail.js +43 -0
  113. package/dist/components/page.d.ts +80 -0
  114. package/dist/components/page.js +60 -0
  115. package/dist/components/path-text.d.ts +8 -0
  116. package/dist/components/path-text.js +11 -0
  117. package/dist/components/percent-input.d.ts +20 -0
  118. package/dist/components/percent-input.js +32 -0
  119. package/dist/components/popover.d.ts +52 -0
  120. package/dist/components/popover.js +36 -0
  121. package/dist/components/progress.d.ts +389 -0
  122. package/dist/components/progress.js +142 -0
  123. package/dist/components/radio.d.ts +65 -0
  124. package/dist/components/radio.js +54 -0
  125. package/dist/components/remote-image-gate.d.ts +34 -0
  126. package/dist/components/remote-image-gate.js +60 -0
  127. package/dist/components/resizable.d.ts +23 -0
  128. package/dist/components/resizable.js +30 -0
  129. package/dist/components/rolling-number.d.ts +13 -0
  130. package/dist/components/rolling-number.js +69 -0
  131. package/dist/components/scroll-area.d.ts +17 -0
  132. package/dist/components/scroll-area.js +25 -0
  133. package/dist/components/section-label.d.ts +10 -0
  134. package/dist/components/section-label.js +21 -0
  135. package/dist/components/section-nav.d.ts +22 -0
  136. package/dist/components/section-nav.js +80 -0
  137. package/dist/components/segmented-control.d.ts +125 -0
  138. package/dist/components/segmented-control.js +101 -0
  139. package/dist/components/select.d.ts +120 -0
  140. package/dist/components/select.js +89 -0
  141. package/dist/components/separator.d.ts +10 -0
  142. package/dist/components/separator.js +12 -0
  143. package/dist/components/sheet.d.ts +101 -0
  144. package/dist/components/sheet.js +129 -0
  145. package/dist/components/shortcut-recorder.d.ts +31 -0
  146. package/dist/components/shortcut-recorder.js +67 -0
  147. package/dist/components/skeleton.d.ts +31 -0
  148. package/dist/components/skeleton.js +33 -0
  149. package/dist/components/slider.d.ts +138 -0
  150. package/dist/components/slider.js +98 -0
  151. package/dist/components/spinner.d.ts +37 -0
  152. package/dist/components/spinner.js +16 -0
  153. package/dist/components/switch.d.ts +59 -0
  154. package/dist/components/switch.js +56 -0
  155. package/dist/components/tab-strip.d.ts +29 -0
  156. package/dist/components/tab-strip.js +42 -0
  157. package/dist/components/tabs.d.ts +13 -0
  158. package/dist/components/tabs.js +68 -0
  159. package/dist/components/text-link.d.ts +54 -0
  160. package/dist/components/text-link.js +38 -0
  161. package/dist/components/textarea.d.ts +75 -0
  162. package/dist/components/textarea.js +90 -0
  163. package/dist/components/toast.d.ts +74 -0
  164. package/dist/components/toast.js +128 -0
  165. package/dist/components/tooltip.d.ts +50 -0
  166. package/dist/components/tooltip.js +46 -0
  167. package/dist/components/truncated-text.d.ts +15 -0
  168. package/dist/components/truncated-text.js +19 -0
  169. package/dist/i18n/defaults.d.ts +7 -0
  170. package/dist/i18n/defaults.js +7 -0
  171. package/dist/i18n/format.d.ts +84 -0
  172. package/dist/i18n/format.js +169 -0
  173. package/dist/i18n/index.d.ts +6 -0
  174. package/dist/i18n/index.js +8 -0
  175. package/dist/i18n/locales/ru-formatters.d.ts +3 -0
  176. package/dist/i18n/locales/ru-formatters.js +22 -0
  177. package/dist/i18n/locales/ru.d.ts +5 -0
  178. package/dist/i18n/locales/ru.js +185 -0
  179. package/dist/i18n/plural.d.ts +20 -0
  180. package/dist/i18n/plural.js +26 -0
  181. package/dist/i18n/provider.d.ts +36 -0
  182. package/dist/i18n/provider.js +39 -0
  183. package/dist/i18n/rich.d.ts +14 -0
  184. package/dist/i18n/rich.js +44 -0
  185. package/dist/i18n/ru-plural.d.ts +3 -0
  186. package/dist/i18n/ru-plural.js +4 -0
  187. package/dist/i18n/strings/alert-dialog.d.ts +5 -0
  188. package/dist/i18n/strings/alert-dialog.js +5 -0
  189. package/dist/i18n/strings/block-stack.d.ts +17 -0
  190. package/dist/i18n/strings/block-stack.js +11 -0
  191. package/dist/i18n/strings/code-block.d.ts +18 -0
  192. package/dist/i18n/strings/code-block.js +13 -0
  193. package/dist/i18n/strings/combobox.d.ts +12 -0
  194. package/dist/i18n/strings/combobox.js +10 -0
  195. package/dist/i18n/strings/command-palette.d.ts +17 -0
  196. package/dist/i18n/strings/command-palette.js +11 -0
  197. package/dist/i18n/strings/diff-view.d.ts +92 -0
  198. package/dist/i18n/strings/diff-view.js +68 -0
  199. package/dist/i18n/strings/image-viewer.d.ts +43 -0
  200. package/dist/i18n/strings/image-viewer.js +32 -0
  201. package/dist/i18n/strings/index.d.ts +314 -0
  202. package/dist/i18n/strings/index.js +43 -0
  203. package/dist/i18n/strings/kbd.d.ts +42 -0
  204. package/dist/i18n/strings/kbd.js +39 -0
  205. package/dist/i18n/strings/markdown.d.ts +23 -0
  206. package/dist/i18n/strings/markdown.js +18 -0
  207. package/dist/i18n/strings/money.d.ts +7 -0
  208. package/dist/i18n/strings/money.js +5 -0
  209. package/dist/i18n/strings/primitives.d.ts +25 -0
  210. package/dist/i18n/strings/primitives.js +18 -0
  211. package/dist/i18n/strings/progress.d.ts +4 -0
  212. package/dist/i18n/strings/progress.js +4 -0
  213. package/dist/i18n/strings/shortcut-recorder.d.ts +15 -0
  214. package/dist/i18n/strings/shortcut-recorder.js +11 -0
  215. package/dist/i18n/strings/time.d.ts +41 -0
  216. package/dist/i18n/strings/time.js +20 -0
  217. package/dist/i18n/strings/toast.d.ts +6 -0
  218. package/dist/i18n/strings/toast.js +6 -0
  219. package/dist/i18n/time-zones.d.ts +20 -0
  220. package/dist/i18n/time-zones.js +64 -0
  221. package/dist/index.d.ts +84 -0
  222. package/dist/index.js +88 -0
  223. package/dist/lib/ansi.d.ts +55 -0
  224. package/dist/lib/ansi.js +438 -0
  225. package/dist/lib/clock.d.ts +32 -0
  226. package/dist/lib/clock.js +106 -0
  227. package/dist/lib/cn.d.ts +12 -0
  228. package/dist/lib/cn.js +28 -0
  229. package/dist/lib/control-props.d.ts +21 -0
  230. package/dist/lib/control-props.js +14 -0
  231. package/dist/lib/direction.d.ts +13 -0
  232. package/dist/lib/direction.js +25 -0
  233. package/dist/lib/image-size.d.ts +12 -0
  234. package/dist/lib/image-size.js +66 -0
  235. package/dist/lib/keycaps.d.ts +21 -0
  236. package/dist/lib/keycaps.js +62 -0
  237. package/dist/lib/keyed.d.ts +9 -0
  238. package/dist/lib/keyed.js +14 -0
  239. package/dist/lib/keys.d.ts +49 -0
  240. package/dist/lib/keys.js +159 -0
  241. package/dist/lib/kit-motion.d.ts +9 -0
  242. package/dist/lib/kit-motion.js +12 -0
  243. package/dist/lib/link-check-dialog.d.ts +11 -0
  244. package/dist/lib/link-check-dialog.js +18 -0
  245. package/dist/lib/motion-features.d.ts +1 -0
  246. package/dist/lib/motion-features.js +4 -0
  247. package/dist/lib/motion-provider.d.ts +5 -0
  248. package/dist/lib/motion-provider.js +8 -0
  249. package/dist/lib/motion.d.ts +39 -0
  250. package/dist/lib/motion.js +49 -0
  251. package/dist/lib/number-format.d.ts +114 -0
  252. package/dist/lib/number-format.js +313 -0
  253. package/dist/lib/patch.d.ts +72 -0
  254. package/dist/lib/patch.js +344 -0
  255. package/dist/lib/path.d.ts +34 -0
  256. package/dist/lib/path.js +85 -0
  257. package/dist/lib/search.d.ts +10 -0
  258. package/dist/lib/search.js +20 -0
  259. package/dist/lib/shiki-themes.d.ts +7 -0
  260. package/dist/lib/shiki-themes.js +115 -0
  261. package/dist/lib/shiki.d.ts +101 -0
  262. package/dist/lib/shiki.js +353 -0
  263. package/dist/lib/shortcut-context.d.ts +23 -0
  264. package/dist/lib/shortcut-context.js +29 -0
  265. package/dist/lib/text.d.ts +56 -0
  266. package/dist/lib/text.js +149 -0
  267. package/dist/lib/theme-scope.d.ts +18 -0
  268. package/dist/lib/theme-scope.js +24 -0
  269. package/dist/lib/theme.d.ts +40 -0
  270. package/dist/lib/theme.js +96 -0
  271. package/dist/lib/tree-keys.d.ts +72 -0
  272. package/dist/lib/tree-keys.js +126 -0
  273. package/dist/lib/url.d.ts +17 -0
  274. package/dist/lib/url.js +38 -0
  275. package/dist/lib/use-copy-to-clipboard.d.ts +13 -0
  276. package/dist/lib/use-copy-to-clipboard.js +40 -0
  277. package/dist/lib/use-delayed-loading.d.ts +11 -0
  278. package/dist/lib/use-delayed-loading.js +31 -0
  279. package/dist/lib/use-file-picker.d.ts +26 -0
  280. package/dist/lib/use-file-picker.js +43 -0
  281. package/dist/lib/use-hydrated.d.ts +6 -0
  282. package/dist/lib/use-hydrated.js +11 -0
  283. package/dist/lib/use-latest.d.ts +12 -0
  284. package/dist/lib/use-latest.js +22 -0
  285. package/dist/lib/use-resolved-theme.d.ts +12 -0
  286. package/dist/lib/use-resolved-theme.js +25 -0
  287. package/dist/styles/base.css +393 -0
  288. package/dist/styles/code.css +35 -0
  289. package/dist/styles/fonts.css +12 -0
  290. package/dist/styles/index.css +13 -0
  291. package/dist/styles/tokens.gen.css +494 -0
  292. package/package.json +208 -4
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
4
+ import { useRef, useState } from "react";
5
+ import { cn } from "../lib/cn.js";
6
+ import { TooltipContent } from "./tooltip.js";
7
+ /**
8
+ * One line of text that truncates with an ellipsis when its box is too narrow, and then shows the
9
+ * whole of it in a tooltip on hover. Text that fits has no tooltip. Screen readers always get the
10
+ * full text (the cut is visual). Use it for names and titles that must stay on one line.
11
+ */
12
+ export function TruncatedText({ children, full, side, className, ...props }) {
13
+ const ref = useRef(null);
14
+ const [open, setOpen] = useState(false);
15
+ return (_jsxs(BaseTooltip.Root, { open: open, onOpenChange: (next) => {
16
+ const el = ref.current;
17
+ setOpen(next && el !== null && el.scrollWidth > el.clientWidth + 1);
18
+ }, children: [_jsx(BaseTooltip.Trigger, { render: _jsx("span", { ref: ref, "data-slot": "truncated-text", className: cn("block min-w-0 truncate", className), ...props }), children: children }), _jsx(TooltipContent, { ...(side === undefined ? {} : { side }), children: _jsx("span", { className: "break-words", children: full ?? children }) })] }));
19
+ }
@@ -0,0 +1,7 @@
1
+ /** The language the kit speaks without a provider, and whose table every other one matches. */
2
+ export declare const DEFAULT_LOCALE = "en";
3
+ /**
4
+ * The tag English is formatted with when no provider names one: day before month and a 24-hour clock
5
+ * ("1 Nov", "14:05"), the kit's own choice. A provider's `locale` always wins.
6
+ */
7
+ export declare const ENGLISH_FORMAT_LOCALE = "en-GB";
@@ -0,0 +1,7 @@
1
+ /** The language the kit speaks without a provider, and whose table every other one matches. */
2
+ export const DEFAULT_LOCALE = "en";
3
+ /**
4
+ * The tag English is formatted with when no provider names one: day before month and a 24-hour clock
5
+ * ("1 Nov", "14:05"), the kit's own choice. A provider's `locale` always wins.
6
+ */
7
+ export const ENGLISH_FORMAT_LOCALE = "en-GB";
@@ -0,0 +1,84 @@
1
+ import { type Amount } from "../lib/number-format.js";
2
+ import { type UiStrings } from "./strings/index.js";
3
+ /** A unit of a spoken time phrase (`Intl.RelativeTimeFormat` unit names). */
4
+ export type TimeUnit = "second" | "minute" | "hour" | "day";
5
+ /** Whole minutes as the largest sensible unit, like `span`: 12 → 12 minutes, 180 → 3 hours, 2880 → 2 days. */
6
+ export declare function spanValue(minutes: number): {
7
+ readonly value: number;
8
+ readonly unit: "minute" | "hour" | "day";
9
+ };
10
+ /** Locale-aware formatters. Get them from `useFormatters()`; English output is the house style. */
11
+ export interface UiFormatters {
12
+ readonly locale: string;
13
+ /** IANA zone dates and clock times are shown in (the person's); `undefined`: the runtime's own. */
14
+ readonly timeZone: string | undefined;
15
+ /** A plain number in the locale: "1,234.5" / "1 234,5". */
16
+ readonly number: (n: number, options?: Intl.NumberFormatOptions) => string;
17
+ /** `formatCount`: "58.7k" / "58,7 тыс.". */
18
+ readonly count: (n: number) => string;
19
+ /** `formatMoney`: "$1,204" / "1 204 $", in the amount's currency. */
20
+ readonly money: (amount: Amount) => string;
21
+ /** Money in words for composite labels: "1.84 US dollars"; dust is "less than 0.01 US dollars". */
22
+ readonly spokenMoney: (amount: Amount) => string;
23
+ /** Whole units, for amounts people set: "$25", "25 $". */
24
+ readonly wholeMoney: (amount: Amount) => string;
25
+ /** An amount exactly as set or billed: "$25", "$2.50", "$1,204.50"; never rounded to whole units. */
26
+ readonly exactMoney: (amount: Amount) => string;
27
+ /** A low–high range: "$0.05–$0.20", "0,05–0,20 $". */
28
+ readonly moneyRange: (low: Amount, high: Amount) => string;
29
+ /** A unit price, sub-cent digits kept: "$4", "$2.50", "$0.075". */
30
+ readonly unitPrice: (amount: Amount) => string;
31
+ /** A currency's symbol (`currency`'s, else the provider's) and the side the locale writes it on, for amount fields. */
32
+ readonly currencySymbol: (currency?: string) => {
33
+ readonly symbol: string;
34
+ readonly leading: boolean;
35
+ };
36
+ /** A size, decimal like Finder: "2.4 MB", "830 kB", "12 bytes" / "2,4 МБ", "12 байт". */
37
+ readonly bytes: (n: number) => string;
38
+ /** Memory, binary as the system reports RAM: 32 GiB is "32 GB", 512 MiB "512 MB" / "32 ГБ". */
39
+ readonly memory: (n: number) => string;
40
+ /**
41
+ * A percent (0–100) as the locale writes it (`Intl.NumberFormat`'s percent style): "61%", "61 %",
42
+ * "%61". Whole by default; `maximumFractionDigits` keeps decimals ("1.8%").
43
+ */
44
+ readonly percent: (pct: number, options?: {
45
+ readonly maximumFractionDigits?: number;
46
+ }) => string;
47
+ /** Elapsed time: "850ms", "4.2s", "42s", "3m 05s", "2h 05m". */
48
+ readonly duration: (ms: number) => string;
49
+ /** A live counter in whole seconds: "12s", "1m 04s", "1h 02m" (a finished span reads `duration`). */
50
+ readonly elapsed: (ms: number) => string;
51
+ /** Whole minutes as the largest sensible unit: "12m", "3h", "2d" (spoken: "12 minutes"). */
52
+ readonly span: (minutes: number, options?: {
53
+ readonly spoken?: boolean;
54
+ }) => string;
55
+ /**
56
+ * A future time as a whole phrase in the locale's grammar (`Intl.RelativeTimeFormat`):
57
+ * "in 12 minutes", "через 1 минуту". For sentences like "Expires {relative}".
58
+ */
59
+ readonly future: (value: number, unit: TimeUnit) => string;
60
+ /**
61
+ * A past time as a whole phrase in the locale's grammar (`Intl.RelativeTimeFormat`): "4 minutes
62
+ * ago", "4 минуты назад". For sentences like "Started {relative}" (`relativeTime` is a column label).
63
+ */
64
+ readonly past: (value: number, unit: TimeUnit) => string;
65
+ /** "now", "4m", "3h", "yesterday", "5d", then a short date. */
66
+ readonly relativeTime: (at: string | number | Date, now?: number) => string;
67
+ /** "Oct 21" / "21 окт.". */
68
+ readonly shortDate: (at: string | number | Date) => string;
69
+ /** "09:41 AM" / "09:41"; undefined for an invalid date. */
70
+ readonly clockTime: (at: string | number | Date) => string | undefined;
71
+ }
72
+ /**
73
+ * Builds the formatters for a locale (the exact BCP 47 tag) and its `time` / `money` strings.
74
+ * `Intl` objects are created on first use and owned by the returned object — never cached at
75
+ * module scope, since one SSR process may render several locales. `UiI18nProvider` keeps one per
76
+ * locale; pure helpers build English ones per call (`englishFormatters()`), which is cheap. A number
77
+ * is shown as money in `currency`; without one, only `Money` amounts (which carry their own) can be.
78
+ */
79
+ export declare function createFormatters(locale: string, strings: Pick<UiStrings, "time" | "money">, timeZone?: string, currency?: string): UiFormatters;
80
+ /**
81
+ * Fresh formatters in the default language, whose strings are the source table: the default of the
82
+ * pure helpers (`formatRelativeTime`, `formatTimeLeft`, …).
83
+ */
84
+ export declare function englishFormatters(currency?: string): UiFormatters;
@@ -0,0 +1,169 @@
1
+ import { createNumberFormatters } from "../lib/number-format.js";
2
+ import { ENGLISH_FORMAT_LOCALE } from "./defaults.js";
3
+ import { EN_UI_STRINGS } from "./strings/index.js";
4
+ /** Whole minutes as the largest sensible unit, like `span`: 12 → 12 minutes, 180 → 3 hours, 2880 → 2 days. */
5
+ export function spanValue(minutes) {
6
+ if (minutes < 60)
7
+ return { value: minutes, unit: "minute" };
8
+ const hours = Math.round(minutes / 60);
9
+ if (hours < 48)
10
+ return { value: hours, unit: "hour" };
11
+ return { value: Math.round(hours / 24), unit: "day" };
12
+ }
13
+ /** Sizes count in thousands (Finder, file sizes); memory in 1024s, as systems report RAM. */
14
+ const DECIMAL = 1000;
15
+ const BINARY = 1024;
16
+ /** A byte count in its largest unit of `base` (`Intl` unit names). */
17
+ function byteUnit(bytes, base) {
18
+ if (bytes >= base ** 3)
19
+ return [bytes / base ** 3, "gigabyte"];
20
+ if (bytes >= base ** 2)
21
+ return [bytes / base ** 2, "megabyte"];
22
+ if (bytes >= base)
23
+ return [bytes / base, "kilobyte"];
24
+ return [bytes, "byte"];
25
+ }
26
+ /**
27
+ * Builds the formatters for a locale (the exact BCP 47 tag) and its `time` / `money` strings.
28
+ * `Intl` objects are created on first use and owned by the returned object — never cached at
29
+ * module scope, since one SSR process may render several locales. `UiI18nProvider` keeps one per
30
+ * locale; pure helpers build English ones per call (`englishFormatters()`), which is cheap. A number
31
+ * is shown as money in `currency`; without one, only `Money` amounts (which carry their own) can be.
32
+ */
33
+ export function createFormatters(locale, strings, timeZone, currency) {
34
+ const { time, money } = strings;
35
+ const numbers = createNumberFormatters(locale, currency);
36
+ let dateFormat;
37
+ let clockFormat;
38
+ let relativeFormat;
39
+ const numberFormats = new Map();
40
+ const number = (n, options) => {
41
+ const key = options === undefined ? "" : JSON.stringify(options);
42
+ let format = numberFormats.get(key);
43
+ if (format === undefined) {
44
+ format = new Intl.NumberFormat(locale, options);
45
+ numberFormats.set(key, format);
46
+ }
47
+ return format.format(n);
48
+ };
49
+ const integer = (n) => number(n, { useGrouping: false });
50
+ // A minute or more of whole seconds: "3m 05s" under an hour, "2h 05m" from one.
51
+ const minutesOrHours = (seconds) => {
52
+ const m = Math.floor(seconds / 60);
53
+ if (m < 60) {
54
+ return time.minutesSecondsShort({
55
+ minutes: integer(m),
56
+ seconds: String(seconds % 60).padStart(2, "0"),
57
+ });
58
+ }
59
+ return time.hoursMinutesShort({
60
+ hours: integer(Math.floor(m / 60)),
61
+ minutes: String(m % 60).padStart(2, "0"),
62
+ });
63
+ };
64
+ const oneDecimal = (n) => number(n, { minimumFractionDigits: 1, maximumFractionDigits: 1 });
65
+ const span = (minutes, options) => {
66
+ const spoken = options?.spoken === true;
67
+ const { value, unit } = spanValue(minutes);
68
+ if (unit === "minute") {
69
+ return spoken ? time.minutes({ count: value }) : time.minutesShort({ value: integer(value) });
70
+ }
71
+ if (unit === "hour")
72
+ return spoken ? time.hours({ count: value }) : time.hoursShort({ value: integer(value) });
73
+ return spoken ? time.days({ count: value }) : time.daysShort({ value: integer(value) });
74
+ };
75
+ const size = (bytes, base) => {
76
+ const [value, unit] = byteUnit(bytes, base);
77
+ // Intl's short "byte" doesn't pluralize ("44 byte"); spelled out it does ("44 bytes", "44 байта").
78
+ const unitDisplay = unit === "byte" ? "long" : "short";
79
+ return number(value, { style: "unit", unit, unitDisplay, maximumFractionDigits: 1 });
80
+ };
81
+ const shortDate = (at) => {
82
+ dateFormat ??= new Intl.DateTimeFormat(locale, { month: "short", day: "numeric", timeZone });
83
+ return dateFormat.format(new Date(at));
84
+ };
85
+ return {
86
+ locale,
87
+ timeZone,
88
+ number,
89
+ count: numbers.count,
90
+ money: numbers.money,
91
+ spokenMoney: (amount) => {
92
+ const floor = numbers.dustFloor(amount);
93
+ return floor === undefined
94
+ ? numbers.spokenMoney(amount)
95
+ : money.spokenDust({ amount: numbers.spokenMoney(floor) });
96
+ },
97
+ wholeMoney: numbers.wholeMoney,
98
+ exactMoney: numbers.exactMoney,
99
+ moneyRange: numbers.moneyRange,
100
+ unitPrice: numbers.unitPrice,
101
+ currencySymbol: numbers.currencySymbol,
102
+ bytes: (n) => size(n, DECIMAL),
103
+ memory: (n) => size(n, BINARY),
104
+ percent: (pct, options) => {
105
+ const digits = options?.maximumFractionDigits ?? 0;
106
+ // Rounded in percent first, so 57.5 reads as 58, not as 0.575's binary 0.57499….
107
+ const scale = 10 ** digits;
108
+ return number(Math.round(pct * scale) / scale / 100, {
109
+ style: "percent",
110
+ maximumFractionDigits: digits,
111
+ });
112
+ },
113
+ duration: (ms) => {
114
+ if (ms < 1000)
115
+ return time.millisecondsShort({ value: integer(Math.max(1, Math.round(ms))) });
116
+ if (ms < 10_000)
117
+ return time.secondsShort({ value: oneDecimal(ms / 1000) });
118
+ if (ms < 60_000)
119
+ return time.secondsShort({ value: integer(Math.round(ms / 1000)) });
120
+ return minutesOrHours(Math.round(ms / 1000));
121
+ },
122
+ elapsed: (ms) => {
123
+ const seconds = Math.max(0, Math.floor(ms / 1000));
124
+ return seconds < 60 ? time.secondsShort({ value: integer(seconds) }) : minutesOrHours(seconds);
125
+ },
126
+ span,
127
+ future: (value, unit) => {
128
+ relativeFormat ??= new Intl.RelativeTimeFormat(locale, { numeric: "always" });
129
+ return relativeFormat.format(value, unit);
130
+ },
131
+ past: (value, unit) => {
132
+ relativeFormat ??= new Intl.RelativeTimeFormat(locale, { numeric: "always" });
133
+ return relativeFormat.format(-value, unit);
134
+ },
135
+ relativeTime: (at, now = Date.now()) => {
136
+ const t = typeof at === "number" ? at : new Date(at).getTime();
137
+ const s = Math.max(0, Math.round((now - t) / 1000));
138
+ if (s < 45)
139
+ return time.now;
140
+ const m = Math.round(s / 60);
141
+ if (m < 60)
142
+ return time.minutesShort({ value: integer(m) });
143
+ const h = Math.round(m / 60);
144
+ if (h < 24)
145
+ return time.hoursShort({ value: integer(h) });
146
+ const d = Math.round(h / 24);
147
+ if (d === 1)
148
+ return time.yesterday;
149
+ if (d < 7)
150
+ return time.daysShort({ value: integer(d) });
151
+ return shortDate(t);
152
+ },
153
+ shortDate,
154
+ clockTime: (at) => {
155
+ const date = at instanceof Date ? at : new Date(at);
156
+ if (Number.isNaN(date.getTime()))
157
+ return undefined;
158
+ clockFormat ??= new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", timeZone });
159
+ return clockFormat.format(date);
160
+ },
161
+ };
162
+ }
163
+ /**
164
+ * Fresh formatters in the default language, whose strings are the source table: the default of the
165
+ * pure helpers (`formatRelativeTime`, `formatTimeLeft`, …).
166
+ */
167
+ export function englishFormatters(currency) {
168
+ return createFormatters(ENGLISH_FORMAT_LOCALE, EN_UI_STRINGS, undefined, currency);
169
+ }
@@ -0,0 +1,6 @@
1
+ export { createFormatters, englishFormatters, spanValue, type TimeUnit, type UiFormatters, } from "./format.js";
2
+ export { digits, type PluralForms, plural } from "./plural.js";
3
+ export { UiI18nProvider, type UiI18nProviderProps, useFormatters, useUiLocale, useUiStrings, } from "./provider.js";
4
+ export { type RichParams, richText } from "./rich.js";
5
+ export { type DeepReadonly, EN_UI_STRINGS, type UiStrings } from "./strings/index.js";
6
+ export { currentZoneName, type TimeZoneOption, timeZoneOptions, zoneCity, zoneLabel } from "./time-zones.js";
@@ -0,0 +1,8 @@
1
+ // @nibapp/ui/i18n — the kit's English strings, locale-aware formatters and the provider that localizes
2
+ // its components in any language (another language's table: `@nibapp/ui/locales/ru`, or your own).
3
+ export { createFormatters, englishFormatters, spanValue, } from "./format.js";
4
+ export { digits, plural } from "./plural.js";
5
+ export { UiI18nProvider, useFormatters, useUiLocale, useUiStrings, } from "./provider.js";
6
+ export { richText } from "./rich.js";
7
+ export { EN_UI_STRINGS } from "./strings/index.js";
8
+ export { currentZoneName, timeZoneOptions, zoneCity, zoneLabel } from "./time-zones.js";
@@ -0,0 +1,3 @@
1
+ import type { UiStrings } from "../strings/index.js";
2
+ export declare const RU_TIME: UiStrings["time"];
3
+ export declare const RU_MONEY: UiStrings["money"];
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The Russian of the kit's formatter words (`time`, `money`), on their own so a host that shows only
3
+ * failures or times (the CLI, the VS Code host, the Action) loads these without the whole table.
4
+ */
5
+ import { NBSP, ru } from "../ru-plural.js";
6
+ export const RU_TIME = {
7
+ now: "сейчас",
8
+ yesterday: "вчера",
9
+ millisecondsShort: (p) => `${p.value}${NBSP}мс`,
10
+ secondsShort: (p) => `${p.value}${NBSP}с`,
11
+ minutesSecondsShort: (p) => `${p.minutes}${NBSP}мин ${p.seconds}${NBSP}с`,
12
+ hoursMinutesShort: (p) => `${p.hours}${NBSP}ч ${p.minutes}${NBSP}мин`,
13
+ minutesShort: (p) => `${p.value}${NBSP}мин`,
14
+ hoursShort: (p) => `${p.value}${NBSP}ч`,
15
+ daysShort: (p) => `${p.value}${NBSP}д`,
16
+ minutes: (p) => ru(p.count, "# минута", "# минуты", "# минут"),
17
+ hours: (p) => ru(p.count, "# час", "# часа", "# часов"),
18
+ days: (p) => ru(p.count, "# день", "# дня", "# дней"),
19
+ };
20
+ export const RU_MONEY = {
21
+ spokenDust: (p) => `меньше ${p.amount}`,
22
+ };
@@ -0,0 +1,5 @@
1
+ import type { UiStrings } from "../strings/index.js";
2
+ /** For writing a Russian table: `ru(count, one, few, many)` picks the plural form, `NBSP` joins a number to its unit. */
3
+ export { NBSP, ru } from "../ru-plural.js";
4
+ export { RU_MONEY, RU_TIME } from "./ru-formatters.js";
5
+ export declare const RU_UI_STRINGS: UiStrings;
@@ -0,0 +1,185 @@
1
+ /**
2
+ * The kit's Russian: every key of `EN_UI_STRINGS`, typed complete, so a key added in English is a
3
+ * compile error until it has Russian. Hand it to `UiI18nProvider` (`strings={RU_UI_STRINGS}`) with a
4
+ * Russian locale ("ru", "ru-RU"). Plurals go through `plural("ru", …)` inside the functions; nothing
5
+ * locale-dependent runs at module scope.
6
+ */
7
+ import { ru } from "../ru-plural.js";
8
+ import { RU_MONEY, RU_TIME } from "./ru-formatters.js";
9
+ /** For writing a Russian table: `ru(count, one, few, many)` picks the plural form, `NBSP` joins a number to its unit. */
10
+ export { NBSP, ru } from "../ru-plural.js";
11
+ export { RU_MONEY, RU_TIME } from "./ru-formatters.js";
12
+ export const RU_UI_STRINGS = {
13
+ money: RU_MONEY,
14
+ imageViewer: {
15
+ open: (p) => `Открыть изображение: ${p.alt}`,
16
+ untitled: "Изображение",
17
+ position: (p) => `${p.index} из ${p.total}`,
18
+ previous: "Предыдущее изображение",
19
+ next: "Следующее изображение",
20
+ zoomIn: "Увеличить",
21
+ zoomOut: "Уменьшить",
22
+ fit: "По размеру окна",
23
+ actualSize: "Реальный размер",
24
+ copy: "Скопировать изображение",
25
+ copied: "Изображение скопировано",
26
+ copyFailed: "Не удалось скопировать изображение",
27
+ save: "Сохранить изображение",
28
+ loading: "Изображение загружается",
29
+ failed: "Не удалось загрузить изображение",
30
+ tooLarge: (p) => p.size === undefined
31
+ ? "Слишком большое, чтобы показать здесь"
32
+ : `Слишком большое, чтобы показать здесь (${p.size})`,
33
+ remote: (p) => `Изображение на ${p.host}`,
34
+ remoteHost: (p) => `— изображение на ${p.host}`,
35
+ openInBrowser: "Открыть в браузере",
36
+ },
37
+ time: RU_TIME,
38
+ alertDialog: { confirm: "Подтвердить", cancel: "Отмена" },
39
+ combobox: {
40
+ clearSelection: "Очистить выбор",
41
+ showOptions: "Показать варианты",
42
+ remove: "Удалить",
43
+ removeItem: (p) => `Удалить ${p.label}`,
44
+ noMatches: "Совпадений нет",
45
+ },
46
+ commandPalette: {
47
+ placeholder: "Введите команду или запрос…",
48
+ label: "Палитра команд",
49
+ loadingResults: "Загружаем результаты",
50
+ searching: "Ищем…",
51
+ noResults: "Ничего не найдено",
52
+ nothingMatches: (p) => `По запросу «${p.query}» ничего не найдено. Попробуйте другое слово.`,
53
+ hints: { navigate: "Перейти", select: "Выбрать", close: "Закрыть" },
54
+ },
55
+ kbd: {
56
+ // Russian keyboards print the same Latin keycap words; only Space is named.
57
+ keys: {
58
+ ctrl: "Ctrl",
59
+ alt: "Alt",
60
+ shift: "Shift",
61
+ enter: "Enter",
62
+ esc: "Esc",
63
+ tab: "Tab",
64
+ space: "Пробел",
65
+ },
66
+ spoken: {
67
+ command: "Command",
68
+ control: "Control",
69
+ option: "Option",
70
+ alt: "Alt",
71
+ shift: "Shift",
72
+ return: "Return",
73
+ enter: "Enter",
74
+ escape: "Escape",
75
+ tab: "Tab",
76
+ space: "Пробел",
77
+ upArrow: "Стрелка вверх",
78
+ downArrow: "Стрелка вниз",
79
+ leftArrow: "Стрелка влево",
80
+ rightArrow: "Стрелка вправо",
81
+ delete: "Delete",
82
+ backspace: "Backspace",
83
+ forwardDelete: "Удаление вперёд",
84
+ repeated: (p) => p.count === 2 ? `${p.key} дважды` : `${p.key} ${p.count} ${ru(p.count, "раз", "раза", "раз")}`,
85
+ },
86
+ },
87
+ progress: { indeterminate: "неопределённый прогресс" },
88
+ blockStack: {
89
+ reorder: (p) => `Переместить: ${p.title}`,
90
+ grip: "перемещаемый",
91
+ reorderHint: "Перетащите или используйте клавиши со стрелками вверх и вниз.",
92
+ moved: (p) => `${p.title}: теперь ${p.position}-й из ${p.count}.`,
93
+ },
94
+ toast: { notifications: "Уведомления", close: "Закрыть уведомление" },
95
+ codeBlock: {
96
+ copy: "Копировать",
97
+ copied: "Скопировано",
98
+ copiedAnnouncement: "Скопировано в буфер обмена",
99
+ copyCommand: (p) => `Копировать ${p.command}`,
100
+ copyLabelledCommand: (p) => `${p.label}: ${p.command}`,
101
+ copyCode: "Копировать код",
102
+ },
103
+ diffView: {
104
+ changeKinds: { new: "Новый", deleted: "Удалён", renamed: "Переименован" },
105
+ stats: (p) => `${ru(p.additions, "# строка добавлена", "# строки добавлено", "# строк добавлено")}, ${ru(p.deletions, "# строка удалена", "# строки удалено", "# строк удалено")}`,
106
+ expandFile: (p) => `Развернуть ${p.path}`,
107
+ collapseFile: (p) => `Свернуть ${p.path}`,
108
+ copyFile: "Копировать файл",
109
+ copyPatch: "Копировать патч",
110
+ showUnchangedLines: "Показать неизменённые строки",
111
+ showAllLines: "Показать все строки",
112
+ collapseUnchangedLines: "Свернуть неизменённые строки",
113
+ softWrap: "Перенос строк",
114
+ wrapLines: "Переносить длинные строки",
115
+ unwrapLines: "Не переносить строки",
116
+ splitView: "Две колонки",
117
+ unifiedView: "Одна колонка",
118
+ switchToSplit: "Показать в две колонки",
119
+ switchToUnified: "Показать в одну колонку",
120
+ expandLines: {
121
+ up: "Показать строки выше",
122
+ down: "Показать строки ниже",
123
+ both: "Показать скрытые строки",
124
+ },
125
+ noChanges: "Изменений нет.",
126
+ nothingToCompare: "Нечего сравнивать.",
127
+ hunk: {
128
+ label: (p) => `Фрагмент ${p.index} из ${p.total}`,
129
+ position: (p) => `Фрагмент ${p.index}/${p.total}`,
130
+ ask: "Спросить",
131
+ askLabel: (p) => `Спросить о фрагменте ${p.index}`,
132
+ comment: "Комментарий",
133
+ commentLabel: (p) => `Прокомментировать фрагмент ${p.index}`,
134
+ revert: "Откатить",
135
+ revertLabel: (p) => `Откатить фрагмент ${p.index}`,
136
+ accept: "Принять",
137
+ acceptLabel: (p) => `Принять фрагмент ${p.index}`,
138
+ accepted: "Принято",
139
+ reverted: "Откачено",
140
+ },
141
+ comment: {
142
+ you: "Вы",
143
+ line: (p) => `строка ${p.line}`,
144
+ remove: (p) => `Удалить комментарий к строке ${p.line}`,
145
+ onOldLine: (p) => `Комментарий к старой строке ${p.line}`,
146
+ onNewLine: (p) => `Комментарий к новой строке ${p.line}`,
147
+ placeholder: "Оставьте комментарий…",
148
+ toAdd: (p) => `${p.keys} — добавить`,
149
+ cancel: "Отмена",
150
+ submit: "Комментировать",
151
+ },
152
+ },
153
+ markdown: {
154
+ taskDone: "Готово",
155
+ taskTodo: "Не сделано",
156
+ remoteImage: (p) => `Изображение с ${p.host}`,
157
+ remoteImageNamed: (p) => `${p.alt} · ${p.host}`,
158
+ loadImage: "Загрузить изображение",
159
+ linkCheck: {
160
+ title: "Открыть ссылку?",
161
+ description: "Она ведёт по этому адресу:",
162
+ open: "Открыть",
163
+ copy: "Скопировать адрес",
164
+ copied: "Скопировано",
165
+ cancel: "Отмена",
166
+ },
167
+ },
168
+ primitives: {
169
+ close: "Закрыть",
170
+ dismiss: "Скрыть",
171
+ clearSearch: "Очистить поиск",
172
+ showMore: "Показать больше",
173
+ showLess: "Свернуть",
174
+ avatarStatus: { online: "в сети", busy: "не беспокоить", away: "нет на месте", offline: "не в сети" },
175
+ moreAvatars: (p) => ru(p.count, "ещё # человек", "ещё # человека", "ещё # человек"),
176
+ trail: "Навигационная цепочка",
177
+ },
178
+ shortcutRecorder: {
179
+ change: "Изменить",
180
+ recording: "Нажмите клавиши…",
181
+ off: "Выключено",
182
+ needsModifier: (p) => `Используйте сочетание с ${p.modifiers}.`,
183
+ needsModifierOrFunctionKey: (p) => `Используйте сочетание с ${p.modifiers} либо функциональную клавишу.`,
184
+ },
185
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * CLDR plural forms. `other` is required; the rest fall back to it. Russian needs `one` (1, 21, 101),
3
+ * `few` (2–4, 22–24) and `many` (0, 5–20, 25–30); English only `one` and `other`.
4
+ */
5
+ export interface PluralForms {
6
+ readonly other: string;
7
+ readonly zero?: string;
8
+ readonly one?: string;
9
+ readonly two?: string;
10
+ readonly few?: string;
11
+ readonly many?: string;
12
+ }
13
+ /**
14
+ * Picks the plural form for `n` with `Intl.PluralRules` and replaces every `#` with `n` (locale
15
+ * digits, no grouping): `plural("ru", 5, { one: "# файл", few: "# файла", many: "# файлов", other: "# файла" })`
16
+ * → "5 файлов". Used by the English defaults; a Paraglide table brings its own plural selection.
17
+ */
18
+ export declare function plural(locale: string, n: number, forms: PluralForms): string;
19
+ /** A count in `locale`'s digits (no grouping), as `plural`'s `#` writes one: for a number a sentence says bare ("Cycle 3"). */
20
+ export declare function digits(locale: string, n: number): string;
@@ -0,0 +1,26 @@
1
+ /** A locale's plural rules and digits, built once per locale: the tables call `plural` per count shown. */
2
+ const PLURAL_INTL = new Map();
3
+ function pluralIntl(locale) {
4
+ let intl = PLURAL_INTL.get(locale);
5
+ if (intl === undefined) {
6
+ intl = {
7
+ rules: new Intl.PluralRules(locale),
8
+ digits: new Intl.NumberFormat(locale, { useGrouping: false, maximumFractionDigits: 2 }),
9
+ };
10
+ PLURAL_INTL.set(locale, intl);
11
+ }
12
+ return intl;
13
+ }
14
+ /**
15
+ * Picks the plural form for `n` with `Intl.PluralRules` and replaces every `#` with `n` (locale
16
+ * digits, no grouping): `plural("ru", 5, { one: "# файл", few: "# файла", many: "# файлов", other: "# файла" })`
17
+ * → "5 файлов". Used by the English defaults; a Paraglide table brings its own plural selection.
18
+ */
19
+ export function plural(locale, n, forms) {
20
+ const form = forms[pluralIntl(locale).rules.select(n)] ?? forms.other;
21
+ return form.includes("#") ? form.replaceAll("#", digits(locale, n)) : form;
22
+ }
23
+ /** A count in `locale`'s digits (no grouping), as `plural`'s `#` writes one: for a number a sentence says bare ("Cycle 3"). */
24
+ export function digits(locale, n) {
25
+ return pluralIntl(locale).digits.format(n);
26
+ }
@@ -0,0 +1,36 @@
1
+ import { type ReactNode } from "react";
2
+ import { type UiFormatters } from "./format.js";
3
+ import { type UiStrings } from "./strings/index.js";
4
+ export interface UiI18nProviderProps {
5
+ /** BCP 47 locale for numbers, money, dates and plurals, used as given: "ru", "ru-RU", "en-GB", "ar". */
6
+ locale: string;
7
+ /**
8
+ * The kit's words in the locale's language: a complete table, such as `RU_UI_STRINGS` from
9
+ * `@nibapp/ui/locales/ru`, or one of your own typed as `UiStrings`. English when left out.
10
+ */
11
+ strings?: UiStrings | undefined;
12
+ /** IANA zone for dates and clock times (the person's own); omitted: the runtime's own. */
13
+ timeZone?: string | undefined;
14
+ /**
15
+ * The ISO 4217 currency a plain number is shown in as money ("USD", "EUR"). `Money` amounts carry
16
+ * their own. Without it, showing a number as money fails: the kit never assumes a currency.
17
+ */
18
+ currency?: string | undefined;
19
+ /** The writing direction of the locale's language ("rtl" for Arabic or Hebrew). Left to right when left out. */
20
+ direction?: "ltr" | "rtl" | undefined;
21
+ children?: ReactNode;
22
+ }
23
+ /**
24
+ * Localizes every kit component below it: its words (`strings`), formatters for the exact tag in its
25
+ * currency, and the writing direction for Base UI (arrow keys, sliders and popup sides follow it in a
26
+ * right-to-left language). Any language works: pass its table and its direction. Without a provider,
27
+ * components render English with "en-GB" formatting, left to right. Explicit label props on a component
28
+ * always win over these strings.
29
+ */
30
+ export declare function UiI18nProvider({ locale, strings, timeZone, currency, direction, children, }: UiI18nProviderProps): import("react").JSX.Element;
31
+ /** The provider's strings; English without one. */
32
+ export declare function useUiStrings(): UiStrings;
33
+ /** Exactly the BCP 47 tag the provider was given ("ru-RU", "en-US"); the default language without one. */
34
+ export declare function useUiLocale(): string;
35
+ /** Count, money, percent, duration, relative-time and date formatters for the provider's locale. */
36
+ export declare function useFormatters(): UiFormatters;