@dloizides/ui-forms 1.4.0 → 1.6.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/dist/index.js CHANGED
@@ -1,15 +1,83 @@
1
1
  'use strict';
2
2
 
3
- var React3 = require('react');
3
+ var React = require('react');
4
4
  var reactNative = require('react-native');
5
5
  var uiFeedback = require('@dloizides/ui-feedback');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
- var React3__default = /*#__PURE__*/_interopDefault(React3);
10
+ var React__default = /*#__PURE__*/_interopDefault(React);
11
11
 
12
- // src/FormField/FormField.tsx
12
+ // src/Field/Field.tsx
13
+ var CONTAINER_MARGIN_BOTTOM = 16;
14
+ var LABEL_FONT_SIZE = 13;
15
+ var LABEL_FONT_WEIGHT = "600";
16
+ var LABEL_MARGIN_BOTTOM = 4;
17
+ var ERROR_FONT_SIZE = 12;
18
+ var ERROR_MARGIN_TOP = 4;
19
+ var styles = reactNative.StyleSheet.create({
20
+ container: {
21
+ marginBottom: CONTAINER_MARGIN_BOTTOM
22
+ },
23
+ label: {
24
+ marginBottom: LABEL_MARGIN_BOTTOM,
25
+ fontSize: LABEL_FONT_SIZE,
26
+ fontWeight: LABEL_FONT_WEIGHT
27
+ },
28
+ errorText: {
29
+ fontSize: ERROR_FONT_SIZE,
30
+ marginTop: ERROR_MARGIN_TOP
31
+ }
32
+ });
33
+ var fieldSeq = 0;
34
+ function useFieldErrorId() {
35
+ const [id] = React__default.default.useState(() => {
36
+ fieldSeq += 1;
37
+ return `field-error-${String(fieldSeq)}`;
38
+ });
39
+ return id;
40
+ }
41
+ function hasFieldError(error) {
42
+ return typeof error === "string" && error !== "";
43
+ }
44
+ var Field = ({
45
+ label,
46
+ children,
47
+ required = false,
48
+ error,
49
+ containerStyle,
50
+ testID
51
+ }) => {
52
+ const { theme } = uiFeedback.useUi();
53
+ const { colors, semantic } = theme;
54
+ const errorColor = semantic.error["500"];
55
+ const hasError = hasFieldError(error);
56
+ const hasLabel = typeof label === "string" && label !== "";
57
+ const errorId = useFieldErrorId();
58
+ const themeStyles = React__default.default.useMemo(
59
+ () => ({
60
+ label: { color: colors.textSecondary },
61
+ requiredMark: { color: errorColor },
62
+ errorText: { color: errorColor }
63
+ }),
64
+ [colors.textSecondary, errorColor]
65
+ );
66
+ const control = typeof children === "function" ? children({ describedById: hasError ? errorId : void 0, hasError }) : children;
67
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.container, containerStyle], testID, children: [
68
+ hasLabel ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles.label, themeStyles.label], children: [
69
+ label,
70
+ " ",
71
+ required ? (
72
+ // The asterisk is decorative — the control's `aria-required` conveys "required" to
73
+ // assistive tech, so a screen reader says "required" instead of "star".
74
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { "aria-hidden": true, accessibilityElementsHidden: true, importantForAccessibility: "no", style: themeStyles.requiredMark, children: "*" })
75
+ ) : null
76
+ ] }) : null,
77
+ control,
78
+ hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: errorId, role: "alert", style: [styles.errorText, themeStyles.errorText], children: error }) : null
79
+ ] });
80
+ };
13
81
  var IS_WEB = reactNative.Platform.OS === "web";
14
82
  var TRANSITION_PROPERTY = "border-color, background-color, box-shadow";
15
83
  var TRANSITION_DURATION = "0.14s";
