@lotics/ui 5.2.0 → 5.3.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.
package/AGENTS.md CHANGED
@@ -13,8 +13,8 @@ typeahead, async search, virtualization, and a11y the primitive already ships.
13
13
  - RN-Web only: `View`/`ScrollView` from `react-native`, the `Text` primitive (no raw
14
14
  `div`/`span`, no raw `fontSize`/`fontWeight`); styles are RN objects.
15
15
  - i18n: most components are string-free; the few that emit their own user-facing strings take
16
- a `labels` prop (`DateRangeFilterField`, `Pagination`, `SortHeader`/`Table.sortLabels`) —
17
- localize there.
16
+ a `labels` prop (`DateRangeFilterField`, `Pagination`, `SortHeader`/`Table.sortLabels`,
17
+ `RemainderMeter`) — localize there.
18
18
 
19
19
  ---
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./tokens": "./src/tokens.ts",
@@ -2,6 +2,26 @@ import { StyleSheet, View, type DimensionValue } from "react-native";
2
2
  import { colors, solid } from "./colors";
3
3
  import { Text } from "./text";
4
4
 
5
+ /**
6
+ * Override the meter's captions for localization. Each key is optional and
7
+ * falls back to English (mirrors `PaginationLabels` / `DateRangeFilterField`).
8
+ */
9
+ export interface RemainderMeterLabels {
10
+ /** The left caption. Default: `{allocated} of {total} applied`. */
11
+ applied?: (allocated: string, total: string) => string;
12
+ /** UNDER state (a remainder still to place). Default: `{remainder} unapplied`. */
13
+ remaining?: (remainder: string) => string;
14
+ /** OVER state (over-allocated). Default: `Over by {amount}`. */
15
+ over?: (amount: string) => string;
16
+ /** EXACT state. Default: `Fully applied`. */
17
+ exact?: string;
18
+ }
19
+
20
+ const defaultApplied = (allocated: string, total: string) => `${allocated} of ${total} applied`;
21
+ const defaultRemaining = (remainder: string) => `${remainder} unapplied`;
22
+ const defaultOver = (amount: string) => `Over by ${amount}`;
23
+ const DEFAULT_EXACT = "Fully applied";
24
+
5
25
  export interface RemainderMeterProps {
6
26
  /** The source amount being distributed — the payment, the available stock. */
7
27
  total: number;
@@ -9,6 +29,8 @@ export interface RemainderMeterProps {
9
29
  allocated: number;
10
30
  /** Format amounts (money / units). Defaults to a plain locale string. */
11
31
  format?: (n: number) => string;
32
+ /** Localize the captions; each key falls back to English. */
33
+ labels?: RemainderMeterLabels;
12
34
  }
13
35
 
14
36
  /**
@@ -20,17 +42,21 @@ export interface RemainderMeterProps {
20
42
  * distribution, budgeting.
21
43
  */
22
44
  export function RemainderMeter(props: RemainderMeterProps) {
23
- const { total, allocated, format = (n) => n.toLocaleString() } = props;
45
+ const { total, allocated, format = (n) => n.toLocaleString(), labels } = props;
24
46
  const remainder = total - allocated;
25
47
  const state = remainder > 0 ? "under" : remainder < 0 ? "over" : "exact";
26
48
  const pct: DimensionValue = `${total <= 0 ? 0 : Math.min(100, (allocated / total) * 100)}%`;
27
49
  const barColor = state === "over" ? solid("red") : state === "exact" ? solid("emerald") : solid("blue");
28
50
  const right =
29
- state === "exact" ? "Fully applied" : state === "over" ? `Over by ${format(-remainder)}` : `${format(remainder)} unapplied`;
51
+ state === "exact"
52
+ ? (labels?.exact ?? DEFAULT_EXACT)
53
+ : state === "over"
54
+ ? (labels?.over ?? defaultOver)(format(-remainder))
55
+ : (labels?.remaining ?? defaultRemaining)(format(remainder));
30
56
  return (
31
57
  <View style={{ gap: 8 }}>
32
58
  <View style={{ flexDirection: "row", alignItems: "baseline", gap: 8 }}>
33
- <Text size="sm" color="muted" style={{ flex: 1 }}>{`${format(allocated)} of ${format(total)} applied`}</Text>
59
+ <Text size="sm" color="muted" style={{ flex: 1 }}>{(labels?.applied ?? defaultApplied)(format(allocated), format(total))}</Text>
34
60
  <Text size="sm" weight="medium" tabular color={state === "over" ? "danger" : state === "exact" ? "success" : "default"}>
35
61
  {right}
36
62
  </Text>