@utilitywarehouse/hearth-react-native 0.9.0 → 0.11.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +16 -0
- package/build/components/Avatar/Avatar.d.ts +6 -0
- package/build/components/Avatar/Avatar.js +80 -0
- package/build/components/Avatar/Avatar.props.d.ts +28 -0
- package/build/components/Avatar/Avatar.props.js +1 -0
- package/build/components/Avatar/index.d.ts +2 -0
- package/build/components/Avatar/index.js +1 -0
- package/build/components/DateInput/DateInput.d.ts +6 -0
- package/build/components/DateInput/DateInput.js +19 -0
- package/build/components/DateInput/DateInput.props.d.ts +79 -0
- package/build/components/DateInput/DateInput.props.js +1 -0
- package/build/components/DateInput/DateInputSegment.d.ts +20 -0
- package/build/components/DateInput/DateInputSegment.js +31 -0
- package/build/components/DateInput/index.d.ts +2 -0
- package/build/components/DateInput/index.js +1 -0
- package/build/components/PillGroup/Pill.d.ts +16 -0
- package/build/components/PillGroup/Pill.js +94 -0
- package/build/components/PillGroup/Pill.props.d.ts +10 -0
- package/build/components/PillGroup/Pill.props.js +1 -0
- package/build/components/PillGroup/PillGroup.context.d.ts +6 -0
- package/build/components/PillGroup/PillGroup.context.js +5 -0
- package/build/components/PillGroup/PillGroup.d.ts +5 -0
- package/build/components/PillGroup/PillGroup.js +34 -0
- package/build/components/PillGroup/PillGroup.props.d.ts +15 -0
- package/build/components/PillGroup/PillGroup.props.js +1 -0
- package/build/components/PillGroup/index.d.ts +4 -0
- package/build/components/PillGroup/index.js +2 -0
- package/build/components/Select/Select.js +2 -1
- package/build/components/Toast/Toast.context.d.ts +9 -0
- package/build/components/Toast/Toast.context.js +90 -0
- package/build/components/Toast/Toast.props.d.ts +29 -0
- package/build/components/Toast/Toast.props.js +1 -0
- package/build/components/Toast/ToastItem.d.ts +10 -0
- package/build/components/Toast/ToastItem.js +129 -0
- package/build/components/Toast/index.d.ts +3 -0
- package/build/components/Toast/index.js +2 -0
- package/build/components/index.d.ts +4 -0
- package/build/components/index.js +4 -0
- package/build/tokens/components/dark/checkbox.d.ts +3 -0
- package/build/tokens/components/dark/checkbox.js +3 -0
- package/build/tokens/components/dark/input.d.ts +6 -0
- package/build/tokens/components/dark/input.js +6 -0
- package/build/tokens/components/dark/radio.d.ts +3 -0
- package/build/tokens/components/dark/radio.js +3 -0
- package/build/tokens/components/dark/table.d.ts +2 -0
- package/build/tokens/components/dark/table.js +2 -0
- package/build/tokens/components/dark/toast.d.ts +6 -2
- package/build/tokens/components/dark/toast.js +6 -2
- package/build/tokens/components/light/checkbox.d.ts +3 -0
- package/build/tokens/components/light/checkbox.js +3 -0
- package/build/tokens/components/light/input.d.ts +6 -0
- package/build/tokens/components/light/input.js +6 -0
- package/build/tokens/components/light/radio.d.ts +3 -0
- package/build/tokens/components/light/radio.js +3 -0
- package/build/tokens/components/light/table.d.ts +2 -0
- package/build/tokens/components/light/table.js +2 -0
- package/build/tokens/components/light/toast.d.ts +6 -2
- package/build/tokens/components/light/toast.js +6 -2
- package/build/utils/getInitials.d.ts +1 -0
- package/build/utils/getInitials.js +8 -0
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.js +1 -0
- package/docs/assets/toast-ios.MP4 +0 -0
- package/docs/components/AllComponents.web.tsx +43 -0
- package/package.json +3 -3
- package/src/components/Avatar/Avatar.docs.mdx +105 -0
- package/src/components/Avatar/Avatar.props.ts +31 -0
- package/src/components/Avatar/Avatar.stories.tsx +77 -0
- package/src/components/Avatar/Avatar.tsx +136 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/DateInput/DateInput.docs.mdx +163 -0
- package/src/components/DateInput/DateInput.props.ts +80 -0
- package/src/components/DateInput/DateInput.stories.tsx +269 -0
- package/src/components/DateInput/DateInput.tsx +117 -0
- package/src/components/DateInput/DateInputSegment.tsx +83 -0
- package/src/components/DateInput/index.ts +2 -0
- package/src/components/PillGroup/Pill.props.ts +13 -0
- package/src/components/PillGroup/Pill.tsx +120 -0
- package/src/components/PillGroup/PillGroup.context.tsx +12 -0
- package/src/components/PillGroup/PillGroup.docs.mdx +96 -0
- package/src/components/PillGroup/PillGroup.props.ts +22 -0
- package/src/components/PillGroup/PillGroup.stories.tsx +159 -0
- package/src/components/PillGroup/PillGroup.tsx +66 -0
- package/src/components/PillGroup/index.ts +4 -0
- package/src/components/Select/Select.tsx +2 -0
- package/src/components/Toast/Toast.context.tsx +118 -0
- package/src/components/Toast/Toast.docs.mdx +164 -0
- package/src/components/Toast/Toast.props.ts +33 -0
- package/src/components/Toast/Toast.stories.tsx +356 -0
- package/src/components/Toast/ToastItem.tsx +200 -0
- package/src/components/Toast/index.ts +3 -0
- package/src/components/index.ts +4 -0
- package/src/tokens/components/dark/checkbox.ts +3 -0
- package/src/tokens/components/dark/input.ts +6 -0
- package/src/tokens/components/dark/radio.ts +3 -0
- package/src/tokens/components/dark/table.ts +2 -0
- package/src/tokens/components/dark/toast.ts +6 -2
- package/src/tokens/components/light/checkbox.ts +3 -0
- package/src/tokens/components/light/input.ts +6 -0
- package/src/tokens/components/light/radio.ts +3 -0
- package/src/tokens/components/light/table.ts +2 -0
- package/src/tokens/components/light/toast.ts +6 -2
- package/src/utils/getInitials.ts +7 -0
- package/src/utils/index.ts +1 -0
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-lint.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @utilitywarehouse/hearth-react-native@0.
|
|
2
|
+
> @utilitywarehouse/hearth-react-native@0.11.0 lint /home/runner/work/hearth/hearth/packages/react-native
|
|
3
3
|
> TIMING=1 eslint --max-warnings 0
|
|
4
4
|
|
|
5
5
|
Rule | Time (ms) | Relative
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @utilitywarehouse/hearth-react-native
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#674](https://github.com/utilitywarehouse/hearth/pull/674) [`c617257`](https://github.com/utilitywarehouse/hearth/commit/c617257974b11c39d706d6fd46712a284ff5fe10) Thanks [@jordmccord](https://github.com/jordmccord)! - Adds `DateInput` component
|
|
8
|
+
|
|
9
|
+
- [#663](https://github.com/utilitywarehouse/hearth/pull/663) [`8889a07`](https://github.com/utilitywarehouse/hearth/commit/8889a07e347e9289928e679cee495d7656a4e9aa) Thanks [@Utakato](https://github.com/Utakato)! - Add Avatar component
|
|
10
|
+
|
|
11
|
+
## 0.10.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#659](https://github.com/utilitywarehouse/hearth/pull/659) [`99afbed`](https://github.com/utilitywarehouse/hearth/commit/99afbed95df550d5d5a8bb6e04f7640077bf4883) Thanks [@MichalCiesliczka](https://github.com/MichalCiesliczka)! - Adds `Pill` and `PillGroup` components
|
|
16
|
+
|
|
17
|
+
- [#671](https://github.com/utilitywarehouse/hearth/pull/671) [`706448d`](https://github.com/utilitywarehouse/hearth/commit/706448d91f354cb96a71a5f3acc9d17aaa767078) Thanks [@jordmccord](https://github.com/jordmccord)! - Adds `Toast` component
|
|
18
|
+
|
|
3
19
|
## 0.9.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { UserMediumIcon, UserSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Image, View } from 'react-native';
|
|
5
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
6
|
+
import { useTheme } from '../../hooks';
|
|
7
|
+
import { getInitials } from '../../utils';
|
|
8
|
+
import BodyText from '../BodyText/BodyText';
|
|
9
|
+
const Avatar = ({ src, name, size = 'md', delayMs = 0, onLoadingStatusChange, style, ...props }) => {
|
|
10
|
+
const [status, setStatus] = useState('idle');
|
|
11
|
+
const [isDelayed, setIsDelayed] = useState(delayMs > 0);
|
|
12
|
+
const { components } = useTheme();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!src) {
|
|
15
|
+
setStatus('idle');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
setStatus('loading');
|
|
19
|
+
}, [src]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
onLoadingStatusChange?.(status);
|
|
22
|
+
}, [status, onLoadingStatusChange]);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (delayMs <= 0) {
|
|
25
|
+
setIsDelayed(false);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const timerId = setTimeout(() => {
|
|
29
|
+
setIsDelayed(false);
|
|
30
|
+
}, delayMs);
|
|
31
|
+
return () => clearTimeout(timerId);
|
|
32
|
+
}, [delayMs]);
|
|
33
|
+
styles.useVariants({ size });
|
|
34
|
+
const initials = getInitials(name);
|
|
35
|
+
const handleLoad = () => setStatus('loaded');
|
|
36
|
+
const handleError = () => setStatus('error');
|
|
37
|
+
const showImage = src && status === 'loaded';
|
|
38
|
+
const showFallback = !showImage && !isDelayed;
|
|
39
|
+
const textSize = size === 'sm' ? 'md' : 'lg';
|
|
40
|
+
const FallbackIcon = size === 'sm' ? UserSmallIcon : UserMediumIcon;
|
|
41
|
+
return (_jsxs(View, { ...props, style: [styles.container, style], accessibilityRole: showImage && name ? 'image' : undefined, accessibilityLabel: showImage ? name : undefined, children: [src && (_jsx(Image, { source: src, style: styles.image, onLoad: handleLoad, onError: handleError, accessibilityElementsHidden: true })), showFallback && (_jsx(View, { style: styles.fallback, children: name ? (_jsx(BodyText, { size: textSize, weight: "semibold", textTransform: "uppercase", style: styles.text, children: initials })) : (_jsx(FallbackIcon, {})) }))] }));
|
|
42
|
+
};
|
|
43
|
+
Avatar.displayName = 'Avatar';
|
|
44
|
+
const styles = StyleSheet.create(theme => ({
|
|
45
|
+
container: {
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
alignItems: 'center',
|
|
48
|
+
overflow: 'hidden',
|
|
49
|
+
backgroundColor: theme.color.surface.pig.subtle,
|
|
50
|
+
variants: {
|
|
51
|
+
size: {
|
|
52
|
+
sm: {
|
|
53
|
+
width: theme.components.avatar.sm.width,
|
|
54
|
+
height: theme.components.avatar.sm.height,
|
|
55
|
+
borderRadius: theme.components.avatar.sm.borderRadius,
|
|
56
|
+
},
|
|
57
|
+
md: {
|
|
58
|
+
width: theme.components.avatar.md.width,
|
|
59
|
+
height: theme.components.avatar.md.height,
|
|
60
|
+
borderRadius: theme.components.avatar.md.borderRadius,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
image: {
|
|
66
|
+
width: '100%',
|
|
67
|
+
height: '100%',
|
|
68
|
+
position: 'absolute',
|
|
69
|
+
},
|
|
70
|
+
fallback: {
|
|
71
|
+
width: '100%',
|
|
72
|
+
height: '100%',
|
|
73
|
+
justifyContent: 'center',
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
},
|
|
76
|
+
text: {
|
|
77
|
+
color: theme.color.text.primary,
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
80
|
+
export default Avatar;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ImageSourcePropType, ViewProps } from 'react-native';
|
|
2
|
+
export type AvatarLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
|
|
3
|
+
interface AvatarProps extends ViewProps {
|
|
4
|
+
/**
|
|
5
|
+
* The image source to display.
|
|
6
|
+
*/
|
|
7
|
+
src?: ImageSourcePropType;
|
|
8
|
+
/**
|
|
9
|
+
* The name associated with the avatar, used for creating initials and accessibility label.
|
|
10
|
+
*/
|
|
11
|
+
name?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Sets the avatar size.
|
|
14
|
+
* @default md
|
|
15
|
+
*/
|
|
16
|
+
size?: 'sm' | 'md';
|
|
17
|
+
/**
|
|
18
|
+
* Delay in milliseconds before the image is rendered.
|
|
19
|
+
* Useful to prevent flickering when the image loads very quickly.
|
|
20
|
+
* @default 0
|
|
21
|
+
*/
|
|
22
|
+
delayMs?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Callback fired when the loading status of the image changes.
|
|
25
|
+
*/
|
|
26
|
+
onLoadingStatusChange?: (status: AvatarLoadingStatus) => void;
|
|
27
|
+
}
|
|
28
|
+
export default AvatarProps;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Avatar } from './Avatar';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DateInputProps } from './DateInput.props';
|
|
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, ...props }: DateInputProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
displayName: string;
|
|
5
|
+
};
|
|
6
|
+
export default DateInput;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
4
|
+
import { FormField } from '../FormField';
|
|
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, ...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" })), !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" })), !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" }))] }) }));
|
|
8
|
+
};
|
|
9
|
+
DateInput.displayName = 'DateInput';
|
|
10
|
+
const styles = StyleSheet.create(theme => ({
|
|
11
|
+
wrap: {
|
|
12
|
+
gap: theme.components.input.gap,
|
|
13
|
+
},
|
|
14
|
+
container: {
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
gap: theme.components.input.date.gap,
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
export default DateInput;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { TextInputProps } from 'react-native';
|
|
2
|
+
import type { FormFieldBaseProps } from '../FormField/FormField.props';
|
|
3
|
+
export interface DateInputProps extends FormFieldBaseProps {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the day segment is hidden.
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
8
|
+
hideDay?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Whether the month segment is hidden.
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
hideMonth?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Whether the year segment is hidden.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
hideYear?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Placeholder text for the day segment.
|
|
21
|
+
*/
|
|
22
|
+
dayPlaceholder?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Placeholder text for the month segment.
|
|
25
|
+
*/
|
|
26
|
+
monthPlaceholder?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Placeholder text for the year segment.
|
|
29
|
+
*/
|
|
30
|
+
yearPlaceholder?: string;
|
|
31
|
+
/**
|
|
32
|
+
* The controlled value for the day segment. Must be used with an `onDayChange` handler.
|
|
33
|
+
*/
|
|
34
|
+
dayValue?: string;
|
|
35
|
+
/**
|
|
36
|
+
* The controlled value for the month segment. Must be used with an `onMonthChange` handler.
|
|
37
|
+
*/
|
|
38
|
+
monthValue?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The controlled value for the year segment. Must be used with an `onYearChange` handler.
|
|
41
|
+
*/
|
|
42
|
+
yearValue?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Callback fired when the day value changes.
|
|
45
|
+
*/
|
|
46
|
+
onDayChange?: (text: string) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Callback fired when the month value changes.
|
|
49
|
+
*/
|
|
50
|
+
onMonthChange?: (text: string) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Callback fired when the year value changes.
|
|
53
|
+
*/
|
|
54
|
+
onYearChange?: (text: string) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Callback fired when the day segment receives focus.
|
|
57
|
+
*/
|
|
58
|
+
onDayFocus?: TextInputProps['onFocus'];
|
|
59
|
+
/**
|
|
60
|
+
* Callback fired when the month segment receives focus.
|
|
61
|
+
*/
|
|
62
|
+
onMonthFocus?: TextInputProps['onFocus'];
|
|
63
|
+
/**
|
|
64
|
+
* Callback fired when the year segment receives focus.
|
|
65
|
+
*/
|
|
66
|
+
onYearFocus?: TextInputProps['onFocus'];
|
|
67
|
+
/**
|
|
68
|
+
* Callback fired when the day segment loses focus.
|
|
69
|
+
*/
|
|
70
|
+
onDayBlur?: TextInputProps['onBlur'];
|
|
71
|
+
/**
|
|
72
|
+
* Callback fired when the month segment loses focus.
|
|
73
|
+
*/
|
|
74
|
+
onMonthBlur?: TextInputProps['onBlur'];
|
|
75
|
+
/**
|
|
76
|
+
* Callback fired when the year segment loses focus.
|
|
77
|
+
*/
|
|
78
|
+
onYearBlur?: TextInputProps['onBlur'];
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DateInputProps } from './DateInput.props';
|
|
2
|
+
interface DateInputSegmentProps {
|
|
3
|
+
label: string;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
onChange?: (text: string) => void;
|
|
7
|
+
onFocus?: DateInputProps['onDayFocus'];
|
|
8
|
+
onBlur?: DateInputProps['onDayBlur'];
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
validationStatus?: DateInputProps['validationStatus'];
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
testID?: string;
|
|
15
|
+
}
|
|
16
|
+
declare const DateInputSegment: {
|
|
17
|
+
({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, }: DateInputSegmentProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
displayName: string;
|
|
19
|
+
};
|
|
20
|
+
export default DateInputSegment;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
4
|
+
import { BodyText } from '../BodyText';
|
|
5
|
+
import { Input } from '../Input';
|
|
6
|
+
const DateInputSegment = ({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, }) => {
|
|
7
|
+
styles.useVariants({ disabled });
|
|
8
|
+
return (_jsxs(View, { style: styles.container, children: [_jsx(BodyText, { size: "md", style: styles.label, 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: styles.input })] }));
|
|
9
|
+
};
|
|
10
|
+
DateInputSegment.displayName = 'DateInputSegment';
|
|
11
|
+
const styles = StyleSheet.create(theme => ({
|
|
12
|
+
container: {
|
|
13
|
+
flex: 1,
|
|
14
|
+
gap: theme.components.input.gap,
|
|
15
|
+
maxWidth: 96,
|
|
16
|
+
},
|
|
17
|
+
label: {
|
|
18
|
+
variants: {
|
|
19
|
+
disabled: {
|
|
20
|
+
true: {
|
|
21
|
+
opacity: theme.opacity.disabled,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
input: {
|
|
27
|
+
flex: 1,
|
|
28
|
+
maxWidth: 96,
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
export default DateInputSegment;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DateInput } from './DateInput';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PillProps } from './Pill.props';
|
|
2
|
+
export declare const Pill: import("react").ForwardRefExoticComponent<PillProps & {
|
|
3
|
+
states?: {
|
|
4
|
+
active?: boolean;
|
|
5
|
+
};
|
|
6
|
+
} & Omit<import("react-native").PressableProps, "children"> & {
|
|
7
|
+
tabIndex?: 0 | -1 | undefined;
|
|
8
|
+
} & {
|
|
9
|
+
children?: import("react").ReactNode | (({ hovered, pressed, focused, focusVisible, disabled, }: {
|
|
10
|
+
hovered?: boolean | undefined;
|
|
11
|
+
pressed?: boolean | undefined;
|
|
12
|
+
focused?: boolean | undefined;
|
|
13
|
+
focusVisible?: boolean | undefined;
|
|
14
|
+
disabled?: boolean | undefined;
|
|
15
|
+
}) => import("react").ReactNode);
|
|
16
|
+
} & import("react").RefAttributes<unknown>>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createPressable } from '@gluestack-ui/pressable';
|
|
3
|
+
import { Pressable } from 'react-native';
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { BodyText } from '../BodyText';
|
|
7
|
+
import { usePillGroupContext } from './PillGroup.context';
|
|
8
|
+
const PillRoot = ({ value, label, icon, states = {}, ...props }) => {
|
|
9
|
+
const { active } = states;
|
|
10
|
+
const context = usePillGroupContext();
|
|
11
|
+
const isSelected = context?.value.includes(value) ?? false;
|
|
12
|
+
styles.useVariants({ selected: isSelected, active });
|
|
13
|
+
const handlePress = () => {
|
|
14
|
+
context?.onChange(value);
|
|
15
|
+
};
|
|
16
|
+
return (_jsxs(Pressable, { ...props, style: styles.pill, accessibilityRole: "button", accessibilityState: { selected: isSelected }, onPress: handlePress, children: [icon && _jsx(Icon, { as: icon, size: "sm", style: styles.icon }), _jsx(BodyText, { weight: "semibold", style: styles.text, children: label })] }));
|
|
17
|
+
};
|
|
18
|
+
export const Pill = createPressable({ Root: PillRoot });
|
|
19
|
+
Pill.displayName = 'Pill';
|
|
20
|
+
const styles = StyleSheet.create(theme => ({
|
|
21
|
+
pill: {
|
|
22
|
+
flexDirection: 'row',
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
justifyContent: 'center',
|
|
25
|
+
height: theme.components.pill.height,
|
|
26
|
+
minWidth: theme.components.pill.minWidth,
|
|
27
|
+
gap: theme.components.pill.gap,
|
|
28
|
+
paddingHorizontal: theme.components.pill.paddingHorizontal,
|
|
29
|
+
paddingVertical: theme.components.pill.paddingVertical,
|
|
30
|
+
borderRadius: theme.components.pill.borderRadius,
|
|
31
|
+
borderWidth: theme.components.pill.borderWidth,
|
|
32
|
+
borderColor: theme.color.interactive.neutral.border.subtle,
|
|
33
|
+
backgroundColor: 'transparent',
|
|
34
|
+
_web: {
|
|
35
|
+
_hover: {
|
|
36
|
+
backgroundColor: theme.color.interactive.neutral.surface.subtle.hover,
|
|
37
|
+
},
|
|
38
|
+
'_focus-visible': theme.helpers.focusVisible,
|
|
39
|
+
},
|
|
40
|
+
variants: {
|
|
41
|
+
active: {
|
|
42
|
+
true: {
|
|
43
|
+
backgroundColor: theme.color.interactive.neutral.surface.subtle.active,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
selected: {
|
|
47
|
+
true: {
|
|
48
|
+
backgroundColor: theme.color.interactive.brand.surface.strong.default,
|
|
49
|
+
borderColor: theme.color.interactive.brand.surface.strong.default,
|
|
50
|
+
_web: {
|
|
51
|
+
_hover: {
|
|
52
|
+
backgroundColor: theme.color.interactive.brand.surface.strong.hover,
|
|
53
|
+
borderColor: theme.color.interactive.brand.surface.strong.hover,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
compoundVariants: [
|
|
60
|
+
{
|
|
61
|
+
selected: true,
|
|
62
|
+
active: true,
|
|
63
|
+
styles: {
|
|
64
|
+
backgroundColor: theme.color.interactive.brand.surface.strong.active,
|
|
65
|
+
borderColor: theme.color.interactive.brand.surface.strong.active,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
text: {
|
|
71
|
+
variants: {
|
|
72
|
+
selected: {
|
|
73
|
+
true: {
|
|
74
|
+
color: theme.color.text.inverted,
|
|
75
|
+
},
|
|
76
|
+
false: {
|
|
77
|
+
color: theme.color.text.primary,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
icon: {
|
|
83
|
+
variants: {
|
|
84
|
+
selected: {
|
|
85
|
+
true: {
|
|
86
|
+
color: theme.color.icon.inverted,
|
|
87
|
+
},
|
|
88
|
+
false: {
|
|
89
|
+
color: theme.color.icon.primary,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { PressableProps } from 'react-native';
|
|
3
|
+
export interface PillProps extends Omit<PressableProps, 'children'> {
|
|
4
|
+
/** Value returned when selected */
|
|
5
|
+
value: string;
|
|
6
|
+
/** Text label shown inside the pill */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Left icon */
|
|
9
|
+
icon?: React.ComponentType<any>;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface PillGroupContextValue {
|
|
2
|
+
value: string[];
|
|
3
|
+
onChange: (value: string) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare const PillGroupContext: import("react").Context<PillGroupContextValue | null>;
|
|
6
|
+
export declare const usePillGroupContext: () => PillGroupContextValue | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { ScrollView } from 'react-native';
|
|
4
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
5
|
+
import { Box } from '../Box';
|
|
6
|
+
import { PillGroupContext } from './PillGroup.context';
|
|
7
|
+
export const PillGroup = ({ children, value, multiple = false, wrap = true, onChange, style, ...props }) => {
|
|
8
|
+
const normalizedValue = Array.isArray(value) ? value : [value];
|
|
9
|
+
const contextValue = useMemo(() => ({
|
|
10
|
+
value: normalizedValue,
|
|
11
|
+
onChange: (pillValue) => {
|
|
12
|
+
if (multiple) {
|
|
13
|
+
const newValue = normalizedValue.includes(pillValue)
|
|
14
|
+
? normalizedValue.filter(v => v !== pillValue)
|
|
15
|
+
: [...normalizedValue, pillValue];
|
|
16
|
+
onChange?.(newValue);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
onChange?.(pillValue);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
}), [normalizedValue, multiple, onChange]);
|
|
23
|
+
return (_jsx(PillGroupContext.Provider, { value: contextValue, children: wrap ? (_jsx(Box, { style: [styles.group, styles.wrap, style], ...props, children: children })) : (_jsx(ScrollView, { horizontal: true, contentContainerStyle: [styles.group, style], showsHorizontalScrollIndicator: false, ...props, children: children })) }));
|
|
24
|
+
};
|
|
25
|
+
PillGroup.displayName = 'PillGroup';
|
|
26
|
+
const styles = StyleSheet.create(theme => ({
|
|
27
|
+
group: {
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
gap: theme.components.pill.group.gap,
|
|
30
|
+
},
|
|
31
|
+
wrap: {
|
|
32
|
+
flexWrap: 'wrap',
|
|
33
|
+
},
|
|
34
|
+
}));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ScrollViewProps, ViewStyle } from 'react-native';
|
|
3
|
+
export interface PillGroupProps extends Omit<ScrollViewProps, 'horizontal' | 'contentContainerStyle' | 'showsHorizontalScrollIndicator'> {
|
|
4
|
+
/** Controlled selected value(s) */
|
|
5
|
+
value: string | string[];
|
|
6
|
+
/** Multi-select mode. Default = false */
|
|
7
|
+
multiple?: boolean;
|
|
8
|
+
/** Allow pills to wrap lines. Default = true */
|
|
9
|
+
wrap?: boolean;
|
|
10
|
+
/** Handle selection changes */
|
|
11
|
+
onChange?: (value: string | string[]) => void;
|
|
12
|
+
/** Children must be <Pill> elements */
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
style?: ViewStyle | ViewStyle[];
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -77,7 +77,7 @@ const Select = ({ options = [], value, onValueChange, label, placeholder = 'Sele
|
|
|
77
77
|
selectedValue: value,
|
|
78
78
|
onValueChange,
|
|
79
79
|
close: closeBottomSheet,
|
|
80
|
-
}, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, onChangeText: setSearch, type: "search" }) })), children ? (_jsx(BottomSheetScrollView, { children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, ...listProps }))] }) })] }));
|
|
80
|
+
}, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search" }) })), children ? (_jsx(BottomSheetScrollView, { children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, ...listProps }))] }) })] }));
|
|
81
81
|
};
|
|
82
82
|
const styles = StyleSheet.create(theme => ({
|
|
83
83
|
container: {
|
|
@@ -161,6 +161,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
161
161
|
emptyContainer: {
|
|
162
162
|
alignItems: 'center',
|
|
163
163
|
justifyContent: 'center',
|
|
164
|
+
marginTop: theme.space.md,
|
|
164
165
|
},
|
|
165
166
|
}));
|
|
166
167
|
Select.displayName = 'Select';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ToastContextValue } from './Toast.props';
|
|
3
|
+
declare const ToastContext: React.Context<ToastContextValue | undefined>;
|
|
4
|
+
export declare const useToastContext: () => ToastContextValue;
|
|
5
|
+
export declare const ToastProvider: React.FC<{
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const useToast: () => ToastContextValue;
|
|
9
|
+
export default ToastContext;
|