@swan-io/lake 2.6.1 → 2.7.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/lake",
3
- "version": "2.6.1",
3
+ "version": "2.7.1",
4
4
  "engines": {
5
5
  "node": ">=18.0.0",
6
6
  "yarn": "^1.22.0"
@@ -27,8 +27,8 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@popperjs/core": "^2.11.8",
30
- "@react-three/drei": "^9.77.10",
31
- "@react-three/fiber": "^8.13.4",
30
+ "@react-three/drei": "^9.79.3",
31
+ "@react-three/fiber": "^8.13.5",
32
32
  "@swan-io/boxed": "^1.0.2",
33
33
  "@swan-io/chicane": "^1.4.1",
34
34
  "dayjs": "^1.11.9",
@@ -37,23 +37,23 @@
37
37
  "react": "^18.2.0",
38
38
  "react-atomic-state": "^1.2.7",
39
39
  "react-dom": "^18.2.0",
40
- "react-native-web": "^0.19.6",
40
+ "react-native-web": "^0.19.7",
41
41
  "react-popper": "^2.3.0",
42
- "react-ux-form": "^1.3.0",
42
+ "react-ux-form": "^1.4.0",
43
43
  "rifm": "^0.12.1",
44
44
  "three": "^0.154.0",
45
45
  "ts-dedent": "^2.2.0",
46
- "ts-pattern": "^5.0.1",
46
+ "ts-pattern": "^5.0.4",
47
47
  "urql": "^4.0.4",
48
48
  "uuid": "^9.0.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@types/react": "^18.2.14",
52
- "@types/react-dom": "^18.2.6",
51
+ "@types/react": "^18.2.15",
52
+ "@types/react-dom": "^18.2.7",
53
53
  "@types/react-native": "^0.72.2",
54
- "@types/three": "^0.152.1",
54
+ "@types/three": "^0.154.0",
55
55
  "@types/uuid": "^9.0.2",
56
56
  "jsdom": "^22.1.0",
57
- "type-fest": "^3.12.0"
57
+ "type-fest": "^4.0.0"
58
58
  }
59
59
  }
