@swan-io/lake 4.5.1 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Avatar.js +3 -6
- package/src/components/FilterChooser.js +4 -9
- package/src/components/FixedListView.js +11 -4
- package/src/components/InputError.js +6 -7
- package/src/components/LakeCombobox.js +2 -3
- package/src/components/LakeTagInput.d.ts +2 -0
- package/src/components/LakeTagInput.js +12 -3
- package/src/components/LoadingView.js +2 -2
- package/src/components/SwanLogo.js +2 -2
- package/src/constants/design.d.ts +1 -0
- package/src/constants/design.js +1 -0
- package/src/hooks/useUrqlMutation.d.ts +2 -2
- package/src/hooks/useUrqlMutation.js +2 -2
package/package.json
CHANGED
package/src/components/Avatar.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { memo } from "react";
|
|
3
|
-
import { StyleSheet,
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
4
|
import { commonStyles } from "../constants/commonStyles";
|
|
5
5
|
import { colors } from "../constants/design";
|
|
6
|
-
import { typography } from "../constants/typography";
|
|
7
6
|
import { Icon } from "./Icon";
|
|
7
|
+
import { LakeText } from "./LakeText";
|
|
8
8
|
const styles = StyleSheet.create({
|
|
9
9
|
text: {
|
|
10
|
-
...typography.bodyLarge,
|
|
11
|
-
fontWeight: typography.fontWeights.demi,
|
|
12
|
-
textAlign: "center",
|
|
13
10
|
userSelect: "none",
|
|
14
11
|
},
|
|
15
12
|
container: {
|
|
@@ -39,5 +36,5 @@ export const Avatar = memo(({ initials = "", size }) => {
|
|
|
39
36
|
width: size,
|
|
40
37
|
borderRadius: size / 2,
|
|
41
38
|
},
|
|
42
|
-
], children: initials !== "" ? (_jsx(
|
|
39
|
+
], children: initials !== "" ? (_jsx(LakeText, { variant: "semibold", align: "center", style: [styles.text, { color: colors[variant][500], fontSize: size * 0.4 }], children: initials })) : (_jsx(Icon, { name: "person-filled", size: size - 8, color: colors[variant][50] })) }));
|
|
43
40
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from "react";
|
|
3
|
-
import { FlatList, Pressable, StyleSheet,
|
|
3
|
+
import { FlatList, Pressable, StyleSheet, View } from "react-native";
|
|
4
4
|
import { colors } from "../constants/design";
|
|
5
|
-
import { typography } from "../constants/typography";
|
|
6
5
|
import { useDisclosure } from "../hooks/useDisclosure";
|
|
7
6
|
import { Box } from "./Box";
|
|
8
7
|
import { Icon } from "./Icon";
|
|
9
8
|
import { LakeButton } from "./LakeButton";
|
|
9
|
+
import { LakeText } from "./LakeText";
|
|
10
10
|
import { Popover } from "./Popover";
|
|
11
11
|
import { Space } from "./Space";
|
|
12
12
|
const styles = StyleSheet.create({
|
|
@@ -31,22 +31,17 @@ const styles = StyleSheet.create({
|
|
|
31
31
|
backgroundColor: colors.gray[50],
|
|
32
32
|
},
|
|
33
33
|
availableFiltersTitle: {
|
|
34
|
-
...typography.bodyLarge,
|
|
35
|
-
color: colors.current[500],
|
|
36
34
|
paddingHorizontal: 24,
|
|
37
35
|
},
|
|
38
|
-
filterName: {
|
|
39
|
-
...typography.bodySmall,
|
|
40
|
-
},
|
|
41
36
|
});
|
|
42
37
|
export function FilterChooser({ filters, openFilters, label, title, availableFilters, large = true, onAddFilter, }) {
|
|
43
38
|
const inputRef = useRef(null);
|
|
44
39
|
const [visible, { close, toggle }] = useDisclosure(false);
|
|
45
|
-
return (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", justifyContent: "start", alignItems: "center", children: _jsx(LakeButton, { size: "small", mode: "secondary", color: "gray", onPress: toggle, ref: inputRef, icon: large ? "chevron-down-filled" : "filter-filled", iconPosition: "end", ariaLabel: label, children: large ? label : null }) }), _jsx(Popover, { role: "listbox", matchReferenceMinWidth: true, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: styles.list, children: [_jsx(
|
|
40
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", justifyContent: "start", alignItems: "center", children: _jsx(LakeButton, { size: "small", mode: "secondary", color: "gray", onPress: toggle, ref: inputRef, icon: large ? "chevron-down-filled" : "filter-filled", iconPosition: "end", ariaLabel: label, children: large ? label : null }) }), _jsx(Popover, { role: "listbox", matchReferenceMinWidth: true, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: styles.list, children: [_jsx(LakeText, { style: styles.availableFiltersTitle, children: title }), _jsx(Space, { height: 8 }), _jsx(FlatList, { role: "list", data: availableFilters, keyExtractor: (_, index) => `filter-item-${index}`, renderItem: ({ item }) => {
|
|
46
41
|
const isSet = Boolean(filters[item.name]) || openFilters.includes(item.name);
|
|
47
42
|
return (_jsxs(Pressable, { style: ({ hovered }) => [styles.item, hovered && styles.itemHovered], role: "button", disabled: isSet, onPress: () => {
|
|
48
43
|
onAddFilter(item.name);
|
|
49
44
|
close();
|
|
50
|
-
}, children: [_jsx(
|
|
45
|
+
}, children: [_jsx(LakeText, { variant: "smallRegular", style: isSet && styles.selected, children: item.label }), isSet && _jsx(Icon, { color: colors.positive[500], name: "checkmark-filled", size: 14 })] }));
|
|
51
46
|
} })] }) })] }));
|
|
52
47
|
}
|
|
@@ -275,12 +275,19 @@ const styles = StyleSheet.create({
|
|
|
275
275
|
borderBottomRightRadius: radii[4],
|
|
276
276
|
},
|
|
277
277
|
emptyListContainer: {
|
|
278
|
-
|
|
278
|
+
position: "absolute",
|
|
279
|
+
top: 0,
|
|
280
|
+
left: 0,
|
|
281
|
+
right: 0,
|
|
282
|
+
bottom: 0,
|
|
283
|
+
backgroundColor: backgroundColor.default,
|
|
284
|
+
},
|
|
285
|
+
emptyListContentContainer: {
|
|
279
286
|
flexDirection: "column",
|
|
280
287
|
alignItems: "center",
|
|
281
288
|
justifyContent: "center",
|
|
282
289
|
padding: spacings[48],
|
|
283
|
-
|
|
290
|
+
minHeight: "100%",
|
|
284
291
|
},
|
|
285
292
|
emptyList: {
|
|
286
293
|
flexDirection: "column",
|
|
@@ -721,7 +728,7 @@ export const FixedListView = ({ data: originalData, mode = "tile", keyExtractor,
|
|
|
721
728
|
setHasHorizontalScroll(centerColumnsWidth > width);
|
|
722
729
|
}, [centerColumnsWidth]);
|
|
723
730
|
const isLoading = isNotNullish(loading) && loading.isLoading;
|
|
724
|
-
return (_jsxs(View, { style: styles.root, children: [_jsx(View, { ref: startFocusAnchorRef, tabIndex: 0 }),
|
|
731
|
+
return (_jsxs(View, { style: styles.root, children: [_jsx(View, { ref: startFocusAnchorRef, tabIndex: 0 }), _jsxs(ScrollView, { onKeyDown: onKeyDown, onLayout: onLayout, onScroll: onScroll, scrollEventThrottle: 32, style: [styles.container, mode === "tile" && styles.containerTile], contentContainerStyle: [
|
|
725
732
|
styles.contentContainer,
|
|
726
733
|
{
|
|
727
734
|
height: totalHeight +
|
|
@@ -804,7 +811,7 @@ export const FixedListView = ({ data: originalData, mode = "tile", keyExtractor,
|
|
|
804
811
|
], children: [_jsx(View, { style: [
|
|
805
812
|
styles.stickyColumnEndOverflow,
|
|
806
813
|
{ width: horizontalPadding, backgroundColor: headerBackgroundColor },
|
|
807
|
-
] }), _jsx(HeaderSegment, { columns: stickedToEndColumns, extraInfo: extraInfo, viewId: viewId, width: stickedToEndColumnsWidth }), _jsx(View, { style: [styles.topGradient, isScrolled && styles.visibleTopGradient] })] }), _jsx(View, { style: { height: rowsHeight }, children: endRows })] })) : null] })] })), _jsx(View, { ref: endFocusAnchorRef, tabIndex: 0 })] }));
|
|
814
|
+
] }), _jsx(HeaderSegment, { columns: stickedToEndColumns, extraInfo: extraInfo, viewId: viewId, width: stickedToEndColumnsWidth }), _jsx(View, { style: [styles.topGradient, isScrolled && styles.visibleTopGradient] })] }), _jsx(View, { style: { height: rowsHeight }, children: endRows })] })) : null] })] }), data.length === 0 && isNotNullish(renderEmptyList) && !isLoading ? (_jsx(ScrollView, { style: styles.emptyListContainer, contentContainerStyle: styles.emptyListContentContainer, children: renderEmptyList() })) : null, _jsx(View, { ref: endFocusAnchorRef, tabIndex: 0 })] }));
|
|
808
815
|
};
|
|
809
816
|
export const FixedListViewPlaceholder = ({ count, rowHeight, rowVerticalSpacing, groupHeaderHeight, headerHeight, paddingHorizontal = HORIZONTAL_SAFE_AREA, }) => {
|
|
810
817
|
const totalRowHeight = rowHeight + rowVerticalSpacing;
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { StyleSheet
|
|
3
|
-
import { colors } from "../constants/
|
|
4
|
-
import {
|
|
2
|
+
import { StyleSheet } from "react-native";
|
|
3
|
+
import { colors, texts } from "../constants/design";
|
|
4
|
+
import { LakeText } from "./LakeText";
|
|
5
5
|
import { Space } from "./Space";
|
|
6
6
|
const styles = StyleSheet.create({
|
|
7
7
|
base: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
lineHeight: typography.lineHeights.input,
|
|
8
|
+
color: colors.negative[500],
|
|
9
|
+
lineHeight: texts.h1.lineHeight,
|
|
11
10
|
minHeight: 32,
|
|
12
11
|
paddingHorizontal: 3, // borderRadius / 2
|
|
13
12
|
paddingVertical: 4,
|
|
14
13
|
},
|
|
15
14
|
});
|
|
16
|
-
export const InputError = ({ message = "", style }) => message !== "" ? _jsx(
|
|
15
|
+
export const InputError = ({ message = "", style }) => message !== "" ? (_jsx(LakeText, { variant: "smallRegular", style: [styles.base, style], children: message })) : (_jsx(Space, { height: 32 }));
|
|
@@ -2,12 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef, useCallback, useId, useImperativeHandle, useRef, useState, } from "react";
|
|
3
3
|
import { FlatList, Pressable, StyleSheet, Text, View, } from "react-native";
|
|
4
4
|
import { backgroundColor, colors, spacings } from "../constants/design";
|
|
5
|
-
import { typography } from "../constants/typography";
|
|
6
5
|
import { useMergeRefs } from "../hooks/useMergeRefs";
|
|
7
6
|
import { getFocusableElements } from "../utils/a11y";
|
|
8
7
|
import { isNotEmpty } from "../utils/nullish";
|
|
9
8
|
import { Box } from "./Box";
|
|
10
9
|
import { Icon } from "./Icon";
|
|
10
|
+
import { LakeText } from "./LakeText";
|
|
11
11
|
import { LakeTextInput } from "./LakeTextInput";
|
|
12
12
|
import { LoadingView } from "./LoadingView";
|
|
13
13
|
import { Popover } from "./Popover";
|
|
@@ -41,7 +41,6 @@ const styles = StyleSheet.create({
|
|
|
41
41
|
backgroundColor: colors.gray[100],
|
|
42
42
|
},
|
|
43
43
|
itemText: {
|
|
44
|
-
...typography.bodyLarge,
|
|
45
44
|
userSelect: "none",
|
|
46
45
|
},
|
|
47
46
|
loader: {
|
|
@@ -171,7 +170,7 @@ const LakeComboboxWithRef = ({ inputRef, value, items, itemHeight = DEFAULT_ELEM
|
|
|
171
170
|
setIsFetchingAdditionalInfo(false);
|
|
172
171
|
dismiss();
|
|
173
172
|
});
|
|
174
|
-
}, children: isReactText(rendered) ? (_jsx(
|
|
173
|
+
}, children: isReactText(rendered) ? (_jsx(LakeText, { numberOfLines: 1, style: styles.itemText, children: rendered })) : (rendered) }));
|
|
175
174
|
} })), ListFooterComponent, isFetchingAdditionalInfo ? (_jsxs(View, { style: styles.loaderAdditional, children: [_jsx(View, { style: styles.loaderAdditionalUnderlay }), _jsx(LoadingView, {})] })) : null] })),
|
|
176
175
|
}),
|
|
177
176
|
}) }) })] }));
|
|
@@ -7,6 +7,7 @@ export type LakeTagInputProps = Merge<TextInputProps, {
|
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
valid?: boolean;
|
|
9
9
|
hideErrors?: boolean;
|
|
10
|
+
validateOnBlur?: boolean;
|
|
10
11
|
help?: string;
|
|
11
12
|
validator?: (value: string) => boolean;
|
|
12
13
|
values: string[];
|
|
@@ -211,6 +212,7 @@ export declare const LakeTagInput: import("react").ForwardRefExoticComponent<{
|
|
|
211
212
|
disabled?: boolean | undefined;
|
|
212
213
|
valid?: boolean | undefined;
|
|
213
214
|
hideErrors?: boolean | undefined;
|
|
215
|
+
validateOnBlur?: boolean | undefined;
|
|
214
216
|
help?: string | undefined;
|
|
215
217
|
validator?: ((value: string) => boolean) | undefined;
|
|
216
218
|
placeholder?: string | undefined;
|
|
@@ -77,7 +77,7 @@ const styles = StyleSheet.create({
|
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
const SEPARATORS_REGEX = /,| /;
|
|
80
|
-
export const LakeTagInput = forwardRef(({ validator = () => true, onFocus: originalOnFocus, onBlur: originalOnBlur, values, onValuesChanged, readOnly = false, disabled = false, valid = false, hideErrors = false, placeholder, help, error, }, forwardRef) => {
|
|
80
|
+
export const LakeTagInput = forwardRef(({ validator = () => true, onFocus: originalOnFocus, onBlur: originalOnBlur, validateOnBlur = true, values, onValuesChanged, readOnly = false, disabled = false, valid = false, hideErrors = false, placeholder, help, error, }, forwardRef) => {
|
|
81
81
|
const inputRef = useRef(null);
|
|
82
82
|
const containerRef = useRef(null);
|
|
83
83
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -97,6 +97,9 @@ export const LakeTagInput = forwardRef(({ validator = () => true, onFocus: origi
|
|
|
97
97
|
}
|
|
98
98
|
}, [pushNewValues]);
|
|
99
99
|
const onTextInputKeyPress = useCallback(({ nativeEvent }) => {
|
|
100
|
+
if (disabled || readOnly) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
100
103
|
match({ key: nativeEvent.key, input: inputRef.current })
|
|
101
104
|
.with({ key: "Backspace", input: P.instanceOf(HTMLInputElement) }, ({ input }) => {
|
|
102
105
|
if (isNullishOrEmpty(input.value)) {
|
|
@@ -108,7 +111,7 @@ export const LakeTagInput = forwardRef(({ validator = () => true, onFocus: origi
|
|
|
108
111
|
pushNewValues([input.value]);
|
|
109
112
|
}
|
|
110
113
|
});
|
|
111
|
-
}, [onValuesChanged, pushNewValues, values]);
|
|
114
|
+
}, [onValuesChanged, pushNewValues, values, disabled, readOnly]);
|
|
112
115
|
const autoFocus = useCallback(() => {
|
|
113
116
|
inputRef.current?.focus();
|
|
114
117
|
}, []);
|
|
@@ -117,9 +120,15 @@ export const LakeTagInput = forwardRef(({ validator = () => true, onFocus: origi
|
|
|
117
120
|
originalOnFocus?.(event);
|
|
118
121
|
}, [originalOnFocus]);
|
|
119
122
|
const onBlur = useCallback((event) => {
|
|
123
|
+
const input = inputRef.current;
|
|
124
|
+
if (input instanceof HTMLInputElement &&
|
|
125
|
+
isNotNullishOrEmpty(input.value) &&
|
|
126
|
+
validateOnBlur) {
|
|
127
|
+
pushNewValues([input.value]);
|
|
128
|
+
}
|
|
120
129
|
setIsFocused(false);
|
|
121
130
|
originalOnBlur?.(event);
|
|
122
|
-
}, [originalOnBlur]);
|
|
131
|
+
}, [pushNewValues, originalOnBlur, validateOnBlur]);
|
|
123
132
|
const mergedRef = useMergeRefs(inputRef, forwardRef);
|
|
124
133
|
const hasError = isNotNullishOrEmpty(error);
|
|
125
134
|
return (_jsxs(View, { children: [_jsxs(Pressable, { style: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { ActivityIndicator, StyleSheet, View } from "react-native";
|
|
4
|
-
import { colors } from "../constants/
|
|
4
|
+
import { colors } from "../constants/design";
|
|
5
5
|
const styles = StyleSheet.create({
|
|
6
6
|
base: {
|
|
7
7
|
alignItems: "center",
|
|
@@ -21,4 +21,4 @@ const styles = StyleSheet.create({
|
|
|
21
21
|
},
|
|
22
22
|
});
|
|
23
23
|
const isDev = process.env.NODE_ENV === "development";
|
|
24
|
-
export const LoadingView = forwardRef(({ color = colors.gray[
|
|
24
|
+
export const LoadingView = forwardRef(({ color = colors.gray[400], delay = isDev ? 0 : 1000, style }, forwardedRef) => (_jsx(View, { ref: forwardedRef, style: [styles.base, style], children: _jsx(ActivityIndicator, { size: "small", color: color, style: [styles.indicator, delay > 0 && { animationDelay: delay.toString() + "ms" }] }) })));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { StyleSheet } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { invariantColors } from "../constants/design";
|
|
4
4
|
import { Path, Svg } from "./Svg";
|
|
5
5
|
const styles = StyleSheet.create({
|
|
6
6
|
base: {
|
|
@@ -8,4 +8,4 @@ const styles = StyleSheet.create({
|
|
|
8
8
|
width: 45,
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
|
-
export const SwanLogo = ({ color =
|
|
11
|
+
export const SwanLogo = ({ color = invariantColors.gray, style }) => (_jsxs(Svg, { viewBox: "0 0 45 10", style: [styles.base, style], children: [_jsx("title", { children: "Swan" }), _jsx(Path, { d: "M41.01 0c2.2 0 3.66 1.6 3.66 3.82v5.95H42.9V3.9c0-1.28-1-2.19-2.23-2.19a2.33 2.33 0 00-2.37 2.4v5.65h-1.83V.27h1.83v.92A3.4 3.4 0 0141 0zM30.77 9.73H29.2c-2.65 0-4.53-2.27-4.53-4.86A4.81 4.81 0 0129.44 0c2.92 0 4.93 1.74 4.93 4.45v5.32h-1.71V4.45c0-1.72-1.2-2.76-3.22-2.76a3.11 3.11 0 00-3.06 3.18c0 1.72 1.2 3.17 2.82 3.17h1.57v1.7zm-14.37-7l-2.25 7.04h-2.1L9.07.27h1.96l2.11 7.16L15.45.27h1.9l2.3 7.16L21.76.27h1.96l-3 9.5h-2.1zM4.14 10C1.94 10 .54 8.82.36 6.93L.33 6.7h1.79l.02.18c.15.98.84 1.48 2.07 1.48s1.93-.54 1.93-1.38c0-.82-.5-1.1-2.15-1.42l-.43-.09C1.54 5.05.64 4.41.64 2.76.64 1.1 2.1 0 4.18 0 6.06 0 7.5 1.12 7.65 2.83l.02.23H5.9l-.02-.19c-.12-.79-.72-1.25-1.79-1.25-1.03 0-1.68.47-1.68 1.14 0 .68.47.92 1.99 1.2l.6.12c2 .4 2.93 1.1 2.93 2.83C7.93 8.76 6.4 10 4.14 10z", fill: color })] }));
|
package/src/constants/design.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
|
-
import { AnyVariables, CombinedError, TypedDocumentNode } from "urql";
|
|
3
|
-
export declare const useUrqlMutation: <Data, Variables extends AnyVariables>(query: TypedDocumentNode<Data, Variables>) => readonly [AsyncData<Result<Data, Error>>, (input: Variables) => Future<Result<Data, Error | CombinedError>>];
|
|
2
|
+
import { AnyVariables, CombinedError, OperationContext, TypedDocumentNode } from "urql";
|
|
3
|
+
export declare const useUrqlMutation: <Data, Variables extends AnyVariables>(query: TypedDocumentNode<Data, Variables>) => readonly [AsyncData<Result<Data, Error>>, (input: Variables, context?: Partial<OperationContext>) => Future<Result<Data, Error | CombinedError>>];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncData, Future, Result } from "@swan-io/boxed";
|
|
2
2
|
import { useCallback, useMemo } from "react";
|
|
3
|
-
import { CombinedError, useMutation } from "urql";
|
|
3
|
+
import { CombinedError, useMutation, } from "urql";
|
|
4
4
|
import { isNotNullish, isNullish } from "../utils/nullish";
|
|
5
5
|
const toResult = ({ data, error, }) => {
|
|
6
6
|
if (isNotNullish(error)) {
|
|
@@ -23,7 +23,7 @@ export const useUrqlMutation = (query) => {
|
|
|
23
23
|
}
|
|
24
24
|
return AsyncData.Done(toResult({ data, error }));
|
|
25
25
|
}, [fetching, data, error]),
|
|
26
|
-
useCallback((input) => Future.fromPromise(execute(input))
|
|
26
|
+
useCallback((input, context) => Future.fromPromise(execute(input, context))
|
|
27
27
|
.mapError(error => error) // Only used to cast error
|
|
28
28
|
.mapOkToResult(toResult), [execute]),
|
|
29
29
|
];
|