@@ -42,27 +110,27 @@ function useThemedInput(options = {}) {
42
110
  const { hasError = false, onFocus, onBlur } = options;
43
111
  const { theme } = uiFeedback.useUi();
44
112
  const { colors, palette, semantic } = theme;
45
- const [isFocused, setIsFocused] = React3.useState(false);
46
- const [isHovered, setIsHovered] = React3.useState(false);
47
- const handleFocus = React3.useCallback(
113
+ const [isFocused, setIsFocused] = React.useState(false);
114
+ const [isHovered, setIsHovered] = React.useState(false);
115
+ const handleFocus = React.useCallback(
48
116
  (e) => {
49
117
  setIsFocused(true);
50
118
  onFocus?.(e);
51
119
  },
52
120
  [onFocus]
53
121
  );
54
- const handleBlur = React3.useCallback(
122
+ const handleBlur = React.useCallback(
55
123
  (e) => {
56
124
  setIsFocused(false);
57
125
  onBlur?.(e);
58
126
  },
59
127
  [onBlur]
60
128
  );
61
- const handleHoverIn = React3.useCallback(() => setIsHovered(true), []);
62
- const handleHoverOut = React3.useCallback(() => setIsHovered(false), []);
129
+ const handleHoverIn = React.useCallback(() => setIsHovered(true), []);
130
+ const handleHoverOut = React.useCallback(() => setIsHovered(false), []);
63
131
  const primary = palette.primary["500"];
64
132
  const errorColor = semantic.error["500"];
65
- const style = React3.useMemo(() => {
133
+ const style = React.useMemo(() => {
66
134
  const restBorder = hasError ? errorColor : colors.border;
67
135
  const focusBorder = hasError ? errorColor : primary;
68
136
  const borderColor = isFocused ? focusBorder : isHovered ? withAlpha(colors.text, HOVER_BORDER_ALPHA) : restBorder;
@@ -90,8 +158,8 @@ function useThemedInput(options = {}) {
90
158
  primary,
91
159
  errorColor
92
160
  ]);
93
- const focusBind = React3.useMemo(() => ({ onFocus: handleFocus, onBlur: handleBlur }), [handleFocus, handleBlur]);
94
- const hoverBind = React3.useMemo(
161
+ const focusBind = React.useMemo(() => ({ onFocus: handleFocus, onBlur: handleBlur }), [handleFocus, handleBlur]);
162
+ const hoverBind = React.useMemo(
95
163
  () => IS_WEB ? { onMouseEnter: handleHoverIn, onMouseLeave: handleHoverOut } : {},
96
164
  [handleHoverIn, handleHoverOut]
97
165
  );
@@ -105,7 +173,7 @@ function useThemedInput(options = {}) {
105
173
  };
106
174
  }
107
175
  var IS_WEB2 = reactNative.Platform.OS === "web";
108
- var ThemedTextInput = React3__default.default.forwardRef(function ThemedTextInput2({ hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
176
+ var ThemedTextInput = React__default.default.forwardRef(function ThemedTextInput2({ hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
109
177
  const {
110
178
  style: themedStyle,
111
179
  placeholderTextColor: themedPlaceholder,
@@ -131,85 +199,37 @@ var ThemedTextInput = React3__default.default.forwardRef(function ThemedTextInpu
131
199
  }
132
200
  );
133
201
  });
134
- var CONTAINER_MARGIN_BOTTOM = 16;
135
202
  var INPUT_PADDING_V = 10;
136
203
  var INPUT_PADDING_H = 12;
137
204
  var INPUT_BORDER_RADIUS = 8;
138
- var ERROR_FONT_SIZE = 12;
139
- var LABEL_FONT_SIZE = 13;
140
- var styles = reactNative.StyleSheet.create({
141
- container: {
142
- marginBottom: CONTAINER_MARGIN_BOTTOM
143
- },
144
- label: {
145
- marginBottom: 4,
146
- fontSize: LABEL_FONT_SIZE,
147
- fontWeight: "600"
148
- },
205
+ var INPUT_BORDER_WIDTH = 1;
206
+ var styles2 = reactNative.StyleSheet.create({
149
207
  input: {
150
208
  paddingVertical: INPUT_PADDING_V,
151
209
  paddingHorizontal: INPUT_PADDING_H,
152
210
  borderRadius: INPUT_BORDER_RADIUS,
153
- borderWidth: 1
154
- },
155
- errorText: {
156
- fontSize: ERROR_FONT_SIZE,
157
- marginTop: 4
211
+ borderWidth: INPUT_BORDER_WIDTH
158
212
  }
159
213
  });
160
- var formFieldSeq = 0;
161
- function useErrorId() {
162
- const [id] = React3__default.default.useState(() => {
163
- formFieldSeq += 1;
164
- return `form-field-error-${String(formFieldSeq)}`;
165
- });
166
- return id;
167
- }
168
214
  var FormField = ({
169
215
  label,
170
216
  required = false,
171
217
  error,
172
218
  containerStyle,
173
219
  ...textInputProps
174
- }) => {
175
- const { theme } = uiFeedback.useUi();
176
- const { colors, semantic } = theme;
177
- const errorColor = semantic.error["500"];
178
- const hasError = typeof error === "string" && error !== "";
179
- const errorId = useErrorId();
180
- const themeStyles = React3__default.default.useMemo(
181
- () => ({
182
- label: { color: colors.textSecondary },
183
- requiredMark: { color: errorColor },
184
- errorText: { color: errorColor }
185
- }),
186
- [colors.textSecondary, errorColor]
187
- );
188
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.container, containerStyle], children: [
189
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles.label, themeStyles.label], children: [
190
- label,
191
- " ",
192
- required ? (
193
- // The asterisk is decorative — `requiredField` conveys "required" to assistive tech.
194
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { "aria-hidden": true, accessibilityElementsHidden: true, importantForAccessibility: "no", style: themeStyles.requiredMark, children: "*" })
195
- ) : null
196
- ] }),
197
- /* @__PURE__ */ jsxRuntime.jsx(
198
- ThemedTextInput,
199
- {
200
- accessibilityHint: `Enter ${label}`,
201
- accessibilityLabel: label,
202
- describedById: hasError ? errorId : void 0,
203
- hasError,
204
- requiredField: required,
205
- style: styles.input,
206
- testID: "form-field-input",
207
- ...textInputProps
208
- }
209
- ),
210
- hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: errorId, role: "alert", style: [styles.errorText, themeStyles.errorText], children: error }) : null
211
- ] });
212
- };
220
+ }) => /* @__PURE__ */ jsxRuntime.jsx(Field, { containerStyle, error, label, required, children: ({ describedById, hasError }) => /* @__PURE__ */ jsxRuntime.jsx(
221
+ ThemedTextInput,
222
+ {
223
+ accessibilityHint: `Enter ${label}`,
224
+ accessibilityLabel: label,
225
+ describedById,
226
+ hasError,
227
+ requiredField: required,
228
+ style: styles2.input,
229
+ testID: "form-field-input",
230
+ ...textInputProps
231
+ }
232
+ ) });
213
233
  var TRANSPARENT_COLOR = "transparent";
214
234
  var WHITE_COLOR = "#fff";
215
235
  var SOLID_RADIUS = 20;
@@ -225,6 +245,7 @@ var RGB_R_END = 2;
225
245
  var RGB_G_END = 4;
226
246
  var RGB_B_END = 6;
227
247
  var CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 };
