@lotics/ui 7.4.0 → 7.5.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
@@ -20,8 +20,8 @@ typeahead, async search, virtualization, and a11y the primitive already ships.
20
20
  per-instance `labels`/`clearLabel`/`selectAllLabel` still overrides for one-offs, and an un-wrapped
21
21
  app stays English. Wired so far: `Pagination`, `SortHeader`/`Table.sortLabels`, `OptionList`
22
22
  (+ `Select`/`Combobox` built on it), `FilterChip`, `Drawer`, `Confidence`, `RemainderMeter`,
23
- `ChangeReview`/`ChangeReviewActions`, and `DateRangeFilterField`/`DateFilter` (presets + footer +
24
- time-segment a11y, one `dateRange` slice). Adding a string to a wired component's `*Labels` forces
23
+ `ChangeReview`/`ChangeReviewActions`, `DateRangeFilterField`/`DateFilter` (presets + footer +
24
+ time-segment a11y, one `dateRange` slice), and `FormField` (the `optional` marker). Adding a string to a wired component's `*Labels` forces
25
25
  both packs in `locale.tsx` to fill it (compile error) — that's how the kit avoids a silent English
26
26
  leak. Not yet on the provider (pass `labels` for now): calendar/gantt, the file/preview/comment labels.
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./tokens": "./src/tokens.ts",
@@ -2,6 +2,7 @@ import { createContext, useContext, useId } from "react";
2
2
  import { StyleProp, View, ViewStyle } from "react-native";
3
3
  import { Text } from "./text";
4
4
  import { Spacer } from "./spacer";
5
+ import { useLoticsLocale } from "./locale";
5
6
 
6
7
  export interface FormFieldProps {
7
8
  label: string;
@@ -9,7 +10,8 @@ export interface FormFieldProps {
9
10
  description?: string;
10
11
  error?: string;
11
12
  style?: StyleProp<ViewStyle>;
12
- /** Label shown next to `label` when `optional` is true. Default: "Optional". Pass a translated string from the consumer. */
13
+ /** Label shown next to `label` when `optional` is true. Defaults to the locale
14
+ * pack's `formField.optional` ("Optional"); pass to override for one instance. */
13
15
  optionalLabel?: string;
14
16
  }
15
17
 
@@ -40,7 +42,8 @@ export function useFormField(): FormFieldBinding | null {
40
42
  }
41
43
 
42
44
  export function FormField(props: FormFieldProps & { children: React.ReactNode }) {
43
- const { label, description, error, optional, style, children, optionalLabel = "Optional" } = props;
45
+ const { label, description, error, optional, style, children, optionalLabel } = props;
46
+ const resolvedOptionalLabel = optionalLabel ?? useLoticsLocale().formField.optional;
44
47
 
45
48
  const inputId = useId();
46
49
  const labelId = `${inputId}-label`;
@@ -72,7 +75,7 @@ export function FormField(props: FormFieldProps & { children: React.ReactNode })
72
75
  )}
73
76
  {!!optional && (
74
77
  <Text numberOfLines={1} size="sm" color="zinc-500">
75
- {optionalLabel}
78
+ {resolvedOptionalLabel}
76
79
  </Text>
77
80
  )}
78
81
  </View>
package/src/locale.tsx CHANGED
@@ -24,12 +24,14 @@ export interface LoticsLocale {
24
24
  /** `SortHeader` a11y prefix + asc/desc suffixes. */
25
25
  sortHeader: Required<SortHeaderLabels>;
26
26
  /** `OptionList` (and everything built on it — `Select`, `Combobox`, the
27
- * in-cell editors): the select-all/deselect-all links, the empty state, and
28
- * the `Combobox` recents header. */
29
- optionList: { selectAll: string; deselectAll: string; noResults: string; recent: string };
27
+ * in-cell editors): the select-all/deselect-all links, the empty state, the
28
+ * internal search-field placeholder, and the `Combobox` recents header. */
29
+ optionList: { selectAll: string; deselectAll: string; noResults: string; recent: string; searchPlaceholder: string };
30
30
  /** `FilterChip` (and `ColumnFilter`): the generic clear affordance, used when
31
31
  * a call site doesn't pass a dimension-specific `clearLabel`. */
32
32
  filterChip: { clear: string };
33
+ /** `FormField`: the "Optional" marker shown next to the label when `optional`. */
34
+ formField: { optional: string };
33
35
  /** `Drawer`: the record prev/next + close controls (screen-reader names). */
34
36
  drawer: { previous: string; next: string; close: string };
35
37
  /** `Confidence`: the full level phrase ("High confidence" …). */
@@ -74,8 +76,9 @@ export const en: LoticsLocale = {
74
76
  ascending: ", ascending",
75
77
  descending: ", descending",
76
78
  },
77
- optionList: { selectAll: "Select all", deselectAll: "Deselect all", noResults: "No results", recent: "Recent" },
79
+ optionList: { selectAll: "Select all", deselectAll: "Deselect all", noResults: "No results", recent: "Recent", searchPlaceholder: "Search…" },
78
80
  filterChip: { clear: "Clear" },
81
+ formField: { optional: "Optional" },
79
82
  drawer: { previous: "Previous record", next: "Next record", close: "Close" },
80
83
  confidence: { high: "High confidence", medium: "Medium confidence", low: "Low confidence" },
81
84
  remainderMeter: {
@@ -123,8 +126,9 @@ export const vi: LoticsLocale = {
123
126
  ascending: " (tăng dần)",
124
127
  descending: " (giảm dần)",
125
128
  },
126
- optionList: { selectAll: "Chọn tất cả", deselectAll: "Bỏ chọn tất cả", noResults: "Không có kết quả", recent: "Gần đây" },
129
+ optionList: { selectAll: "Chọn tất cả", deselectAll: "Bỏ chọn tất cả", noResults: "Không có kết quả", recent: "Gần đây", searchPlaceholder: "Tìm…" },
127
130
  filterChip: { clear: "Xóa" },
131
+ formField: { optional: "Tùy chọn" },
128
132
  drawer: { previous: "Bản ghi trước", next: "Bản ghi sau", close: "Đóng" },
129
133
  confidence: { high: "Độ tin cậy cao", medium: "Độ tin cậy trung bình", low: "Độ tin cậy thấp" },
130
134
  remainderMeter: {
@@ -58,7 +58,7 @@ export function OptionList<T extends string, MULTI extends boolean = false, D =
58
58
  icon="search"
59
59
  value={list.query}
60
60
  onChangeText={list.setQuery}
61
- placeholder={search.placeholder ?? "Search…"}
61
+ placeholder={search.placeholder ?? loc.searchPlaceholder}
62
62
  autoFocus={!small}
63
63
  autoCapitalize="none"
64
64
  autoCorrect={false}