@swan-io/lake 1.4.3 → 1.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.
Files changed (114) hide show
  1. package/package.json +4 -5
  2. package/src/components/AppOpeningAnimation.js +13 -13
  3. package/src/components/AutoWidthImage.d.ts +1 -0
  4. package/src/components/AutoWidthImage.js +3 -4
  5. package/src/components/Avatar.js +3 -2
  6. package/src/components/BorderedButton.d.ts +1 -1
  7. package/src/components/BorderedButton.js +6 -4
  8. package/src/components/BottomPanel.js +2 -2
  9. package/src/components/Box.js +1 -1
  10. package/src/components/Breadcrumbs.js +17 -17
  11. package/src/components/ChoicePicker.js +6 -6
  12. package/src/components/Fill.js +2 -1
  13. package/src/components/FilterChooser.js +2 -2
  14. package/src/components/Filters.js +10 -10
  15. package/src/components/FixedListView.js +15 -12
  16. package/src/components/FixedListViewCells.js +2 -2
  17. package/src/components/Form.d.ts +1 -1
  18. package/src/components/FullViewportLayer.js +13 -10
  19. package/src/components/Heading.d.ts +1 -1
  20. package/src/components/Heading.js +1 -1
  21. package/src/components/Icon.d.ts +4 -4
  22. package/src/components/Icon.js +7 -1
  23. package/src/components/Input.d.ts +6 -6
  24. package/src/components/Input.js +5 -10
  25. package/src/components/InputError.js +1 -1
  26. package/src/components/Label.d.ts +1 -1
  27. package/src/components/Label.js +1 -1
  28. package/src/components/LakeButton.d.ts +3 -3
  29. package/src/components/LakeButton.js +4 -4
  30. package/src/components/LakeCheckbox.js +2 -2
  31. package/src/components/LakeCombobox.d.ts +2 -2
  32. package/src/components/LakeCombobox.js +6 -10
  33. package/src/components/LakeDownloadButton.js +1 -1
  34. package/src/components/LakeHeading.d.ts +3 -2
  35. package/src/components/LakeHeading.js +7 -1
  36. package/src/components/LakeLabel.d.ts +0 -1
  37. package/src/components/LakeLabel.js +4 -4
  38. package/src/components/LakeModal.js +6 -3
  39. package/src/components/LakeRadio.js +3 -3
  40. package/src/components/LakeScrollView.js +2 -1
  41. package/src/components/LakeSearchField.js +3 -3
  42. package/src/components/LakeSelect.d.ts +2 -2
  43. package/src/components/LakeSelect.js +14 -23
  44. package/src/components/LakeSlider.js +1 -1
  45. package/src/components/LakeStepper.js +5 -5
  46. package/src/components/LakeText.d.ts +9 -8
  47. package/src/components/LakeText.js +7 -1
  48. package/src/components/LakeTextInput.d.ts +11 -6
  49. package/src/components/LakeTextInput.js +5 -5
  50. package/src/components/LakeTooltip.js +7 -12
  51. package/src/components/Link.d.ts +53 -50
  52. package/src/components/Link.js +4 -4
  53. package/src/components/ListRightPanel.js +2 -2
  54. package/src/components/Modal.js +15 -5
  55. package/src/components/MultiSelect.d.ts +1 -1
  56. package/src/components/MultiSelect.js +9 -6
  57. package/src/components/PlainListView.js +5 -4
  58. package/src/components/Popover.js +9 -5
  59. package/src/components/Portal.js +2 -2
  60. package/src/components/Pressable.d.ts +112 -101
  61. package/src/components/Pressable.js +16 -6
  62. package/src/components/ProjectEnvTag.js +1 -1
  63. package/src/components/ReadOnlyFieldList.js +2 -2
  64. package/src/components/RightPanel.d.ts +1 -1
  65. package/src/components/RightPanel.js +14 -11
  66. package/src/components/Separator.js +1 -1
  67. package/src/components/SidebarNavigationTracker.js +4 -3
  68. package/src/components/Slider.js +28 -12
  69. package/src/components/SmsOpeningAnimation.js +15 -15
  70. package/src/components/Space.d.ts +1 -1
  71. package/src/components/Stack.d.ts +4 -4
  72. package/src/components/Stack.js +1 -1
  73. package/src/components/Stepper.js +1 -1
  74. package/src/components/Svg.d.ts +6 -7
  75. package/src/components/Switch.js +19 -7
  76. package/src/components/TabView.js +16 -15
  77. package/src/components/Tag.d.ts +2 -2
  78. package/src/components/Tag.js +6 -3
  79. package/src/components/Tile.js +2 -2
  80. package/src/components/ToastStack.js +19 -10
  81. package/src/components/Tooltip.js +3 -6
  82. package/src/components/TransitionGroupView.d.ts +2 -3
  83. package/src/components/TransitionGroupView.js +3 -3
  84. package/src/components/TransitionView.d.ts +2 -3
  85. package/src/components/TransitionView.js +2 -2
  86. package/src/components/WithCurrentColor.d.ts +1 -1
  87. package/src/constants/design.d.ts +4 -12
  88. package/src/constants/design.js +12 -12
  89. package/src/hooks/useAnimatedValue.js +9 -2
  90. package/src/hooks/useForceableState.js +1 -1
  91. package/src/hooks/useHover.js +1 -1
  92. package/src/hooks/useMergeRefs.js +1 -1
  93. package/src/hooks/usePressEvents.js +1 -1
  94. package/src/icons/fluent-icons.json +9 -7
  95. package/src/components/Alert.d.ts +0 -10
  96. package/src/components/Alert.js +0 -36
  97. package/src/components/Button.d.ts +0 -15
  98. package/src/components/Button.js +0 -83
  99. package/src/components/Checkbox.d.ts +0 -12
  100. package/src/components/Checkbox.js +0 -83
  101. package/src/components/Combobox.d.ts +0 -29
  102. package/src/components/Combobox.js +0 -182
  103. package/src/components/MultilineInput.d.ts +0 -15
  104. package/src/components/MultilineInput.js +0 -55
  105. package/src/components/Picker.d.ts +0 -26
  106. package/src/components/Picker.js +0 -116
  107. package/src/components/ProgressBar.d.ts +0 -11
  108. package/src/components/ProgressBar.js +0 -46
  109. package/src/components/SegmentedControl.d.ts +0 -19
  110. package/src/components/SegmentedControl.js +0 -74
  111. package/src/components/Table.d.ts +0 -34
  112. package/src/components/Table.js +0 -79
  113. package/src/hooks/useLazyRef.d.ts +0 -2
  114. package/src/hooks/useLazyRef.js +0 -9