248
+ var CHIP_GUTTER = 8;
228
249
  function withAlpha2(hex, alpha) {
229
250
  const normalized = hex.replace("#", "");
230
251
  const isShort = normalized.length === HEX_SHORT_LENGTH2;
@@ -235,18 +256,18 @@ function withAlpha2(hex, alpha) {
235
256
  const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);
236
257
  return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;
237
258
  }
238
- var styles2 = reactNative.StyleSheet.create({
239
- label: {
240
- marginBottom: 8,
241
- fontWeight: "600"
242
- },
259
+ var styles3 = reactNative.StyleSheet.create({
243
260
  chipContainer: {
244
261
  flexDirection: "row",
245
- flexWrap: "wrap"
262
+ flexWrap: "wrap",
263
+ // Each chip's bottom gutter also hangs off the LAST row, stacking on `Field`'s container
264
+ // margin (8 + 16 = 24) and dropping the block below the `FormField` beside it. Cancelling it
265
+ // is standard gutter compensation: inner rows keep their 8px, the block ends at Field's 16.
266
+ marginBottom: -CHIP_GUTTER
246
267
  },
247
268
  chipWrapper: {
248
- marginRight: 8,
249
- marginBottom: 8
269
+ marginRight: CHIP_GUTTER,
270
+ marginBottom: CHIP_GUTTER
250
271
  },
251
272
  chip: {
252
273
  paddingHorizontal: 12,
@@ -271,7 +292,7 @@ function OutlineChip({
271
292
  colors,
272
293
  onPress
273
294
  }) {
274
- const [hovered, setHovered] = React3__default.default.useState(false);
295
+ const [hovered, setHovered] = React__default.default.useState(false);
275
296
  const active = selected || hovered;
276
297
  const borderColor = active ? colors.primary : colors.border;
277
298
  const backgroundColor = selected ? colors.tint : colors.muted;
@@ -285,12 +306,12 @@ function OutlineChip({
285
306
  accessibilityState: { selected, disabled },
286
307
  disabled,
287
308
  hitSlop: CHIP_HIT_SLOP,
288
- style: styles2.chipWrapper,
309
+ style: styles3.chipWrapper,
289
310
  testID: `chip-selector-chip-${String(option.value)}`,
290
311
  onHoverIn: () => setHovered(true),
291
312
  onHoverOut: () => setHovered(false),
292
313
  onPress,
293
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.chipOutline, { borderColor, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.chipText, styles2.chipTextOutline, { color: textColor }], children: option.label }) })
314
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.chipOutline, { borderColor, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.chipText, styles3.chipTextOutline, { color: textColor }], children: option.label }) })
294
315
  }
