@utilitywarehouse/hearth-react-native 0.19.1 → 0.21.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 (149) hide show
  1. package/.storybook/manager.ts +1 -0
  2. package/.storybook/preview.tsx +1 -0
  3. package/.turbo/turbo-build.log +1 -1
  4. package/.turbo/turbo-lint.log +13 -13
  5. package/CHANGELOG.md +299 -4
  6. package/build/components/BodyText/BodyText.js +12 -5
  7. package/build/components/BodyText/BodyText.props.d.ts +5 -19
  8. package/build/components/Box/Box.js +23 -3
  9. package/build/components/Box/Box.props.d.ts +3 -95
  10. package/build/components/Card/Card.props.d.ts +2 -5
  11. package/build/components/Container/Container.props.d.ts +2 -78
  12. package/build/components/DateInput/DateInput.d.ts +1 -1
  13. package/build/components/DateInput/DateInput.js +2 -2
  14. package/build/components/DateInput/DateInput.props.d.ts +15 -1
  15. package/build/components/DateInput/DateInputSegment.d.ts +1 -1
  16. package/build/components/DateInput/DateInputSegment.js +2 -2
  17. package/build/components/DetailText/DetailText.js +14 -13
  18. package/build/components/DetailText/DetailText.props.d.ts +4 -17
  19. package/build/components/Flex/Flex.js +3 -1
  20. package/build/components/Flex/Flex.props.d.ts +2 -2
  21. package/build/components/Heading/Heading.js +34 -13
  22. package/build/components/Heading/Heading.props.d.ts +4 -18
  23. package/build/components/Select/Select.d.ts +1 -1
  24. package/build/components/Select/Select.js +9 -10
  25. package/build/components/Select/Select.props.d.ts +16 -0
  26. package/build/core/themes.d.ts +188 -8
  27. package/build/core/themes.js +18 -2
  28. package/build/hooks/useStyleProps.js +22 -5
  29. package/build/tokens/color.d.ts +4 -0
  30. package/build/tokens/color.js +2 -0
  31. package/build/tokens/components/dark/modal.d.ts +6 -0
  32. package/build/tokens/components/dark/modal.js +6 -0
  33. package/build/tokens/components/dark/navigation.d.ts +1 -0
  34. package/build/tokens/components/dark/navigation.js +1 -0
  35. package/build/tokens/components/light/modal.d.ts +6 -0
  36. package/build/tokens/components/light/modal.js +6 -0
  37. package/build/tokens/components/light/navigation.d.ts +1 -0
  38. package/build/tokens/components/light/navigation.js +1 -0
  39. package/build/tokens/components/light/skeleton.d.ts +1 -1
  40. package/build/tokens/components/light/skeleton.js +1 -1
  41. package/build/tokens/font.d.ts +2 -0
  42. package/build/tokens/font.js +2 -0
  43. package/build/tokens/line-height.d.ts +2 -0
  44. package/build/tokens/line-height.js +2 -0
  45. package/build/tokens/primitive.d.ts +4 -0
  46. package/build/tokens/primitive.js +4 -0
  47. package/build/tokens/semantic-dark.d.ts +1 -0
  48. package/build/tokens/semantic-dark.js +1 -0
  49. package/build/tokens/semantic-light.d.ts +1 -0
  50. package/build/tokens/semantic-light.js +1 -0
  51. package/build/tokens/typography.d.ts +30 -0
  52. package/build/tokens/typography.js +15 -0
  53. package/build/types/index.d.ts +4 -2
  54. package/build/types/index.js +4 -2
  55. package/build/types/semanticColorValues.d.ts +22 -0
  56. package/build/types/semanticColorValues.js +1 -0
  57. package/build/types/utilityProps.d.ts +326 -0
  58. package/build/types/utilityProps.js +1 -0
  59. package/build/types/values.d.ts +4 -3
  60. package/build/utils/coloursAsArray.d.ts +4 -0
  61. package/build/utils/coloursAsArray.js +5 -0
  62. package/build/utils/index.d.ts +1 -1
  63. package/build/utils/index.js +1 -1
  64. package/build/utils/styleUtils.d.ts +26 -2
  65. package/build/utils/styleUtils.js +42 -13
  66. package/build/utils/themeValueHelpers.d.ts +13 -0
  67. package/build/utils/themeValueHelpers.js +29 -0
  68. package/docs/changelog.mdx +74 -2
  69. package/docs/components/AllComponents.web.tsx +23 -24
  70. package/docs/components/UsageWrap.tsx +2 -2
  71. package/docs/introduction.mdx +0 -7
  72. package/package.json +5 -3
  73. package/src/components/BodyText/BodyText.props.ts +5 -19
  74. package/src/components/BodyText/BodyText.stories.tsx +2 -1
  75. package/src/components/BodyText/BodyText.tsx +17 -6
  76. package/src/components/Box/Box.docs.mdx +5 -4
  77. package/src/components/Box/Box.props.ts +3 -231
  78. package/src/components/Box/Box.stories.tsx +2 -2
  79. package/src/components/Box/Box.tsx +38 -9
  80. package/src/components/Button/Button.docs.mdx +46 -1
  81. package/src/components/Card/Card.docs.mdx +1 -1
  82. package/src/components/Card/Card.props.ts +2 -5
  83. package/src/components/Card/Card.stories.tsx +54 -23
  84. package/src/components/Carousel/Carousel.docs.mdx +49 -44
  85. package/src/components/Center/Center.docs.mdx +6 -4
  86. package/src/components/Checkbox/CheckboxGroup.figma.tsx +21 -1
  87. package/src/components/Container/Container.docs.mdx +13 -8
  88. package/src/components/Container/Container.props.ts +9 -80
  89. package/src/components/Container/Container.stories.tsx +81 -65
  90. package/src/components/DateInput/DateInput.docs.mdx +43 -0
  91. package/src/components/DateInput/DateInput.props.ts +15 -1
  92. package/src/components/DateInput/DateInput.stories.tsx +37 -2
  93. package/src/components/DateInput/DateInput.tsx +6 -0
  94. package/src/components/DateInput/DateInputSegment.tsx +2 -0
  95. package/src/components/DetailText/DetailText.props.ts +4 -17
  96. package/src/components/DetailText/DetailText.stories.tsx +2 -3
  97. package/src/components/DetailText/DetailText.tsx +16 -17
  98. package/src/components/Flex/Flex.props.ts +2 -2
  99. package/src/components/Flex/Flex.stories.tsx +1 -1
  100. package/src/components/Flex/Flex.tsx +4 -1
  101. package/src/components/Grid/Grid.docs.mdx +53 -49
  102. package/src/components/Heading/Heading.props.ts +4 -18
  103. package/src/components/Heading/Heading.stories.tsx +2 -1
  104. package/src/components/Heading/Heading.tsx +40 -18
  105. package/src/components/PillGroup/Pill.figma.tsx +4 -17
  106. package/src/components/PillGroup/PillGroup.figma.tsx +8 -9
  107. package/src/components/ProgressStepper/ProgressStep.figma.tsx +4 -15
  108. package/src/components/ProgressStepper/ProgressStepper.figma.tsx +9 -16
  109. package/src/components/Radio/Radio.figma.tsx +35 -22
  110. package/src/components/Radio/RadioGroup.figma.tsx +69 -41
  111. package/src/components/Radio/RadioTile.figma.tsx +34 -0
  112. package/src/components/RadioCard/RadioCard.figma.tsx +24 -0
  113. package/src/components/SectionHeader/SectionHeader.figma.tsx +31 -25
  114. package/src/components/Select/Select.docs.mdx +76 -28
  115. package/src/components/Select/Select.figma.tsx +44 -43
  116. package/src/components/Select/Select.props.ts +16 -0
  117. package/src/components/Select/Select.tsx +42 -35
  118. package/src/components/Select/SelectOption.figma.tsx +3 -21
  119. package/src/components/Spinner/Spinner.figma.tsx +12 -25
  120. package/src/components/Switch/Switch.figma.tsx +2 -23
  121. package/src/components/Tabs/Tab.figma.tsx +21 -0
  122. package/src/components/Tabs/Tabs.figma.tsx +18 -27
  123. package/src/components/Textarea/Textarea.figma.tsx +64 -0
  124. package/src/components/Toast/ToastItem.figma.tsx +1 -8
  125. package/src/components/ToggleButtonCard/ToggleButtonCard.figma.tsx +24 -0
  126. package/src/components/VerificationInput/VerificationInput.figma.tsx +53 -0
  127. package/src/core/themes.ts +19 -2
  128. package/src/hooks/useStyleProps.ts +40 -5
  129. package/src/tokens/color.ts +2 -0
  130. package/src/tokens/components/dark/modal.ts +6 -0
  131. package/src/tokens/components/dark/navigation.ts +1 -0
  132. package/src/tokens/components/light/modal.ts +6 -0
  133. package/src/tokens/components/light/navigation.ts +1 -0
  134. package/src/tokens/components/light/skeleton.ts +1 -1
  135. package/src/tokens/font.ts +2 -0
  136. package/src/tokens/line-height.ts +2 -0
  137. package/src/tokens/primitive.ts +4 -0
  138. package/src/tokens/semantic-dark.ts +1 -0
  139. package/src/tokens/semantic-light.ts +1 -0
  140. package/src/tokens/typography.ts +15 -0
  141. package/src/types/index.ts +4 -2
  142. package/src/types/semanticColorValues.ts +26 -0
  143. package/src/types/utilityProps.ts +410 -0
  144. package/src/types/values.ts +4 -7
  145. package/src/utils/coloursAsArray.ts +6 -0
  146. package/src/utils/index.ts +8 -1
  147. package/src/utils/styleUtils.ts +45 -14
  148. package/src/utils/themeValueHelpers.ts +38 -0
  149. package/src/components/Radio/RadioTileRoot.figma.tsx +0 -31