@@ -1,83 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { forwardRef, memo, useId, useRef } from "react";
3
- import { StyleSheet, Text, unstable_createElement as createElement, View, } from "react-native";
4
- import { colors } from "../constants/colors";
5
- import { typography } from "../constants/typography";
6
- import { useNativeProp } from "../hooks/useNativeProp";
7
- import { isNotNullish } from "../utils/nullish";
8
- import { Icon } from "./Icon";
9
- import { Pressable } from "./Pressable";
10
- import { Space } from "./Space";
11
- const styles = StyleSheet.create({
12
- base: {
13
- flexDirection: "row",
14
- flexShrink: 1,
15
- },
16
- box: {
17
- alignItems: "center",
18
- borderColor: colors.gray[10],
19
- borderRadius: 4,
20
- borderWidth: 1,
21
- height: 20,
22
- justifyContent: "center",
23
- padding: 4,
24
- transitionDuration: "150ms",
25
- transitionProperty: "border-color",
26
- width: 20,
27
- },
28
- native: {
29
- ...StyleSheet.absoluteFillObject,
30
- appearance: "none",
31
- borderColor: colors.transparent,
32
- cursor: "inherit",
33
- height: "100%",
34
- margin: 0,
35
- padding: 0,
36
- width: "100%",
37
- },
38
- icon: {
39
- opacity: 0,
40
- animationKeyframes: {
41
- from: { opacity: 0 },
42
- to: { opacity: 1 },
43
- },
44
- animationDuration: "0.25s",
45
- animationFillMode: "forwards",
46
- animationTimingFunction: "ease",
47
- },
48
- hovered: {
49
- borderColor: colors.gray[30],
50
- },
51
- disabled: {
52
- cursor: "not-allowed",
53
- backgroundColor: colors.gray[3],
54
- },
55
- errored: {
56
- borderColor: colors.red[100],
57
- },
58
- label: {
59
- ...typography.bodyLarge,
60
- lineHeight: typography.lineHeights.title,
61
- },
62
- });
63
- export const CheckBox = memo(forwardRef(({ children, disabled = false, error = "", style, value, onValueChange }, forwardedRef) => {
64
- const ref = useRef(null);
65
- const id = useId();
66
- useNativeProp(ref, "for", id);
67
- return (_jsxs(View, { style: [styles.base, style], children: [_jsxs(Pressable, { ref: forwardedRef, accessibilityRole: "checkbox", focusable: false, accessibilityChecked: value, accessibilityDisabled: disabled, style: ({ hovered }) => [
68
- styles.box,
69
- disabled && styles.disabled,
70
- !disabled && error !== "" && styles.errored,
71
- !disabled && error === "" && hovered && styles.hovered,
72
- ], children: [createElement("input", {
73
- checked: value,
74
- disabled,
75
- id,
76
- style: styles.native,
77
- type: "checkbox",
78
- onChange: () => {
79
- !disabled && onValueChange?.(!value);
80
- },
81
- }), value && (_jsx(Icon, { name: "checkmark-filled", color: disabled ? colors.gray[50] : colors.green[100], size: 16, style: styles.icon }))] }), isNotNullish(children) && (_jsxs(_Fragment, { children: [_jsx(Space, { width: 12 }), _jsx(Text, { accessibilityRole: "label", ref: ref, style: styles.label, children: children })] }))] }));
82
- }));
83
- CheckBox.displayName = "CheckBox";
@@ -1,29 +0,0 @@
1
- import { ReactNode } from "react";
2
- import { StyleProp, ViewStyle } from "react-native";
3
- import { IconName } from "./Icon";
4
- type Props<I extends {
5
- value: string;
6
- disabled?: boolean;
7
- }> = {
8
- value: string;
9
- items: I[];
10
- ListFooterComponent?: ReactNode;
11
- onValueChange: (value: string) => void;
12
- onSelectItem: (value: I) => void;
13
- renderItem: (item: I) => ReactNode | null;
14
- size?: "large" | "small";
15
- icon?: IconName;
16
- label?: string;
17
- placeholder?: string;
18
- loading?: boolean;
19
- disabled?: boolean;
20
- error?: string;
21
- style?: StyleProp<ViewStyle>;
22
- };
23
- export declare const Combobox: (<I extends {
24
- value: string;
25
- disabled?: boolean | undefined;
26
- }>(props: Props<I>) => JSX.Element | null) & {
27
- displayName?: string | undefined;
28
- };
29
- export {};
@@ -1,182 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { memo as reactMemo, useCallback, useEffect, useId, useRef, useState, } from "react";
3
- import isEqual from "react-fast-compare";
4
- import { ActivityIndicator, FlatList, Pressable, StyleSheet, Text, View, } from "react-native";
5
- import { match } from "ts-pattern";
6
- import { colors } from "../constants/colors";
7
- import { spacings } from "../constants/design";
8
- import { typography } from "../constants/typography";
9
- import { useDisclosure } from "../hooks/useDisclosure";
10
- import { useResponsive } from "../hooks/useResponsive";
11
- import { isNotNullish, isNullish } from "../utils/nullish";
12
- import { Icon } from "./Icon";
13
- import { Input } from "./Input";
14
- import { LakeTextInput } from "./LakeTextInput";
15
- import { Popover, VIEWPORT_WIDTH_THRESHOLD } from "./Popover";
16
- const ELEMENT_HEIGHT = 72;
17
- const NB_SUGGESTION_DISPLAYED = 3.5;
18
- const styles = StyleSheet.create({
19
- inputWithLeftIcon: {
20
- paddingLeft: 48,
21
- },
22
- icon: {
23
- position: "absolute",
24
- left: 16,
25
- top: 14,
26
- },
27
- iconWithLabel: {
28
- top: 42,
29
- },
30
- list: {
31
- maxHeight: ELEMENT_HEIGHT * NB_SUGGESTION_DISPLAYED,
32
- },
33
- loading: {
34
- height: ELEMENT_HEIGHT * NB_SUGGESTION_DISPLAYED,
35
- left: 16,
36
- alignItems: "center",
37
- justifyContent: "center",
38
- },
39
- item: {
40
- flexShrink: 1,
41
- flexGrow: 1,
42
- height: ELEMENT_HEIGHT,
43
- justifyContent: "center",
44
- paddingHorizontal: 16,
45
- paddingVertical: 0,
46
- transitionProperty: "background-color",
47
- transitionDuration: "200ms",
48
- },
49
- hoveredItem: {
50
- backgroundColor: colors.gray[3],
51
- },
52
- pressedItem: {
53
- backgroundColor: colors.gray[10],
54
- },
55
- itemText: {
56
- ...typography.bodyLarge,
57
- },
58
- mobileInput: {
59
- padding: spacings[16],
60
- },
61
- });
62
- const isReactText = (node) => ["string", "number"].includes(typeof node);
63
- const getItemLayout = (_data, index) => ({
64
- length: ELEMENT_HEIGHT,
65
- offset: ELEMENT_HEIGHT * index,
66
- index,
67
- });
68
- const memo = reactMemo;
69
- export const Combobox = memo(({ value, items, ListFooterComponent, onValueChange, onSelectItem, renderItem, size, icon, label, placeholder, loading = false, disabled = false, error, style, }) => {
70
- const isFirstRender = useRef(true);
71
- const ref = useRef(null);
72
- const mobileInputRef = useRef(null);
73
- const listRef = useRef(null);
74
- const [visible, { open, close }] = useDisclosure(false);
75
- const [focusedIndex, setFocusedIndex] = useState();
76
- const { desktop } = useResponsive(VIEWPORT_WIDTH_THRESHOLD);
77
- const suggestionsId = useId();
78
- const handleFocus = useCallback((event) => {
79
- if (!desktop) {
80
- event.preventDefault();
81
- open();
82
- }
83
- else {
84
- if (items.length > 0) {
85
- open();
86
- }
87
- }
88
- }, [items, open, desktop]);
89
- const handleKeyPress = useCallback((event) => {
90
- match(event.nativeEvent.key)
91
- .with("ArrowDown", () => {
92
- event.preventDefault();
93
- setFocusedIndex(prevIndex => {
94
- const nextIndex = isNotNullish(prevIndex) ? prevIndex + 1 : 0;
95
- const maxIndex = items.length - 1;
96
- return Math.min(nextIndex, maxIndex);
97
- });
98
- })
99
- .with("ArrowUp", () => {
100
- event.preventDefault();
101
- setFocusedIndex(prevIndex => {
102
- const maxIndex = items.length - 1;
103
- const previousIndex = isNotNullish(prevIndex) ? prevIndex - 1 : maxIndex;
104
- return Math.max(previousIndex, 0);
105
- });
106
- })
107
- .with("Escape", () => {
108
- event.preventDefault();
109
- close();
110
- })
111
- .with("Enter", () => {
112
- event.preventDefault();
113
- if (isNullish(focusedIndex)) {
114
- return;
115
- }
116
- const item = items[focusedIndex];
117
- if (item) {
118
- onSelectItem(item);
119
- close();
120
- }
121
- })
122
- .otherwise(() => { });
123
- }, [items, focusedIndex, onSelectItem, close]);
124
- useEffect(() => {
125
- isFirstRender.current = false;
126
- return () => {
127
- isFirstRender.current = true;
128
- };
129
- }, []);
130
- // Auto open/close popover depending on value on items
131
- useEffect(() => {
132
- // avoid to open popover on first render
133
- if (isFirstRender.current) {
134
- return;
135
- }
136
- if (value.length > 0 && items.length > 0) {
137
- open();
138
- }
139
- // we want to run this effect only when items or value changed
140
- }, [items.length, value.length]); // eslint-disable-line react-hooks/exhaustive-deps
141
- // reset focused suggestion when the number of suggestions change
142
- useEffect(() => {
143
- setFocusedIndex(prevFocusedIndex => {
144
- const maxIndex = items.length - 1;
145
- if (isNotNullish(prevFocusedIndex) && prevFocusedIndex > maxIndex) {
146
- return maxIndex;
147
- }
148
- if (items.length === 0) {
149
- return undefined;
150
- }
151
- return prevFocusedIndex;
152
- });
153
- }, [items.length]);
154
- // scroll automatically in suggestion list if user use keyboard navigation
155
- useEffect(() => {
156
- if (isNotNullish(focusedIndex)) {
157
- const position = focusedIndex + 1 - NB_SUGGESTION_DISPLAYED;
158
- // avoid negative value for first indexes
159
- const index = Math.max(0, position);
160
- listRef.current?.scrollToIndex({
161
- animated: true,
162
- index,
163
- });
164
- }
165
- }, [focusedIndex]);
166
- useEffect(() => {
167
- if (visible) {
168
- mobileInputRef.current?.focus();
169
- }
170
- }, [visible]);
171
- return (_jsxs(View, { style: style, children: [_jsx(Input, { ref: ref, accessibilityControls: visible ? suggestionsId : "", accessibilityExpanded: visible, inputStyle: icon || loading ? styles.inputWithLeftIcon : undefined, returnKeyType: "search", role: "combobox", label: label, placeholder: placeholder, value: value, size: size, disabled: disabled, error: error, onValueChange: onValueChange, onFocus: handleFocus, onKeyPress: handleKeyPress }), icon ? (_jsx(Icon, { name: icon, color: colors.gray[50], size: 20, style: [styles.icon, isNotNullish(label) && styles.iconWithLabel] })) : null, _jsxs(Popover, { id: suggestionsId, role: "listbox", matchReferenceWidth: true, onDismiss: close, referenceRef: ref, autoFocus: false, returnFocus: false, visible: visible && (!desktop || loading || items.length > 0), underlay: false, children: [!desktop && (_jsx(View, { style: styles.mobileInput, children: _jsx(LakeTextInput, { ref: mobileInputRef, accessibilityControls: visible ? suggestionsId : "", accessibilityExpanded: visible, returnKeyType: "search", placeholder: placeholder, value: value, disabled: disabled, error: error, onChangeText: onValueChange, onKeyPress: handleKeyPress }) })), _jsxs(View, { style: styles.list, children: [loading ? (_jsx(View, { style: styles.loading, children: _jsx(ActivityIndicator, { color: colors.gray[70], size: 20 }) })) : (_jsx(FlatList, { ref: listRef, keyExtractor: item => item.value, getItemLayout: getItemLayout, accessibilityRole: "list", data: items, extraData: focusedIndex, renderItem: ({ item, index }) => {
172
- const rendered = renderItem(item);
173
- return (_jsx(Pressable, { accessibilityRole: "listitem", disabled: item.disabled, style: ({ hovered, pressed, focused }) => [
174
- styles.item,
175
- (hovered || focused || index === focusedIndex) && styles.hoveredItem,
176
- pressed && styles.pressedItem,
177
- ], onPress: () => {
178
- onSelectItem(item);
179
- close();
180
- }, children: isReactText(rendered) ? (_jsx(Text, { numberOfLines: 1, selectable: false, style: styles.itemText, children: rendered })) : (rendered) }));
181
- } })), ListFooterComponent] })] })] }));
182
- }, isEqual);
@@ -1,15 +0,0 @@
1
- /// <reference types="react" />
2
- import { NativeSyntheticEvent, TextInput, TextInputProps } from "react-native";
3
- type Props = {
4
- disabled?: boolean;
5
- error?: string;
6
- label: string;
7
- onBlur?: (event: NativeSyntheticEvent<React.FocusEvent>) => void;
8
- onSubmitEditing?: TextInputProps["onSubmitEditing"];
9
- onValueChange?: TextInputProps["onChangeText"];
10
- placeholder?: string;
11
- value?: string;
12
- readOnly?: boolean;
13
- };
14
- export declare const MultilineInput: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<TextInput>>>;
15
- export {};
@@ -1,55 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { forwardRef, memo, useId } from "react";
3
- import { StyleSheet, View } from "react-native";
4
- import { colors } from "../constants/colors";
5
- import { typography } from "../constants/typography";
6
- import { isNotNullish } from "../utils/nullish";
7
- import { InputError } from "./InputError";
8
- import { Label } from "./Label";
9
- import { PressableTextInput } from "./Pressable";
10
- import { Space } from "./Space";
11
- const styles = StyleSheet.create({
12
- base: {
13
- ...typography.bodyLarge,
14
- backgroundColor: colors.white,
15
- borderColor: colors.gray[10],
16
- borderRadius: 4,
17
- borderWidth: 1,
18
- flexGrow: 1,
19
- flexShrink: 1,
20
- maxWidth: "100%",
21
- minHeight: 128,
22
- outlineStyle: "none",
23
- padding: 16,
24
- placeholderTextColor: colors.gray[30],
25
- resize: "vertical",
26
- transitionProperty: ["border-color", "box-shadow"],
27
- transitionDuration: "150ms",
28
- },
29
- focused: {
30
- borderColor: colors.gray[30],
31
- shadowColor: colors.gray[100],
32
- shadowOpacity: 0.12,
33
- shadowOffset: { height: 0, width: 0 },
34
- shadowRadius: 2,
35
- },
36
- hovered: {
37
- shadowColor: colors.gray[100],
38
- shadowOpacity: 0.06,
39
- shadowOffset: { height: 4, width: 0 },
40
- shadowRadius: 8,
41
- },
42
- errored: {
43
- borderColor: colors.red[100],
44
- paddingRight: 48,
45
- },
46
- });
47
- export const MultilineInput = memo(forwardRef(({ disabled = false, error, label, onBlur, onSubmitEditing, onValueChange, placeholder, readOnly = false, value = "", }, forwardedRef) => {
48
- const id = `input-${useId()}`;
49
- return (_jsxs(View, { children: [_jsx(Label, { htmlFor: id, children: label }), _jsx(Space, { height: 8 }), _jsx(PressableTextInput, { nativeID: id, ref: forwardedRef, allowFontScaling: false, autoComplete: "off", editable: !readOnly && !disabled, multiline: true, onBlur: onBlur, onChangeText: onValueChange, onSubmitEditing: onSubmitEditing, placeholder: placeholder, value: value, style: ({ hovered, focused }) => [
50
- styles.base,
51
- focused ? styles.focused : hovered && styles.hovered,
52
- isNotNullish(error) && styles.errored,
53
- ] }), _jsx(InputError, { message: error })] }));
54
- }));
55
- MultilineInput.displayName = "MultilineInput";
@@ -1,26 +0,0 @@
1
- import { ReactNode } from "react";
2
- import { StyleProp, ViewStyle } from "react-native";
3
- type Props<V, I extends {
4
- value: V;
5
- }> = {
6
- value: V;
7
- items: I[];
8
- onValueChange: (item: V) => void;
9
- renderItem: (item: I) => ReactNode | null;
10
- renderValue?: (item: I) => ReactNode | null;
11
- itemHeight?: number;
12
- describedBy?: string;
13
- size?: "large" | "small";
14
- label?: string | (() => ReactNode);
15
- info?: ReactNode;
16
- disabled?: boolean;
17
- style?: StyleProp<ViewStyle>;
18
- pickerStyle?: StyleProp<ViewStyle>;
19
- hideErrorMessage?: boolean;
20
- };
21
- export declare const Picker: (<V, I extends {
22
- value: V;
23
- }>(props: Props<V, I>) => JSX.Element | null) & {
24
- displayName?: string | undefined;
25
- };
26
- export {};
@@ -1,116 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { memo as reactMemo, useMemo, useRef } from "react";
3
- import isEqual from "react-fast-compare";
4
- import { FlatList, Pressable, StyleSheet, Text, View } from "react-native";
5
- import { colors } from "../constants/colors";
6
- import { commonStyles } from "../constants/commonStyles";
7
- import { typography } from "../constants/typography";
8
- import { useBoolean } from "../hooks/useBoolean";
9
- import { Fill } from "./Fill";
10
- import { Icon } from "./Icon";
11
- import { InputError } from "./InputError";
12
- import { Label } from "./Label";
13
- import { Popover } from "./Popover";
14
- import { Space } from "./Space";
15
- const ELEMENT_HEIGHT = 48;
16
- const styles = StyleSheet.create({
17
- base: {
18
- alignItems: "center",
19
- backgroundColor: colors.white,
20
- borderColor: colors.gray[10],
21
- borderRadius: 4,
22
- borderWidth: 1,
23
- flexDirection: "row",
24
- flexGrow: 1,
25
- flexShrink: 1,
26
- height: 48,
27
- outlineStyle: "none",
28
- paddingHorizontal: 16,
29
- transitionDuration: "150ms",
30
- transitionProperty: ["border-color", "box-shadow"],
31
- },
32
- small: {
33
- height: 40,
34
- },
35
- focused: {
36
- borderColor: colors.gray[20],
37
- shadowColor: colors.gray[100],
38
- shadowOpacity: 0.12,
39
- shadowOffset: { height: 0, width: 0 },
40
- shadowRadius: 2,
41
- },
42
- hovered: {
43
- shadowColor: colors.gray[100],
44
- shadowOpacity: 0.06,
45
- shadowOffset: { height: 4, width: 0 },
46
- shadowRadius: 8,
47
- },
48
- disabled: {
49
- backgroundColor: colors.gray[3],
50
- borderColor: colors.gray[3],
51
- cursor: "not-allowed",
52
- },
53
- list: {
54
- maxHeight: ELEMENT_HEIGHT * 4.5,
55
- backgroundColor: colors.white,
56
- borderRadius: 4,
57
- shadowColor: colors.gray[100],
58
- shadowOpacity: 0.12,
59
- shadowOffset: { height: 6, width: 0 },
60
- shadowRadius: 24,
61
- },
62
- item: {
63
- alignItems: "center",
64
- flexDirection: "row",
65
- flexGrow: 1,
66
- flexShrink: 1,
67
- paddingHorizontal: 16,
68
- paddingVertical: 0,
69
- transitionProperty: "background-color",
70
- transitionDuration: "200ms",
71
- },
72
- hoveredItem: {
73
- backgroundColor: colors.gray[3],
74
- },
75
- pressedItem: {
76
- backgroundColor: colors.gray[10],
77
- },
78
- itemText: {
79
- ...typography.bodyLarge,
80
- },
81
- });
82
- const isReactText = (node) => ["string", "number"].includes(typeof node);
83
- const memo = reactMemo;
84
- export const Picker = memo(({ value, items, onValueChange, renderItem, renderValue = renderItem, itemHeight = ELEMENT_HEIGHT, describedBy, size = "large", label = "", info = "", disabled = false, style, pickerStyle, hideErrorMessage = false, }) => {
85
- const buttonRef = useRef(null);
86
- const [visible, setVisible] = useBoolean(false);
87
- const selectedItem = items.find(item => item.value === value);
88
- const selectedRendered = selectedItem ? renderValue(selectedItem) : undefined;
89
- const getItemLayout = useMemo(() => (data, index) => ({
90
- length: itemHeight,
91
- offset: itemHeight * index,
92
- index,
93
- }), [itemHeight]);
94
- return (_jsxs(View, { style: style, children: [typeof label === "function"
95
- ? label()
96
- : label !== "" && (_jsxs(_Fragment, { children: [_jsx(Label, { children: label }), _jsx(Space, { height: 8 })] })), _jsxs(Pressable, { ref: buttonRef, accessibilityRole: "button", disabled: disabled, onPress: setVisible.toggle, style: ({ hovered, focused }) => [
97
- styles.base,
98
- size === "small" && styles.small,
99
- pickerStyle,
100
- focused || visible ? styles.focused : hovered && styles.hovered,
101
- disabled && styles.disabled,
102
- ], children: [selectedItem ? (_jsx(View, { style: commonStyles.fill, children: isReactText(selectedRendered) ? (_jsx(Text, { numberOfLines: 1, style: styles.itemText, children: selectedRendered })) : (selectedRendered) })) : (_jsx(Fill, {})), !disabled && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 8 }), _jsx(Icon, { name: visible ? "chevron-up-filled" : "chevron-down-filled", color: colors.gray[30], size: 18 })] }))] }), info !== "" && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 8 }), _jsx(View, { children: info })] })), !hideErrorMessage && _jsx(InputError, {}), _jsx(Popover, { referenceRef: buttonRef, matchReferenceWidth: true, describedBy: describedBy, visible: visible, onDismiss: setVisible.toggle, children: _jsx(FlatList, { getItemLayout: getItemLayout, accessibilityRole: "list", data: items, style: styles.list, keyExtractor: item => `option-${item.value}`, renderItem: ({ item }) => {
103
- const selected = item.value === value;
104
- const rendered = renderItem(item);
105
- return (_jsxs(Pressable, { accessibilityRole: "listitem", accessibilitySelected: selected, style: ({ hovered, pressed }) => [
106
- styles.item,
107
- (hovered || selected) && styles.hoveredItem,
108
- pressed && styles.pressedItem,
109
- { height: itemHeight },
110
- ], onPress: () => {
111
- onValueChange(item.value);
112
- setVisible.toggle();
113
- }, children: [isReactText(rendered) ? (_jsx(Text, { numberOfLines: 1, style: styles.itemText, children: rendered })) : (rendered), selected && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 16 }), _jsx(Icon, { name: "checkmark-filled", color: colors.green[100], size: 20 })] }))] }));
114
- } }) })] }));
115
- }, isEqual);
116
- Picker.displayName = "Picker";
@@ -1,11 +0,0 @@
1
- /// <reference types="react" />
2
- type Props = {
3
- color: string;
4
- label: string;
5
- progressLabel: string;
6
- minValue: number;
7
- maxValue: number;
8
- value: number;
9
- };
10
- export declare const ProgressBar: ({ color, label, progressLabel, minValue, maxValue, value }: Props) => JSX.Element;
11
- export {};
@@ -1,46 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useId } from "react";
3
- import { StyleSheet, Text, View } from "react-native";
4
- import { colors } from "../constants/colors";
5
- import { typography } from "../constants/typography";
6
- import { useComputedColors } from "../hooks/useComputedColors";
7
- import { interpolate } from "../utils/math";
8
- import { Box } from "./Box";
9
- import { Fill } from "./Fill";
10
- import { Space } from "./Space";
11
- const styles = StyleSheet.create({
12
- label: {
13
- ...typography.bodySmall,
14
- lineHeight: typography.lineHeights.title,
15
- color: colors.gray[50],
16
- },
17
- progressLabel: {
18
- ...typography.bodySmall,
19
- fontWeight: typography.fontWeights.demi,
20
- color: colors.gray[100],
21
- whiteSpace: "nowrap",
22
- },
23
- bar: {
24
- height: 8,
25
- borderRadius: 4,
26
- backgroundColor: colors.gray[10],
27
- },
28
- progressBar: {
29
- height: "100%",
30
- borderRadius: 4,
31
- },
32
- });
33
- export const ProgressBar = ({ color, label, progressLabel, minValue, maxValue, value }) => {
34
- const computedColors = useComputedColors(color);
35
- const labelId = `label-${useId()}`;
36
- const percentage = interpolate({
37
- inputRange: [minValue, maxValue],
38
- outputRange: [0, 100],
39
- clamp: true,
40
- })(value);
41
- const fillWidth = `${Math.round(percentage)}%`;
42
- return (_jsxs(View, { accessibilityRole: "progressbar", accessibilityLabelledBy: labelId, accessibilityValueMin: minValue, accessibilityValueMax: maxValue, accessibilityValueNow: value, accessibilityValueText: progressLabel, children: [_jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(Text, { nativeID: labelId, style: styles.label, children: label }), _jsx(Fill, { minWidth: 16 }), _jsx(Text, { style: styles.progressLabel, children: progressLabel })] }), _jsx(Space, { height: 8 }), _jsx(View, { style: styles.bar, children: _jsx(View, { style: [
43
- styles.progressBar,
44
- { backgroundColor: computedColors.progress, width: fillWidth },
45
- ] }) })] }));
46
- };
@@ -1,19 +0,0 @@
1
- import { ReactNode } from "react";
2
- import { StyleProp, ViewStyle } from "react-native";
3
- type Props<V, I extends {
4
- value: V;
5
- }> = {
6
- value: V;
7
- items: I[];
8
- onValueChange: (value: V) => void;
9
- renderItem: (item: I) => ReactNode | null;
10
- horizontal?: boolean;
11
- label: string;
12
- style?: StyleProp<ViewStyle>;
13
- };
14
- export declare const SegmentedControl: (<V, I extends {
15
- value: V;
16
- }>(props: Props<V, I>) => JSX.Element | null) & {
17
- displayName?: string | undefined;
18
- };
19
- export {};
@@ -1,74 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { memo as reactMemo } from "react";
3
- import isEqual from "react-fast-compare";
4
- import { Pressable, StyleSheet, Text, View } from "react-native";
5
- import { colors } from "../constants/colors";
6
- import { typography } from "../constants/typography";
7
- import { Fill } from "./Fill";
8
- import { Icon } from "./Icon";
9
- import { Label } from "./Label";
10
- import { Space } from "./Space";
11
- const styles = StyleSheet.create({
12
- base: {
13
- backgroundColor: colors.white,
14
- borderWidth: 1,
15
- borderColor: colors.gray[10],
16
- borderRadius: 4,
17
- overflow: "hidden",
18
- },
19
- horizontalBase: {
20
- flexDirection: "row",
21
- },
22
- item: {
23
- alignItems: "center",
24
- flexDirection: "row",
25
- flexGrow: 1,
26
- flexShrink: 1,
27
- minHeight: 48,
28
- overflow: "hidden",
29
- paddingHorizontal: 16,
30
- transitionProperty: "background-color",
31
- transitionDuration: "200ms",
32
- },
33
- horizontalItem: {
34
- flexBasis: "0%",
35
- flexDirection: "column",
36
- flexGrow: 1,
37
- flexShrink: 1,
38
- justifyContent: "center",
39
- },
40
- hoveredItem: {
41
- backgroundColor: colors.gray[3],
42
- },
43
- pressedItem: {
44
- backgroundColor: colors.gray[10],
45
- },
46
- rightBorder: {
47
- borderRightColor: colors.gray[10],
48
- borderRightWidth: 1,
49
- },
50
- bottomBorder: {
51
- borderBottomColor: colors.gray[10],
52
- borderBottomWidth: 1,
53
- },
54
- itemText: {
55
- ...typography.bodyLarge,
56
- },
57
- });
58
- const isReactText = (node) => ["string", "number"].includes(typeof node);
59
- const memo = reactMemo;
60
- export const SegmentedControl = memo(({ items, horizontal = false, label, onValueChange, renderItem, style, value }) => {
61
- const lastIndex = items.length - 1;
62
- return (_jsxs(View, { children: [_jsx(Label, { children: label }), _jsx(Space, { height: 8 }), _jsx(View, { accessibilityRole: "radiogroup", style: [styles.base, horizontal && styles.horizontalBase, style], children: items.map((item, index) => {
63
- const selected = item.value === value;
64
- const rendered = renderItem(item);
65
- return (_jsx(Pressable, { accessibilitySelected: selected, accessibilityRole: "radio", onPress: () => onValueChange(item.value), style: ({ hovered, pressed }) => [
66
- styles.item,
67
- horizontal && styles.horizontalItem,
68
- (hovered || selected) && styles.hoveredItem,
69
- pressed && styles.pressedItem,
70
- index !== lastIndex && (horizontal ? styles.rightBorder : styles.bottomBorder),
71
- ], children: _jsxs(_Fragment, { children: [isReactText(rendered) ? (_jsx(Text, { style: styles.itemText, children: rendered })) : (rendered), !horizontal && selected ? (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 16 }), _jsx(Icon, { name: "checkmark-filled", color: colors.green[100], size: 20 })] })) : null] }) }, `option-${item.value}`));
72
- }) })] }));
73
- }, isEqual);
74
- SegmentedControl.displayName = "SegmentedControl";