295
316
  );
296
317
  }
@@ -312,13 +333,18 @@ function SolidChip({
312
333
  accessibilityState: { selected, disabled },
313
334
  disabled,
314
335
  hitSlop: CHIP_HIT_SLOP,
315
- style: styles2.chipWrapper,
336
+ style: styles3.chipWrapper,
316
337
  testID: `chip-selector-chip-${String(option.value)}`,
317
338
  onPress,
318
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.chip, { borderColor: colors.border, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.chipText, { color: textColor }], children: option.label }) })
339
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.chip, { borderColor: colors.border, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.chipText, { color: textColor }], children: option.label }) })
319
340
  }
320
341
  );
321
342
  }
343
+ var IS_WEB3 = reactNative.Platform.OS === "web";
344
+ function groupA11yProps(describedById, hasError) {
345
+ if (!IS_WEB3) return {};
346
+ return { "aria-invalid": hasError ? true : void 0, "aria-describedby": describedById };
347
+ }
322
348
  var ChipSelector = ({
323
349
  label,
324
350
  options,
@@ -327,12 +353,14 @@ var ChipSelector = ({
327
353
  multiple = false,
328
354
  disabled = false,
329
355
  variant = "solid",
330
- containerStyle
356
+ containerStyle,
357
+ required = false,
358
+ error,
359
+ testID
331
360
  }) => {
332
361
  const { theme } = uiFeedback.useUi();
333
362
  const { colors, palette } = theme;
334
- const hasLabel = typeof label === "string" && label !== "";
335
- const chipColors = React3__default.default.useMemo(() => {
363
+ const chipColors = React__default.default.useMemo(() => {
336
364
  const primary = palette.primary["500"];
337
365
  return {
338
366
  border: colors.border,
@@ -343,43 +371,26 @@ var ChipSelector = ({
343
371
  tint: withAlpha2(primary, OUTLINE_TINT_ALPHA)
344
372
  };
345
373
  }, [colors.border, colors.text, colors.textSecondary, colors.background, palette.primary]);
346
- const labelStyle = React3__default.default.useMemo(() => ({ color: colors.text }), [colors.text]);
347
374
  function isSelected(optionValue) {
348
375
  if (multiple && Array.isArray(value))
349
376
  return value.includes(optionValue);
350
377
  return value === optionValue;
351
378
  }
352
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: containerStyle, children: [
353
- hasLabel ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.label, labelStyle], children: label }) : null,
354
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.chipContainer, children: options.map((option) => {
355
- const selected = isSelected(option.value);
356
- const onPress = () => onChange(option.value);
357
- return variant === "outline" ? /* @__PURE__ */ jsxRuntime.jsx(
358
- OutlineChip,
359
- {
360
- colors: chipColors,
361
- disabled,
362
- option,
363
- selected,
364
- onPress
365
- },
366
- String(option.value)
367
- ) : /* @__PURE__ */ jsxRuntime.jsx(
368
- SolidChip,
369
- {
370
- colors: chipColors,
371
- disabled,
372
- option,
373
- selected,
374
- onPress
375
- },
376
- String(option.value)
377
- );
378
- }) })
379
- ] });
379
+ function renderChip(option) {
380
+ const chipProps = {
381
+ colors: chipColors,
382
+ disabled,
383
+ option,
384
+ selected: isSelected(option.value),
385
+ onPress: () => onChange(option.value)
386
+ };
387
+ const key = String(option.value);
388
+ return variant === "outline" ? /* @__PURE__ */ jsxRuntime.jsx(OutlineChip, { ...chipProps }, key) : /* @__PURE__ */ jsxRuntime.jsx(SolidChip, { ...chipProps }, key);
389
+ }
390
+ return /* @__PURE__ */ jsxRuntime.jsx(Field, { containerStyle, error, label, required, testID, children: ({ describedById, hasError }) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.chipContainer, ...groupA11yProps(describedById, hasError), children: options.map(renderChip) }) });
380
391
  };