@@ -157,7 +157,7 @@ const LakeComboboxWithRef = ({ inputRef, value, items, itemHeight = DEFAULT_ELEM
157
157
  ], onPress: () => {
158
158
  window.clearTimeout(blurTimeoutId.current);
159
159
  setIsFetchingAdditionalInfo(true);
160
- Promise.resolve(onSelectItem(item)).finally(() => {
160
+ void Promise.resolve(onSelectItem(item)).finally(() => {
161
161
  setIsFetchingAdditionalInfo(false);
162
162
  close();
163
163
  });
@@ -1,9 +1,11 @@
1
+ import { ReactNode } from "react";
1
2
  type Props = {
2
3
  initialValue: string;
3
4
  placeholder: string;
4
5
  onChangeText: (text: string) => void;
5
6
  debounceDuration?: number;
6
7
  maxWidth?: number;
8
+ renderEnd?: () => ReactNode;
7
9
  };
8
- export declare const LakeSearchField: ({ initialValue, placeholder, onChangeText, debounceDuration, maxWidth, }: Props) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const LakeSearchField: ({ initialValue, placeholder, onChangeText, debounceDuration, maxWidth, renderEnd, }: Props) => import("react/jsx-runtime").JSX.Element;
9
11
  export {};
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useRef, useState } from "react";
3
3
  import { Pressable, StyleSheet, View } from "react-native";
4
- import { animations, backgroundColor, colors, radii } from "../constants/design";
4
+ import { animations, backgroundColor, colors, radii, spacings } from "../constants/design";
5
5
  import { useBoolean } from "../hooks/useBoolean";
6
6
  import { useDebounce } from "../hooks/useDebounce";
7
7
  import { LakeButton } from "./LakeButton";
@@ -10,44 +10,24 @@ import { ResponsiveContainer } from "./ResponsiveContainer";
10
10
  import { Line, Svg } from "./Svg";
11
11
  import { TransitionView } from "./TransitionView";
12
12
  const styles = StyleSheet.create({
13
- root: {
14
- flexGrow: 1,
15
- flexShrink: 1,
13
+ input: {
14
+ transition: "300ms ease-in-out border-color",
16
15
  // ResponsiveContainer uses a 200 breaking,
17
16
  // we give the opportunity to the component to grow 2px more
18
17
  // to trigger the change
19
18
  maxWidth: 202,
20
19
  minWidth: 38,
21
20
  },
22
- container: {
23
- width: "100%",
24
- flexGrow: 1,
25
- flexShrink: 0,
26
- alignSelf: "flex-end",
27
- },
28
- input: {
29
- paddingRight: 50,
30
- minWidth: 200,
31
- // fixes a responsiveness bug where the default input width is too large
32
- width: 1,
33
- flexGrow: 1,
34
- transition: "300ms ease-in-out border-color",
35
- },
36
21
  focus: {
37
22
  outlineStyle: "none",
38
23
  borderColor: colors.current.primary,
39
24
  },
40
25
  clearButton: {
41
- position: "absolute",
42
- right: 0,
43
- top: "50%",
44
- transform: "translateY(-50%)",
45
- padding: 16,
26
+ marginRight: spacings[8],
46
27
  },
47
28
  clear: {
48
29
  width: 8,
49
30
  height: 8,
50
- display: "flex",
51
31
  },
52
32
  smallButtonContainer: {
53
33
  flexDirection: "row",
@@ -68,30 +48,30 @@ const styles = StyleSheet.create({
68
48
  borderRadius: radii[6],
69
49
  },
70
50
  });
71
- const CollapsibleSeachField = ({ inputRef, placeholder, initialValue, onChange, setFocused, hasFocus, clear, currentValue, }) => {
72
- return (_jsxs(View, { children: [_jsx(LakeButton, { mode: "secondary", size: "small", ariaLabel: placeholder, icon: "search-filled", onPress: () => {
51
+ const CollapsibleSeachField = ({ inputRef, placeholder, initialValue, onChange, setFocused, hasFocus, clear, currentValue, renderEnd, }) => {
52
+ return (_jsxs(View, { style: styles.smallButtonContainer, children: [_jsx(LakeButton, { mode: "secondary", size: "small", ariaLabel: placeholder, icon: "search-filled", onPress: () => {
73
53
  setFocused.on();
74
- }, pill: currentValue !== "" }), _jsx(TransitionView, { style: styles.openSearchFieldContainer, ...animations.fadeAndSlideInFromRight, children: hasFocus ? (_jsx(View, { style: styles.openSearchField, children: _jsx(ExpandedSearchField, { inputRef: inputRef, placeholder: placeholder, initialValue: initialValue, onChange: onChange, setFocused: setFocused, hasFocus: hasFocus, clear: clear, currentValue: currentValue }) })) : null })] }));
54
+ }, pill: currentValue !== "" }), _jsx(TransitionView, { style: styles.openSearchFieldContainer, ...animations.fadeAndSlideInFromRight, children: hasFocus ? (_jsx(View, { style: styles.openSearchField, children: _jsx(ExpandedSearchField, { inputRef: inputRef, placeholder: placeholder, initialValue: initialValue, onChange: onChange, setFocused: setFocused, hasFocus: hasFocus, clear: clear, currentValue: currentValue, renderEnd: renderEnd }) })) : null })] }));
75
55
  };
76
- const ExpandedSearchField = ({ inputRef, placeholder, initialValue, onChange, setFocused, hasFocus, clear, }) => {
56
+ const ExpandedSearchField = ({ inputRef, placeholder, initialValue, onChange, setFocused, hasFocus, clear, renderEnd, }) => {
77
57
  const timeoutRef = useRef(null);
78
- return (_jsxs(View, { style: styles.container, children: [_jsx(LakeTextInput, { ref: inputRef, autoFocus: hasFocus, icon: "search-filled", placeholder: placeholder, defaultValue: initialValue, inputMode: "search", onChangeText: onChange, hideErrors: true, onFocus: () => {
79
- if (timeoutRef.current != null) {
80
- clearTimeout(timeoutRef.current);
81
- }
82
- setFocused.on();
83
- }, onBlur: () => {
84
- timeoutRef.current = window.setTimeout(() => {
85
- setFocused.off();
86
- }, 300);
87
- }, style: [styles.input, hasFocus ? styles.focus : null] }), _jsx(Pressable, { onPress: () => {
88
- if (timeoutRef.current != null) {
89
- clearTimeout(timeoutRef.current);
90
- }
91
- clear();
92
- }, style: styles.clearButton, children: _jsx(Svg, { viewBox: "0 0 16 16", style: styles.clear, children: _jsxs(_Fragment, { children: [_jsx(Line, { x1: "0", x2: "16", y1: "0", y2: "16", strokeLinecap: "round", stroke: colors.gray[500], strokeWidth: 2 }), _jsx(Line, { x1: "0", x2: "16", y1: "16", y2: "0", strokeLinecap: "round", stroke: colors.gray[500], strokeWidth: 2 })] }) }) })] }));
58
+ return (_jsx(LakeTextInput, { ref: inputRef, autoFocus: hasFocus, icon: "search-filled", placeholder: placeholder, defaultValue: initialValue, inputMode: "search", onChangeText: onChange, hideErrors: true, renderEnd: () => (_jsxs(_Fragment, { children: [_jsx(Pressable, { onPress: () => {
59
+ if (timeoutRef.current != null) {
60
+ clearTimeout(timeoutRef.current);
61
+ }
62
+ clear();
63
+ }, style: styles.clearButton, children: _jsx(Svg, { viewBox: "0 0 16 16", style: styles.clear, children: _jsxs(_Fragment, { children: [_jsx(Line, { x1: "0", x2: "16", y1: "0", y2: "16", strokeLinecap: "round", stroke: colors.gray[500], strokeWidth: 2 }), _jsx(Line, { x1: "0", x2: "16", y1: "16", y2: "0", strokeLinecap: "round", stroke: colors.gray[500], strokeWidth: 2 })] }) }) }), renderEnd?.()] })), onFocus: () => {
64
+ if (timeoutRef.current != null) {
65
+ clearTimeout(timeoutRef.current);
66
+ }
67
+ setFocused.on();
68
+ }, onBlur: () => {
69
+ timeoutRef.current = window.setTimeout(() => {
70
+ setFocused.off();
71
+ }, 300);
72
+ }, style: [styles.input, hasFocus ? styles.focus : null] }));
93
73
  };
94
- export const LakeSearchField = ({ initialValue, placeholder, onChangeText, debounceDuration = 500, maxWidth, }) => {
74
+ export const LakeSearchField = ({ initialValue, placeholder, onChangeText, debounceDuration = 500, maxWidth, renderEnd, }) => {
95
75
  const [hasFocus, setFocused] = useBoolean(false);
96
76
  const inputRef = useRef(null);
97
77
  const [currentValue, setCurrentValue] = useState(initialValue);
@@ -107,5 +87,19 @@ export const LakeSearchField = ({ initialValue, placeholder, onChangeText, debou
107
87
  setCurrentValue("");
108
88
  }
109
89
  }, [onChangeText]);
110
- return (_jsx(ResponsiveContainer, { breakpoint: 200, style: [styles.root, maxWidth != null && { maxWidth }], children: ({ large }) => large ? (_jsx(ExpandedSearchField, { inputRef: inputRef, placeholder: placeholder, initialValue: initialValue, onChange: onChange, setFocused: setFocused, hasFocus: hasFocus, clear: clear, currentValue: currentValue })) : (_jsx(View, { style: styles.smallButtonContainer, children: _jsx(CollapsibleSeachField, { inputRef: inputRef, placeholder: placeholder, initialValue: initialValue, onChange: onChange, setFocused: setFocused, hasFocus: hasFocus, clear: clear, currentValue: currentValue }) })) }));
90
+ const props = {
91
+ inputRef,
92
+ placeholder,
93
+ initialValue,
94
+ onChange,
95
+ setFocused,
96
+ hasFocus,
97
+ clear,
98
+ currentValue,
99
+ renderEnd,
100
+ };
101
+ return (_jsx(ResponsiveContainer, { breakpoint: 200, style: maxWidth != null && { maxWidth }, children: ({ large }) => {
102
+ const Component = large ? ExpandedSearchField : CollapsibleSeachField;
103
+ return _jsx(Component, { ...props });
104
+ } }));
111
105
  };
@@ -23,6 +23,7 @@ export type LakeTextInputProps = Except<TextInputProps, "editable" | "keyboardTy
23
23
  onChange?: ChangeEventHandler<HTMLInputElement>;
24
24
  maxCharCount?: number;
25
25
  help?: string;
26
+ renderEnd?: () => ReactNode;
26
27
  };
27
28
  export declare const LakeTextInput: import("react").ForwardRefExoticComponent<{
28
29
  allowFontScaling?: boolean | undefined;
@@ -234,4 +235,5 @@ export declare const LakeTextInput: import("react").ForwardRefExoticComponent<{
234
235
  onChange?: ChangeEventHandler<HTMLInputElement> | undefined;
235
236
  maxCharCount?: number | undefined;
236
237
  help?: string | undefined;
238
+ renderEnd?: (() => ReactNode) | undefined;
237
239
  } & import("react").RefAttributes<TextInput | null>>;
@@ -19,7 +19,6 @@ const styles = StyleSheet.create({
19
19
  },
20
20
  container: {
21
21
  flexGrow: 1,
22
- flexShrink: 1,
23
22
  flexDirection: "row",
24
23
  alignItems: "stretch",
25
24
  },
@@ -27,21 +26,25 @@ const styles = StyleSheet.create({
27
26
  flexGrow: 1,
28
27
  flexShrink: 1,
29
28
  flexDirection: "row",
30
- alignItems: "stretch",
29
+ width: "100%",
30
+ display: "flex",
31
+ alignItems: "center",
32
+ justifyContent: "center",
33
+ borderRadius: radii[6],
34
+ backgroundColor: backgroundColor.accented,
35
+ borderColor: colors.gray[100],
36
+ borderWidth: 1,
37
+ paddingHorizontal: spacings[8],
31
38
  },
32
39
  input: {
33
40
  ...texts.regular,
34
- paddingHorizontal: spacings[16],
41
+ flexGrow: 1,
35
42
  outlineStyle: "none",
36
- height: 40,
37
- borderColor: colors.gray[100],
38
43
  placeholderTextColor: colors.gray[400],
39
- borderWidth: 1,
40
- borderRadius: radii[6],
41
- backgroundColor: backgroundColor.accented,
42
44
  color: colors.gray[900],
43
- width: "100%",
44
- flexShrink: 1,
45
+ paddingHorizontal: spacings[8],
46
+ height: 40,
47
+ minWidth: 0,
45
48
  },
46
49
  multilineInput: {
47
50
  height: "auto",
@@ -65,32 +68,29 @@ const styles = StyleSheet.create({
65
68
  borderColor: colors.gray[50],
66
69
  color: colors.gray[900],
67
70
  },
68
- withIcon: {
69
- paddingLeft: spacings[48],
70
- },
71
71
  error: {
72
72
  borderColor: colors.negative[400],
73
- paddingRight: spacings[48],
74
73
  },
75
74
  valid: {
76
75
  borderColor: colors.positive[500],
77
- paddingRight: spacings[48],
78
76
  },
79
77
  readOnlyError: {
80
78
  borderColor: TRANSPARENT,
81
79
  paddingRight: spacings[32],
82
80
  },
83
81
  endIcon: {
84
- position: "absolute",
85
- right: spacings[16],
86
- top: "50%",
87
- transform: "translateY(-50%)",
82
+ marginHorizontal: spacings[8],
83
+ },
84
+ endComponents: {
85
+ flexDirection: "row",
86
+ display: "flex",
87
+ alignItems: "center",
88
+ justifyContent: "center",
89
+ marginLeft: spacings[8],
88
90
  },
89
91
  icon: {
90
- position: "absolute",
91
- left: spacings[16],
92
- top: "50%",
93
- transform: "translateY(-50%)",
92
+ marginLeft: spacings[8],
93
+ margiRight: spacings[4],
94
94
  },
95
95
  readOnlyEndIcon: {
96
96
  right: 0,
@@ -122,9 +122,10 @@ const styles = StyleSheet.create({
122
122
  },
123
123
  });
124
124
  export const LakeTextInput = forwardRef(({ ariaExpanded, ariaControls, error, disabled = false, validating = false, valid = false, readOnly = false, icon, children, unit, color = "gray", inputMode = "text", hideErrors = false, onChange, pattern, style: stylesFromProps, onFocus: originalOnFocus, onBlur: originalOnBlur, value, defaultValue, multiline = false,
125
- //maxCharCount is different from maxLength(props inherited of TextInput), maxLength truncates the text in the limitation asked,
125
+ //maxCharCount is different from maxLength(props inherited of TextInput)
126
+ //maxLength truncates the text in the limitation asked,
126
127
  //maxCharCount doesn't have limitation but displays a counter of characters
127
- maxCharCount, help, ...props }, forwardRef) => {
128
+ maxCharCount, help, renderEnd, ...props }, forwardRef) => {
128
129
  const inputRef = useRef(null);
129
130
  const [isHovered, setIsHovered] = useState(false);
130
131
  const [isFocused, setIsFocused] = useState(false);
@@ -145,19 +146,23 @@ maxCharCount, help, ...props }, forwardRef) => {
145
146
  const isInteractive = !disabled && !readOnly;
146
147
  const hasError = isNotNullishOrEmpty(error);
147
148
  const charCount = isNullish(value) ? 0 : value.length;
148
- return (_jsxs(View, { style: commonStyles.fill, children: [_jsxs(View, { style: styles.root, "aria-errormessage": error, children: [_jsxs(View, { style: styles.container, children: [_jsxs(View, { style: styles.contents, children: [_jsx(TextInput, { "aria-expanded": ariaExpanded, "aria-controls": ariaControls, inputMode: inputMode, ref: mergedRef, ...props, defaultValue: defaultValue, value: isNullish(defaultValue) ? value ?? "" : value, onFocus: onFocus, onBlur: onBlur, readOnly: !isInteractive, onChange: onChange, multiline: multiline, style: [
149
+ return (_jsxs(View, { style: commonStyles.fill, children: [_jsxs(View, { style: styles.root, "aria-errormessage": error, children: [_jsxs(View, { style: styles.container, children: [_jsxs(View, { style: [
150
+ styles.contents,
151
+ isHovered && isInteractive && styles.hovered,
152
+ isFocused && { borderColor: colors[color][500] },
153
+ readOnly && hasError && styles.readOnlyError,
154
+ disabled && styles.disabled,
155
+ readOnly && styles.readOnly,
156
+ isFocused && styles.focused,
157
+ isNotNullish(unit) && styles.inputWithUnit,
158
+ hasError && styles.error,
159
+ valid && styles.valid,
160
+ stylesFromProps,
161
+ ], children: [isNotNullish(icon) && (_jsx(Icon, { name: icon, size: 20, color: colors.current.primary, style: styles.icon })), _jsx(TextInput, { "aria-expanded": ariaExpanded, "aria-controls": ariaControls, inputMode: inputMode, ref: mergedRef, ...props, defaultValue: defaultValue, value: isNullish(defaultValue) ? value ?? "" : value, onFocus: onFocus, onBlur: onBlur, readOnly: !isInteractive, onChange: onChange, multiline: multiline, style: [
149
162
  styles.input,
150
163
  multiline && styles.multilineInput,
151
- hasError && styles.error,
152
- valid && styles.valid,
153
- isNotNullish(icon) && styles.withIcon,
154
164
  readOnly && hasError && styles.readOnlyError,
155
165
  disabled && styles.disabled,
156
166
  readOnly && styles.readOnly,
157
- isHovered && isInteractive && styles.hovered,
158
- isNotNullish(unit) && styles.inputWithUnit,
159
- isFocused && styles.focused,
160
- isFocused && { borderColor: colors[color][500] },
161
- stylesFromProps,
162
- ] }), validating && (_jsx(ActivityIndicator, { size: "small", style: styles.endIcon, color: colors.current[500] })), !validating && hasError && (_jsx(Icon, { name: "warning-regular", size: 20, color: colors.negative[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), !validating && !hasError && valid && (_jsx(Icon, { name: "checkmark-filled", size: 20, color: colors.positive[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), isNotNullish(icon) && (_jsx(Icon, { name: icon, size: 20, color: colors.current.primary, style: styles.icon }))] }), isNotNullish(unit) && (_jsx(LakeText, { color: colors.gray[900], style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], children: unit }))] }), children] }), !hideErrors && (_jsxs(Box, { direction: "row", style: styles.errorContainer, children: [isNotNullish(help) ? (_jsx(LakeText, { variant: "smallRegular", color: isNotNullish(error) ? colors.negative[500] : colors.gray[500], children: help })) : (_jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error ?? " " })), isNotNullish(maxCharCount) && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 4 }), _jsxs(LakeText, { variant: "smallRegular", color: charCount > maxCharCount ? colors.negative[500] : colors.gray[400], style: styles.descriptionLimitation, children: [charCount, " / ", maxCharCount] })] }))] }))] }));
167
+ ] }), isNotNullish(renderEnd) && _jsx(View, { style: styles.endComponents, children: renderEnd() }), validating && (_jsx(ActivityIndicator, { size: "small", style: styles.endIcon, color: colors.current[500] })), !validating && hasError && (_jsx(Icon, { name: "warning-regular", size: 20, color: colors.negative[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] })), !validating && !hasError && valid && (_jsx(Icon, { name: "checkmark-filled", size: 20, color: colors.positive[400], style: [styles.endIcon, readOnly && styles.readOnlyEndIcon] }))] }), isNotNullish(unit) && (_jsx(LakeText, { color: colors.gray[900], style: [styles.unit, (disabled || readOnly) && styles.unitDisabled], children: unit }))] }), children] }), !hideErrors && (_jsxs(Box, { direction: "row", style: styles.errorContainer, children: [isNotNullish(error) ? (_jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error })) : (_jsx(LakeText, { variant: "smallRegular", color: colors.gray[500], children: help ?? " " })), isNotNullish(maxCharCount) && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 4 }), _jsxs(LakeText, { variant: "smallRegular", color: charCount > maxCharCount ? colors.negative[500] : colors.gray[400], style: styles.descriptionLimitation, children: [charCount, " / ", maxCharCount] })] }))] }))] }));
163
168
  });
@@ -30,7 +30,7 @@ export const showToast = ({ variant, title, description, autoClose }) => {
30
30
  return uid;
31
31
  }
32
32
  // by default, only info and success toasts are auto-closing
33
- const isAutoClosingToast = autoClose != null ? autoClose : variant === "info" || variant === "success";
33
+ const isAutoClosingToast = autoClose ?? (variant === "info" || variant === "success");
34
34
  const progress = isAutoClosingToast ? new Animated.Value(1) : undefined;
35
35
  const timeout = progress
36
36
  ? createControllableTimeout({