@@ -1,76 +1,6 @@
1
1
  import type { ViewProps } from 'react-native';
2
- import { SpaceValue, SpacingValues } from '../../types';
3
- interface ContainerProps extends ViewProps {
4
- /**
5
- * The padding of the container.
6
- */
7
- padding?: SpaceValue;
8
- /**
9
- * The horizontal padding of the container.
10
- */
11
- paddingHorizontal?: SpaceValue;
12
- /**
13
- * The vertical padding of the container.
14
- */
15
- paddingVertical?: SpaceValue;
16
- /**
17
- * The top padding of the container.
18
- */
19
- paddingTop?: SpaceValue;
20
- /**
21
- * The bottom padding of the container.
22
- */
23
- paddingBottom?: SpaceValue;
24
- /**
25
- * The left padding of the container.
26
- */
27
- paddingLeft?: SpaceValue;
28
- /**
29
- * The right padding of the container.
30
- */
31
- paddingRight?: SpaceValue;
32
- /**
33
- * The margin of the container.
34
- */
35
- margin?: SpaceValue;
36
- /**
37
- * The horizontal margin of the container.
38
- */
39
- marginHorizontal?: SpaceValue;
40
- /**
41
- * The vertical margin of the container.
42
- */
43
- marginVertical?: SpaceValue;
44
- /**
45
- * The top margin of the container.
46
- */
47
- marginTop?: SpaceValue;
48
- /**
49
- * The bottom margin of the container.
50
- */
51
- marginBottom?: SpaceValue;
52
- /**
53
- * The left margin of the container.
54
- */
55
- marginLeft?: SpaceValue;
56
- /**
57
- * The right margin of the container.
58
- */
59
- marginRight?: SpaceValue;
60
- p?: SpaceValue;
61
- px?: SpaceValue;
62
- py?: SpaceValue;
63
- pt?: SpaceValue;
64
- pb?: SpaceValue;
65
- pl?: SpaceValue;
66
- pr?: SpaceValue;
67
- m?: SpaceValue;
68
- mx?: SpaceValue;
69
- my?: SpaceValue;
70
- mt?: SpaceValue;
71
- mb?: SpaceValue;
72
- ml?: SpaceValue;
73
- mr?: SpaceValue;
2
+ import type { BackgroundColorProps, GapProps, MarginProps, PaddingProps, SpacingValues } from '../../types';
3
+ interface ContainerProps extends ViewProps, MarginProps, PaddingProps, GapProps, BackgroundColorProps {
74
4
  /**
75
5
  * The spacing between child elements (gap).
76
6
  */
@@ -80,11 +10,5 @@ interface ContainerProps extends ViewProps {
80
10
  * @deprecated Use `spacing` instead. The `space` prop will be removed in a future release.
81
11
  */
82
12
  space?: SpacingValues;
83
- /**
84
- * The space between child elements.
85
- */
86
- gap?: SpaceValue;
87
- backgroundColor?: 'backgroundBrand' | 'backgroundPrimary' | 'backgroundSecondary' | 'transparent';
88
- bg?: 'backgroundBrand' | 'backgroundPrimary' | 'backgroundSecondary' | 'transparent';
89
13
  }
90
14
  export default ContainerProps;
@@ -1,6 +1,6 @@
1
1
  import type { DateInputProps } from './DateInput.props';
2
2
  declare const DateInput: {
3
- ({ label, helperText, helperIcon, validationStatus, validText, invalidText, disabled, readonly, required, hideDay, hideMonth, hideYear, dayPlaceholder, monthPlaceholder, yearPlaceholder, dayValue, monthValue, yearValue, onDayChange, onMonthChange, onYearChange, onDayFocus, onMonthFocus, onYearFocus, onDayBlur, onMonthBlur, onYearBlur, inputLabelStyle, inputContainerStyle, inputStyle, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ label, helperText, helperIcon, validationStatus, validText, invalidText, disabled, readonly, required, hideDay, hideMonth, hideYear, dayPlaceholder, monthPlaceholder, yearPlaceholder, dayValue, monthValue, yearValue, dayRef, monthRef, yearRef, onDayChange, onMonthChange, onYearChange, onDayFocus, onMonthFocus, onYearFocus, onDayBlur, onMonthBlur, onYearBlur, inputLabelStyle, inputContainerStyle, inputStyle, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default DateInput;
@@ -3,8 +3,8 @@ import { View } from 'react-native';
3
3
  import { StyleSheet } from 'react-native-unistyles';
4
4
  import { FormField } from '../FormField';
5
5
  import DateInputSegment from './DateInputSegment';
6
- const DateInput = ({ label, helperText, helperIcon, validationStatus = 'initial', validText, invalidText, disabled, readonly, required, hideDay = false, hideMonth = false, hideYear = false, dayPlaceholder = 'DD', monthPlaceholder = 'MM', yearPlaceholder = 'YYYY', dayValue, monthValue, yearValue, onDayChange, onMonthChange, onYearChange, onDayFocus, onMonthFocus, onYearFocus, onDayBlur, onMonthBlur, onYearBlur, inputLabelStyle, inputContainerStyle, inputStyle, ...props }) => {
7
- return (_jsx(FormField, { label: label, helperText: helperText, helperIcon: helperIcon, validationStatus: validationStatus, validText: validText, invalidText: invalidText, disabled: disabled, readonly: readonly, required: required, style: styles.wrap, ...props, children: _jsxs(View, { style: styles.container, children: [!hideDay && (_jsx(DateInputSegment, { label: "Day", placeholder: dayPlaceholder, value: dayValue, onChange: onDayChange, onFocus: onDayFocus, onBlur: onDayBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 2, testID: "date-input-day", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle })), !hideMonth && (_jsx(DateInputSegment, { label: "Month", placeholder: monthPlaceholder, value: monthValue, onChange: onMonthChange, onFocus: onMonthFocus, onBlur: onMonthBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 2, testID: "date-input-month", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle })), !hideYear && (_jsx(DateInputSegment, { label: "Year", placeholder: yearPlaceholder, value: yearValue, onChange: onYearChange, onFocus: onYearFocus, onBlur: onYearBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 4, testID: "date-input-year", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle }))] }) }));
6
+ const DateInput = ({ label, helperText, helperIcon, validationStatus = 'initial', validText, invalidText, disabled, readonly, required, hideDay = false, hideMonth = false, hideYear = false, dayPlaceholder = 'DD', monthPlaceholder = 'MM', yearPlaceholder = 'YYYY', dayValue, monthValue, yearValue, dayRef, monthRef, yearRef, onDayChange, onMonthChange, onYearChange, onDayFocus, onMonthFocus, onYearFocus, onDayBlur, onMonthBlur, onYearBlur, inputLabelStyle, inputContainerStyle, inputStyle, ...props }) => {
7
+ return (_jsx(FormField, { label: label, helperText: helperText, helperIcon: helperIcon, validationStatus: validationStatus, validText: validText, invalidText: invalidText, disabled: disabled, readonly: readonly, required: required, style: styles.wrap, ...props, children: _jsxs(View, { style: styles.container, children: [!hideDay && (_jsx(DateInputSegment, { label: "Day", placeholder: dayPlaceholder, value: dayValue, inputRef: dayRef, onChange: onDayChange, onFocus: onDayFocus, onBlur: onDayBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 2, testID: "date-input-day", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle })), !hideMonth && (_jsx(DateInputSegment, { label: "Month", placeholder: monthPlaceholder, value: monthValue, inputRef: monthRef, onChange: onMonthChange, onFocus: onMonthFocus, onBlur: onMonthBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 2, testID: "date-input-month", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle })), !hideYear && (_jsx(DateInputSegment, { label: "Year", placeholder: yearPlaceholder, value: yearValue, inputRef: yearRef, onChange: onYearChange, onFocus: onYearFocus, onBlur: onYearBlur, disabled: disabled, required: required, readonly: readonly, validationStatus: validationStatus, maxLength: 4, testID: "date-input-year", inputContainerStyle: inputContainerStyle, inputStyle: inputStyle, inputLabelStyle: inputLabelStyle }))] }) }));
8
8
  };
9
9
  DateInput.displayName = 'DateInput';
10
10
  const styles = StyleSheet.create(theme => ({
@@ -1,4 +1,5 @@
1
- import type { TextInputProps, ViewProps } from 'react-native';
1
+ import type { Ref } from 'react';
2
+ import type { TextInput, TextInputProps, ViewProps } from 'react-native';
2
3
  import type { FormFieldBaseProps } from '../FormField/FormField.props';
3
4
  import LabelProps from '../Label/Label.props';
4
5
  export interface DateInputProps extends FormFieldBaseProps {
@@ -41,6 +42,18 @@ export interface DateInputProps extends FormFieldBaseProps {
41
42
  * The controlled value for the year segment. Must be used with an `onYearChange` handler.
42
43
  */
43
44
  yearValue?: string;
45
+ /**
46
+ * Ref for the day segment input.
47
+ */
48
+ dayRef?: Ref<TextInput>;
49
+ /**
50
+ * Ref for the month segment input.
51
+ */
52
+ monthRef?: Ref<TextInput>;
53
+ /**
54
+ * Ref for the year segment input.
55
+ */
56
+ yearRef?: Ref<TextInput>;
44
57
  /**
45
58
  * Callback fired when the day value changes.
46
59
  */
@@ -85,6 +98,7 @@ export interface DateInputSegmentProps {
85
98
  label: string;
86
99
  placeholder?: string;
87
100
  value?: string;
101
+ inputRef?: Ref<TextInput>;
88
102
  onChange?: (text: string) => void;
89
103
  onFocus?: DateInputProps['onDayFocus'];
90
104
  onBlur?: DateInputProps['onDayBlur'];
@@ -1,6 +1,6 @@
1
1
  import type { DateInputSegmentProps } from './DateInput.props';
2
2
  declare const DateInputSegment: {
3
- ({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, inputContainerStyle, inputStyle, inputLabelStyle, }: DateInputSegmentProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ label, placeholder, value, inputRef, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, inputContainerStyle, inputStyle, inputLabelStyle, }: DateInputSegmentProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default DateInputSegment;
@@ -3,9 +3,9 @@ import { View } from 'react-native';
3
3
  import { StyleSheet } from 'react-native-unistyles';
4
4
  import { BodyText } from '../BodyText';
5
5
  import { Input } from '../Input';
6
- const DateInputSegment = ({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, inputContainerStyle, inputStyle, inputLabelStyle, }) => {
6
+ const DateInputSegment = ({ label, placeholder, value, inputRef, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, inputContainerStyle, inputStyle, inputLabelStyle, }) => {
7
7
  styles.useVariants({ disabled });
8
- return (_jsxs(View, { style: [styles.container, inputContainerStyle], children: [_jsx(BodyText, { size: "md", style: [styles.label, inputLabelStyle], children: label }), _jsx(Input, { value: value, onChangeText: onChange, onFocus: onFocus, onBlur: onBlur, placeholder: disabled ? undefined : placeholder, keyboardType: "number-pad", maxLength: maxLength, testID: testID, accessibilityLabel: label, disabled: disabled, validationStatus: validationStatus, readonly: readonly, style: inputStyle })] }));
8
+ return (_jsxs(View, { style: [styles.container, inputContainerStyle], children: [_jsx(BodyText, { size: "md", style: [styles.label, inputLabelStyle], children: label }), _jsx(Input, { ref: inputRef, value: value, onChangeText: onChange, onFocus: onFocus, onBlur: onBlur, placeholder: disabled ? undefined : placeholder, keyboardType: "number-pad", maxLength: maxLength, testID: testID, accessibilityLabel: label, disabled: disabled, validationStatus: validationStatus, readonly: readonly, style: inputStyle })] }));
9
9
  };
10
10
  DateInputSegment.displayName = 'DateInputSegment';
11
11
  const styles = StyleSheet.create(theme => ({
@@ -1,11 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
2
  import { Text } from 'react-native';
4
3
  import { StyleSheet } from 'react-native-unistyles';
5
- import { useTheme } from '../../hooks';
6
- import { getFlattenedColorValue } from '../../utils';
4
+ import { useStyleProps } from '../../hooks';
5
+ import { getFlattenedColorValue, resolveThemeValueWithFallback } from '../../utils';
7
6
  const DetailText = ({ children, color, size = 'md', truncated, underline, strikeThrough, italic, textTransform, textAlign, textAlignVertical, textDecorationColor, textDecorationLine, textDecorationStyle, userSelect, inverted, ...props }) => {
8
- const { color: themeColor, colorMode } = useTheme();
7
+ const { computedStyles: utilityStyles, remainingProps } = useStyleProps(props);
9
8
  styles.useVariants({
10
9
  size,
11
10
  underline,
@@ -13,29 +12,23 @@ const DetailText = ({ children, color, size = 'md', truncated, underline, strike
13
12
  italic,
14
13
  inverted,
15
14
  });
16
- const colorValue = useMemo(() => getFlattenedColorValue(color, themeColor),
17
- // eslint-disable-next-line react-hooks/exhaustive-deps
18
- [color, colorMode]);
19
- const decorationColor = useMemo(() => getFlattenedColorValue(textDecorationColor, themeColor),
20
- // eslint-disable-next-line react-hooks/exhaustive-deps
21
- [textDecorationColor, colorMode]);
22
- return (_jsx(Text, { ...props, ...(truncated
15
+ return (_jsx(Text, { ...remainingProps, ...(truncated
23
16
  ? {
24
17
  numberOfLines: 1,
25
18
  ellipsizeMode: 'tail',
26
19
  }
27
20
  : {}), style: [
28
21
  styles.text,
22
+ utilityStyles,
29
23
  {
30
- ...(colorValue && { color: colorValue }),
31
24
  ...(textTransform && { textTransform }),
32
25
  ...(textAlign && { textAlign }),
33
- ...(decorationColor && { textDecorationColor: decorationColor }),
34
26
  ...(textDecorationLine && { textDecorationLine }),
35
27
  ...(textDecorationStyle && { textDecorationStyle }),
36
28
  ...(userSelect && { userSelect }),
37
29
  ...(textAlignVertical && { textAlignVertical }),
38
30
  },
31
+ styles.getColours(color, textDecorationColor),
39
32
  props.style,
40
33
  ], children: children }));
41
34
  };
@@ -111,5 +104,13 @@ const styles = StyleSheet.create(theme => ({
111
104
  },
112
105
  },
113
106
  },
107
+ getColours: (color, textDecorationColor) => ({
108
+ ...(color
109
+ ? { color: resolveThemeValueWithFallback(color, theme.helpers.semanticColor.text, theme.color) }
110
+ : {}),
111
+ ...(textDecorationColor
112
+ ? { textDecorationColor: getFlattenedColorValue(textDecorationColor, theme.color) }
113
+ : {}),
114
+ }),
114
115
  }));
115
116
  export default DetailText;
@@ -1,19 +1,6 @@
1
- import type { TextProps as RNTextProps, TextStyle } from 'react-native';
2
- import type { ColorValue } from '../../types';
3
- interface TextProps extends RNTextProps {
1
+ import type { CommonTextProps } from '../../types';
2
+ interface DetailTextProps extends CommonTextProps {
3
+ /** Text size variant. */
4
4
  size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
5
- strikeThrough?: boolean;
6
- underline?: boolean;
7
- truncated?: boolean;
8
- italic?: boolean;
9
- color?: ColorValue;
10
- textTransform?: TextStyle['textTransform'];
11
- textAlign?: TextStyle['textAlign'];
12
- textAlignVertical?: TextStyle['textAlignVertical'];
13
- textDecorationLine?: TextStyle['textDecorationLine'];
14
- textDecorationStyle?: TextStyle['textDecorationStyle'];
15
- textDecorationColor?: ColorValue;
16
- userSelect?: TextStyle['userSelect'];
17
- inverted?: boolean;
18
5
  }
19
- export default TextProps;
6
+ export default DetailTextProps;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { View } from 'react-native';
3
3
  import { StyleSheet } from 'react-native-unistyles';
4
+ import { useStyleProps } from '../../hooks';
4
5
  const Flex = ({ style, children, direction = 'column', align = 'flex-start', justify = 'flex-start', wrap = 'nowrap', spacing = 'md', space, ...rest }) => {
5
6
  const propStyle = {
6
7
  flexDirection: direction,
@@ -8,8 +9,9 @@ const Flex = ({ style, children, direction = 'column', align = 'flex-start', jus
8
9
  justifyContent: justify,
9
10
  flexWrap: wrap,
10
11
  };
12
+ const { computedStyles, remainingProps } = useStyleProps(rest);
11
13
  styles.useVariants({ spacing: space ?? spacing });
12
- return (_jsx(View, { style: [propStyle, styles.flex, style], ...rest, children: children }));
14
+ return (_jsx(View, { style: [propStyle, styles.flex, computedStyles, style], ...remainingProps, children: children }));
13
15
  };
14
16
  Flex.displayName = 'Flex';
15
17
  const styles = StyleSheet.create(theme => ({
@@ -1,6 +1,6 @@
1
1
  import type { FlexAlignType, ViewProps, ViewStyle } from 'react-native';
2
- import { SpacingValues } from '../../types';
3
- interface FlexProps extends ViewProps {
2
+ import { FlexLayoutProps, GapProps, SpacingValues } from '../../types';
3
+ interface FlexProps extends ViewProps, FlexLayoutProps, GapProps {
4
4
  direction?: ViewStyle['flexDirection'];
5
5
  align?: FlexAlignType;
6
6
  justify?: ViewStyle['justifyContent'];
@@ -1,40 +1,34 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
2
  import { Text } from 'react-native';
4
3
  import { StyleSheet } from 'react-native-unistyles';
5
- import { useTheme } from '../../hooks';
6
- import { getFlattenedColorValue } from '../../utils';
4
+ import { useStyleProps } from '../../hooks';
5
+ import { getFlattenedColorValue, resolveThemeValueWithFallback } from '../../utils';
7
6
  const Heading = ({ children, color, size = 'lg', truncated, underline, strikeThrough, textTransform, textAlign, textAlignVertical, textDecorationColor, textDecorationLine, textDecorationStyle, userSelect, inverted, ...props }) => {
7
+ // Extract margin utility props from remaining props
8
+ const { computedStyles: utilityStyles, remainingProps } = useStyleProps(props);
8
9
  styles.useVariants({
9
10
  size,
10
11
  underline,
11
12
  strikeThrough,
12
13
  inverted,
13
14
  });
14
- const { color: themeColor, colorMode } = useTheme();
15
- const colorValue = useMemo(() => getFlattenedColorValue(color, themeColor),
16
- // eslint-disable-next-line react-hooks/exhaustive-deps
17
- [color, colorMode]);
18
- const decorationColor = useMemo(() => getFlattenedColorValue(textDecorationColor, themeColor),
19
- // eslint-disable-next-line react-hooks/exhaustive-deps
20
- [textDecorationColor, colorMode]);
21
- return (_jsx(Text, { ...props, ...(truncated
15
+ return (_jsx(Text, { ...remainingProps, ...(truncated
22
16
  ? {
23
17
  numberOfLines: 1,
24
18
  ellipsizeMode: 'tail',
25
19
  }
26
20
  : {}), style: [
27
21
  styles.text,
22
+ utilityStyles,
28
23
  {
29
- ...(colorValue ? { color: colorValue } : {}),
30
24
  ...(textTransform ? { textTransform } : {}),
31
25
  ...(textAlign ? { textAlign } : {}),
32
26
  ...(textAlignVertical ? { textAlignVertical } : {}),
33
- ...(decorationColor && { textDecorationColor: decorationColor }),
34
27
  ...(textDecorationLine && { textDecorationLine }),
35
28
  ...(textDecorationStyle && { textDecorationStyle }),
36
29
  ...(userSelect && { userSelect }),
37
30
  },
31
+ styles.getColours(color, textDecorationColor),
38
32
  props.style,
39
33
  ], children: children }));
40
34
  };
@@ -115,6 +109,23 @@ const styles = StyleSheet.create(theme => ({
115
109
  lg: theme.typography.desktop.heading.xl.lineHeight,
116
110
  },
117
111
  },
112
+ '2xl': {
113
+ fontSize: {
114
+ base: theme.typography.mobile.heading['2xl'].fontSize,
115
+ md: theme.typography.tablet.heading['2xl'].fontSize,
116
+ lg: theme.typography.desktop.heading['2xl'].fontSize,
117
+ },
118
+ fontWeight: {
119
+ base: theme.typography.mobile.heading['2xl'].fontWeight,
120
+ md: theme.typography.tablet.heading['2xl'].fontWeight,
121
+ lg: theme.typography.desktop.heading['2xl'].fontWeight,
122
+ },
123
+ lineHeight: {
124
+ base: theme.typography.mobile.heading['2xl'].lineHeight,
125
+ md: theme.typography.tablet.heading['2xl'].lineHeight,
126
+ lg: theme.typography.desktop.heading['2xl'].lineHeight,
127
+ },
128
+ },
118
129
  },
119
130
  underline: {
120
131
  true: {
@@ -133,5 +144,15 @@ const styles = StyleSheet.create(theme => ({
133
144
  },
134
145
  },
135
146
  },
147
+ getColours: (color, textDecorationColor) => ({
148
+ ...(color
149
+ ? {
150
+ color: resolveThemeValueWithFallback(color, theme.helpers.semanticColor.text, theme.color),
151
+ }
152
+ : {}),
153
+ ...(textDecorationColor
154
+ ? { textDecorationColor: getFlattenedColorValue(textDecorationColor, theme.color) }
155
+ : {}),
156
+ }),
136
157
  }));
137
158
  export default Heading;
@@ -1,20 +1,6 @@
1
- import type { Ref } from 'react';
2
- import type { Text, TextProps, TextStyle } from 'react-native';
3
- import type { ColorValue } from '../../types';
4
- interface HeadingProps extends TextProps {
5
- size?: 'sm' | 'md' | 'lg' | 'xl';
6
- strikeThrough?: boolean;
7
- underline?: boolean;
8
- truncated?: boolean;
9
- color?: ColorValue;
10
- textTransform?: TextStyle['textTransform'];
11
- textAlign?: TextStyle['textAlign'];
12
- textAlignVertical?: TextStyle['textAlignVertical'];
13
- textDecorationLine?: TextStyle['textDecorationLine'];
14
- textDecorationStyle?: TextStyle['textDecorationStyle'];
15
- textDecorationColor?: ColorValue;
16
- userSelect?: TextStyle['userSelect'];
17
- inverted?: boolean;
18
- ref?: Ref<Text>;
1
+ import type { CommonTextProps } from '../../types';
2
+ interface HeadingProps extends CommonTextProps {
3
+ /** Heading size variant. */
4
+ size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
19
5
  }
20
6
  export default HeadingProps;
@@ -1,6 +1,6 @@
1
1
  import SelectProps from './Select.props';
2
2
  declare const Select: {
3
- ({ options, value, onValueChange, label, labelVariant, placeholder, disabled, leadingIcon: LeadingIcon, validationStatus, required, children, bottomSheetProps, menuHeading, readonly, emptyText, listProps, searchable, searchPlaceholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ options, value, onValueChange, label, labelVariant, placeholder, disabled, leadingIcon: LeadingIcon, validationStatus, helperText, helperIcon, invalidText, validText, required, children, bottomSheetProps, menuHeading, readonly, emptyText, listProps, searchable, searchPlaceholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default Select;
@@ -6,13 +6,12 @@ import { StyleSheet } from 'react-native-unistyles';
6
6
  import { BodyText } from '../BodyText';
7
7
  import { BottomSheetFlatList, BottomSheetModal, BottomSheetScrollView, BottomSheetView, } from '../BottomSheet';
8
8
  import { DetailText } from '../DetailText';
9
- import { useFormFieldContext } from '../FormField';
9
+ import { FormField, useFormFieldContext } from '../FormField';
10
10
  import { Icon } from '../Icon';
11
11
  import { Input } from '../Input';
12
- import { Label } from '../Label';
13
12
  import { SelectContext } from './Select.context';
14
13
  import SelectOption from './SelectOption';
15
- const Select = ({ options = [], value, onValueChange, label, labelVariant = 'body', placeholder = 'Select an option', disabled = false, leadingIcon: LeadingIcon, validationStatus = 'initial', required = true, children, bottomSheetProps, menuHeading, readonly = false, emptyText = 'No options available', listProps, searchable = false, searchPlaceholder = 'Search', ...rest }) => {
14
+ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'body', placeholder = 'Select an option', disabled = false, leadingIcon: LeadingIcon, validationStatus = 'initial', helperText, helperIcon, invalidText, validText, required = true, children, bottomSheetProps, menuHeading, readonly = false, emptyText = 'No options available', listProps, searchable = false, searchPlaceholder = 'Search', ...rest }) => {
16
15
  const formFieldContext = useFormFieldContext();
17
16
  const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
18
17
  const isRequired = formFieldContext?.required ?? required;
@@ -67,13 +66,13 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
67
66
  }, []);
68
67
  const renderSelectOption = useCallback(({ item }) => (_jsx(SelectOption, { label: item.label, value: item.value, disabled: item.disabled, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon })), []);
69
68
  const renderEmptyComponent = useCallback(() => (_jsx(BottomSheetView, { style: styles.emptyContainer, children: _jsx(DetailText, { children: emptyText }) })), [emptyText]);
70
- return (_jsxs(View, { ...rest, style: [styles.container, rest.style], children: [!!label && (_jsx(View, { children: _jsxs(Label, { variant: labelVariant, children: [label, !isRequired && _jsx(Label, { variant: labelVariant, children: " (Optional)" })] }) })), _jsxs(Pressable, { onPress: openBottomSheet, disabled: isDisabled || isReadonly, style: ({ pressed }) => [
71
- styles.selectContainer,
72
- styles.pressedContainer(pressed || isOpen),
73
- ], children: [!!LeadingIcon && (_jsx(View, { children: (() => {
74
- const IconAny = Icon;
75
- return _jsx(IconAny, { as: LeadingIcon, style: styles.icon });
76
- })() })), _jsx(View, { style: styles.optionContainer, children: _jsx(BodyText, { numberOfLines: 1, style: styles.placeholderText, children: selectedOption?.label || selectedLabel || placeholder }) }), _jsx(View, { children: _jsx(Icon, { as: ExpandSmallIcon, style: styles.icon }) })] }), _jsx(BottomSheetModal, { ref: bottomSheetModalRef, snapPoints: ['25%', '40%', '80%'], onChange: handleClose, enableDynamicSizing: false, ...bottomSheetProps, children: _jsxs(SelectContext.Provider, { value: {
69
+ return (_jsxs(View, { ...rest, style: [styles.container, rest.style], children: [_jsx(FormField, { label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validationStatus: validationStatusFromContext, required: isRequired, disabled: isDisabled, readonly: isReadonly, invalidText: invalidText, validText: validText, children: _jsxs(Pressable, { onPress: openBottomSheet, disabled: isDisabled || isReadonly, style: ({ pressed }) => [
70
+ styles.selectContainer,
71
+ styles.pressedContainer(pressed || isOpen),
72
+ ], children: [!!LeadingIcon && (_jsx(View, { children: (() => {
73
+ const IconAny = Icon;
74
+ return _jsx(IconAny, { as: LeadingIcon, style: styles.icon });
75
+ })() })), _jsx(View, { style: styles.optionContainer, children: _jsx(BodyText, { numberOfLines: 1, style: styles.placeholderText, children: selectedOption?.label || selectedLabel || placeholder }) }), _jsx(View, { children: _jsx(Icon, { as: ExpandSmallIcon, style: styles.icon }) })] }) }), _jsx(BottomSheetModal, { ref: bottomSheetModalRef, snapPoints: ['25%', '40%', '80%'], onChange: handleClose, enableDynamicSizing: false, ...bottomSheetProps, children: _jsxs(SelectContext.Provider, { value: {
77
76
  selectedValue: value,
78
77
  onValueChange,
79
78
  close: closeBottomSheet,
@@ -50,6 +50,22 @@ interface SelectProps extends ViewProps {
50
50
  * @default 'body'.
51
51
  */
52
52
  labelVariant?: 'heading' | 'body';
53
+ /**
54
+ * Helper text to show below the select
55
+ */
56
+ helperText?: string;
57
+ /**
58
+ * Optional icon to display alongside the helper text
59
+ */
60
+ helperIcon?: React.ComponentType;
61
+ /**
62
+ * Text to display when validationStatus is 'invalid'
63
+ */
64
+ invalidText?: string;
65
+ /**
66
+ * Text to display when validationStatus is 'valid'
67
+ */
68
+ validText?: string;
53
69
  /**
54
70
  * Placeholder text to show when no value is selected
55
71
  */