381
392
  var DESCRIPTION_FONT_SIZE = 12;
382
- var styles3 = reactNative.StyleSheet.create({
393
+ var styles4 = reactNative.StyleSheet.create({
383
394
  container: {
384
395
  flexDirection: "row",
385
396
  justifyContent: "space-between",
@@ -410,7 +421,7 @@ var FormSwitch = ({
410
421
  const { theme } = uiFeedback.useUi();
411
422
  const { colors } = theme;
412
423
  const hasDescription = typeof description === "string" && description !== "";
413
- const themeStyles = React3__default.default.useMemo(() => {
424
+ const themeStyles = React__default.default.useMemo(() => {
414
425
  const labelStyle = { color: colors.text };
415
426
  const descriptionStyle = { color: colors.textSecondary };
416
427
  return { label: labelStyle, description: descriptionStyle };
@@ -419,13 +430,13 @@ var FormSwitch = ({
419
430
  reactNative.View,
420
431
  {
421
432
  style: [
422
- styles3.container,
433
+ styles4.container,
423
434
  containerStyle
424
435
  ],
425
436
  children: [
426
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.textColumn, children: [
427
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.label, themeStyles.label], children: label }),
428
- hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.description, themeStyles.description], children: description }) : null
437
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.textColumn, children: [
438
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.label, themeStyles.label], children: label }),
439
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.description, themeStyles.description], children: description }) : null
429
440
  ] }),
430
441
  /* @__PURE__ */ jsxRuntime.jsx(
431
442
  reactNative.Switch,
@@ -450,7 +461,7 @@ var BOX_SIZE = 20;
450
461
  var BOX_RADIUS = 5;
451
462
  var CHECK_FONT_SIZE = 14;
452
463
  var DISABLED_OPACITY = 0.5;
453
- var styles4 = reactNative.StyleSheet.create({
464
+ var styles5 = reactNative.StyleSheet.create({
454
465
  container: {
455
466
  flexDirection: "row",
456
467
  alignItems: "flex-start",
@@ -501,7 +512,7 @@ var FormCheckbox = ({
501
512
  const brand = palette.primary["500"];
502
513
  const hintText = typeof hint === "string" && hint !== "" ? hint : description;
503
514
  const hasHint = typeof hintText === "string" && hintText !== "";
504
- const themeStyles = React3__default.default.useMemo(() => {
515
+ const themeStyles = React__default.default.useMemo(() => {
505
516
  const boxOn = { backgroundColor: brand, borderColor: brand };
506
517
  const boxOff = { backgroundColor: "transparent", borderColor: colors.border };
507
518
  const labelStyle = { color: colors.text };
@@ -532,14 +543,14 @@ var FormCheckbox = ({
532
543
  disabled,
533
544
  onPress: toggle,
534
545
  role: "checkbox",
535
- style: [styles4.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null],
546
+ style: [styles5.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null],
536
547
  testID,
537
548
  ...keyboardProps,
538
549
  children: [
539
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.box, value ? themeStyles.boxOn : themeStyles.boxOff], children: value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null }),
540
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.textColumn, children: [
541
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.label, themeStyles.label], children: label }),
542
- hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.hint, themeStyles.hint], children: hintText }) : null
550
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles5.box, value ? themeStyles.boxOn : themeStyles.boxOff], children: value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null }),
551
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.textColumn, children: [
552
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.label, themeStyles.label], children: label }),
553
+ hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.hint, themeStyles.hint], children: hintText }) : null
543
554
  ] })
544
555
  ]
545
556
  }
@@ -547,6 +558,7 @@ var FormCheckbox = ({
547
558
  };
548
559
 
549
560
  exports.ChipSelector = ChipSelector;
561
+ exports.Field = Field;
550
562
  exports.FormCheckbox = FormCheckbox;
551
563
  exports.FormField = FormField;
552
564
  exports.FormSwitch = FormSwitch;