@swan-io/lake 8.7.1 → 8.8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/lake",
3
- "version": "8.7.1",
3
+ "version": "8.8.0",
4
4
  "engines": {
5
5
  "node": ">=20.9.0",
6
6
  "yarn": "^1.22.0"
@@ -35,6 +35,7 @@
35
35
  */
36
36
  import { ReactElement, ReactNode } from "react";
37
37
  import { IconName } from "./Icon";
38
+ import { SpacingValue } from "./Space";
38
39
  export type ColumnTitleConfig<ExtraInfo> = {
39
40
  title: string;
40
41
  extraInfo: ExtraInfo;
@@ -99,9 +100,10 @@ export declare const PlainListViewPlaceholder: ({ count, rowHeight, rowVerticalS
99
100
  type EmptyProps = {
100
101
  icon: IconName;
101
102
  borderedIcon?: boolean;
103
+ borderedIconPadding?: SpacingValue | 0;
102
104
  title?: string;
103
105
  subtitle?: ReactNode;
104
106
  children?: ReactNode;
105
107
  };
106
- export declare const FixedListViewEmpty: ({ icon, borderedIcon, title, subtitle, children, }: EmptyProps) => import("react/jsx-runtime").JSX.Element;
108
+ export declare const FixedListViewEmpty: ({ icon, borderedIcon, borderedIconPadding, title, subtitle, children, }: EmptyProps) => import("react/jsx-runtime").JSX.Element;
107
109
  export {};
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /**
3
3
  * ## FixedListView
4
4
  *
@@ -526,15 +526,10 @@ export const FixedListView = ({ data: originalData, mode = "tile", keyExtractor,
526
526
  ]);
527
527
  // Used to fix some scrollbar behavior. See `main.css`.
528
528
  useLayoutEffect(() => {
529
- if (centerHeadersRef.current instanceof Element) {
530
- centerHeadersRef.current.setAttribute("data-hide-scrollbar", String(true));
531
- }
532
- if (centerColumnsRef.current instanceof Element) {
533
- centerColumnsRef.current.setAttribute("data-hide-scrollbar", String(true));
534
- }
535
- if (horizontalScrollbarRef.current instanceof Element) {
536
- horizontalScrollbarRef.current.setAttribute("data-force-scrollbar", String(true));
537
- }
529
+ var _a, _b, _c, _d, _e, _f;
530
+ (_b = (_a = centerHeadersRef.current) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.setAttribute("data-hide-scrollbar", String(true));
531
+ (_d = (_c = centerColumnsRef.current) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.setAttribute("data-hide-scrollbar", String(true));
532
+ (_f = (_e = horizontalScrollbarRef.current) === null || _e === void 0 ? void 0 : _e.element) === null || _f === void 0 ? void 0 : _f.setAttribute("data-force-scrollbar", String(true));
538
533
  }, []);
539
534
  // To synchronize scrolls, we keep track of the initiator in order to ignore the scroll events
540
535
  // we provoke ourselves with the sync.
@@ -547,9 +542,9 @@ export const FixedListView = ({ data: originalData, mode = "tile", keyExtractor,
547
542
  isNotNullish(centerColumnsRef.current) &&
548
543
  isNotNullish(horizontalScrollbarRef.current)) {
549
544
  const SCROLL_THRESHOLD_MS = 500;
550
- const centerColumns = centerColumnsRef.current;
551
- const centerHeaders = centerHeadersRef.current;
552
- const horizontalScrollbar = horizontalScrollbarRef.current;
545
+ const centerColumns = centerColumnsRef.current.element;
546
+ const centerHeaders = centerHeadersRef.current.element;
547
+ const horizontalScrollbar = horizontalScrollbarRef.current.element;
553
548
  const onColumnsScroll = () => {
554
549
  const now = Date.now();
555
550
  if (lastHorizontalScroll.current.initiator === "columns" ||
@@ -833,4 +828,4 @@ export const PlainListViewPlaceholder = ({ count, rowHeight, rowVerticalSpacing,
833
828
  ], children: [_jsx(View, { style: styles.placeholderRow }), _jsx(Space, { width: 32 }), _jsx(View, { style: [styles.placeholderRow, styles.smallPlaceholderRow] }), _jsx(Space, { width: 32 }), _jsx(View, { style: styles.placeholderRowEnd, children: _jsx(View, { style: [styles.placeholderRow, styles.smallPlaceholderRow] }) })] }, String(index))] }, String(index)));
834
829
  }) })] }));
835
830
  };
836
- export const FixedListViewEmpty = ({ icon, borderedIcon = false, title, subtitle, children, }) => (_jsxs(View, { style: styles.emptyList, children: [borderedIcon ? (_jsx(BorderedIcon, { name: icon })) : (_jsx(Icon, { name: icon, size: 96, color: colors.current.primary })), _jsx(Space, { height: 32 }), isNotNullish(title) && (_jsx(LakeHeading, { level: 3, variant: "h3", color: colors.gray[700], align: "center", children: title })), _jsx(Space, { height: 8 }), isNotNullish(subtitle) && _jsx(LakeText, { align: "center", children: subtitle }), _jsx(Space, { height: 8 }), children] }));
831
+ export const FixedListViewEmpty = ({ icon, borderedIcon = false, borderedIconPadding, title, subtitle, children, }) => (_jsxs(View, { style: styles.emptyList, children: [borderedIcon ? (_jsx(BorderedIcon, { name: icon, padding: borderedIconPadding })) : (_jsx(Icon, { name: icon, size: 96, color: colors.current.primary })), _jsx(Space, { height: 24 }), isNotNullish(title) && (_jsxs(_Fragment, { children: [_jsx(LakeHeading, { align: "center", level: 3, variant: "h5", children: title }), _jsx(Space, { height: 8 })] })), isNotNullish(subtitle) && _jsx(LakeText, { align: "center", children: subtitle }), children] }));
@@ -7,6 +7,7 @@ export type ButtonProps = {
7
7
  ariaExpanded?: boolean;
8
8
  color?: ColorVariants;
9
9
  disabled?: boolean;
10
+ direction?: "column" | "row";
10
11
  loading?: boolean;
11
12
  grow?: boolean;
12
13
  icon?: IconName;
@@ -14,6 +15,7 @@ export type ButtonProps = {
14
15
  mode?: "primary" | "secondary" | "tertiary";
15
16
  onPress?: (event: GestureResponderEvent) => void;
16
17
  size?: "large" | "small";
18
+ iconSize?: number;
17
19
  style?: StyleProp<ViewStyle> | ((props: PressableStateCallbackType) => StyleProp<ViewStyle>);
18
20
  forceBackground?: boolean;
19
21
  href?: string;
@@ -5,6 +5,7 @@ import { match } from "ts-pattern";
5
5
  import { commonStyles } from "../constants/commonStyles";
6
6
  import { backgroundColor, colors, invariantColors, radii, spacings, texts, } from "../constants/design";
7
7
  import { isNotNullish, isNullish } from "../utils/nullish";
8
+ import { Box } from "./Box";
8
9
  import { Icon } from "./Icon";
9
10
  import { LakeText } from "./LakeText";
10
11
  import { Pressable } from "./Pressable";
@@ -81,7 +82,6 @@ const styles = StyleSheet.create({
81
82
  alignItems: "center",
82
83
  justifyContent: "center",
83
84
  transform: "translateZ(0px)",
84
- borderRadius: radii[6],
85
85
  },
86
86
  group: {
87
87
  flexDirection: "row",
@@ -99,16 +99,32 @@ const styles = StyleSheet.create({
99
99
  top: -3,
100
100
  right: -3,
101
101
  },
102
+ vertical: {
103
+ flexDirection: "column",
104
+ height: "auto",
105
+ paddingVertical: spacings[12],
106
+ },
107
+ verticalSmall: {
108
+ paddingVertical: spacings[8],
109
+ },
110
+ hidden: {
111
+ visibility: "hidden",
112
+ },
102
113
  });
103
- export const LakeButton = memo(forwardRef(({ ariaControls, ariaExpanded, ariaLabel, children, color = "gray", disabled = false, icon, grow = false, iconPosition = "start", loading = false, mode = "primary", onPress, size = "large", style, forceBackground = false, href, hrefAttrs, pill, }, forwardedRef) => {
114
+ export const LakeButton = memo(forwardRef(({ ariaControls, ariaExpanded, ariaLabel, children, color = "gray", direction = "row", disabled = false, icon, grow = false, iconPosition = "start", loading = false, mode = "primary", onPress, size = "large", iconSize = size === "small" ? 18 : 20, style, forceBackground = false, href, hrefAttrs, pill = false, }, forwardedRef) => {
115
+ const isPrimary = mode === "primary";
104
116
  const isSmall = size === "small";
105
- const iconSize = isSmall ? 18 : 20;
106
- const hasIconStart = isNotNullish(icon) && iconPosition === "start";
107
- const hasIconEnd = isNotNullish(icon) && iconPosition === "end";
108
- const hasOnlyIcon = isNullish(children) && isNotNullish(icon);
117
+ const vertical = direction === "column";
118
+ const spaceHeight = vertical ? 4 : undefined;
119
+ const spaceWidth = vertical ? undefined : isSmall ? 8 : 12;
120
+ const hasIcon = isNotNullish(icon);
121
+ const hasIconStart = hasIcon && iconPosition === "start";
122
+ const hasIconEnd = hasIcon && iconPosition === "end";
123
+ const hasOnlyIcon = hasIcon && isNullish(children);
109
124
  return (_jsx(Pressable, { href: href, hrefAttrs: hrefAttrs, role: href != null ? "link" : "button", "aria-busy": loading, "aria-disabled": disabled, "aria-controls": ariaControls, "aria-expanded": ariaExpanded, "aria-label": ariaLabel, disabled: loading || disabled, ref: forwardedRef, onPress: onPress, style: ({ hovered, pressed, focused }) => [
110
125
  styles.base,
111
126
  isSmall && styles.small,
127
+ vertical && [styles.vertical, isSmall && styles.verticalSmall],
112
128
  hasIconStart && isSmall ? styles.withIconStartSmall : styles.withIconStart,
113
129
  hasIconEnd && (isSmall ? styles.withIconEndSmall : styles.withIconEnd),
114
130
  hasOnlyIcon && (isSmall ? styles.iconSmallOnly : styles.iconOnly),
@@ -150,23 +166,18 @@ export const LakeButton = memo(forwardRef(({ ariaControls, ariaExpanded, ariaLab
150
166
  .exhaustive(),
151
167
  typeof style == "function" ? style({ hovered, pressed, focused }) : style,
152
168
  ], children: ({ pressed, hovered }) => {
153
- const textColor = mode === "secondary" || mode === "tertiary"
154
- ? disabled && forceBackground
169
+ const textColor = isPrimary
170
+ ? colors[color].contrast
171
+ : disabled && forceBackground
155
172
  ? colors[color][300]
156
173
  : hovered || pressed
157
174
  ? colors[color][700]
158
- : colors[color][600]
159
- : colors[color].contrast;
160
- return (_jsxs(_Fragment, { children: [hasIconStart && (_jsxs(_Fragment, { children: [_jsx(Icon, { color: textColor, name: icon, size: iconSize }), isNotNullish(children) && _jsx(Space, { width: isSmall ? 8 : 12 })] })), typeof children === "string" || typeof children === "number" ? (_jsx(LakeText, { numberOfLines: 1, userSelect: "none", style: [isSmall ? styles.textSmall : styles.text, { color: textColor }], children: children })) : (children), hasIconEnd && (_jsxs(_Fragment, { children: [isNotNullish(children) && _jsx(Space, { width: isSmall ? 8 : 12 }), _jsx(Icon, { color: textColor, name: icon, size: iconSize })] })), loading && (_jsx(View, { role: "none", style: [
161
- styles.loaderContainer,
162
- {
163
- backgroundColor: mode === "secondary" || mode === "tertiary"
164
- ? backgroundColor.accented
165
- : colors[color].primary,
166
- },
167
- ], children: _jsx(ActivityIndicator, { color: mode === "secondary" || mode === "tertiary"
168
- ? colors[color].primary
169
- : colors[color].contrast, size: iconSize }) })), _jsx(View, { style: [styles.hiddenView, pressed && mode === "primary" && styles.pressed] }), pill === true ? _jsx(View, { style: styles.pill }) : null] }));
175
+ : colors[color][600];
176
+ return (_jsxs(_Fragment, { children: [hasIconStart && (_jsxs(_Fragment, { children: [_jsx(Icon, { color: textColor, name: icon, size: iconSize, style: loading && styles.hidden }), isNotNullish(children) && _jsx(Space, { height: spaceHeight, width: spaceWidth })] })), typeof children === "string" || typeof children === "number" ? (_jsx(LakeText, { numberOfLines: 1, userSelect: "none", style: [
177
+ isSmall ? styles.textSmall : styles.text,
178
+ loading && styles.hidden,
179
+ { color: textColor },
180
+ ], children: children })) : (_jsx(Box, { alignItems: "center", justifyContent: "center", style: [vertical && styles.vertical, loading && styles.hidden], children: children })), hasIconEnd && (_jsxs(_Fragment, { children: [isNotNullish(children) && _jsx(Space, { height: spaceHeight, width: spaceWidth }), _jsx(Icon, { color: textColor, name: icon, size: iconSize, style: loading && styles.hidden })] })), loading && (_jsx(View, { style: styles.loaderContainer, children: _jsx(ActivityIndicator, { color: isPrimary ? colors[color].contrast : colors[color].primary, size: iconSize }) })), isPrimary && _jsx(View, { style: [styles.hiddenView, pressed && styles.pressed] }), pill && _jsx(View, { style: styles.pill })] }));
170
181
  } }));
171
182
  }));
172
183
  LakeButton.displayName = "Button";
@@ -125,7 +125,7 @@ const LakeSelectWithRef = ({ title, items, valueStyle, size, color = "current",
125
125
  const isSmall = size === "small";
126
126
  const itemValue = items.find(i => i.value === value);
127
127
  const onKeyDown = useCallback((event) => {
128
- var _a, _b;
128
+ var _a, _b, _c;
129
129
  // this made a search not visible for user as the native select component
130
130
  if (event.nativeEvent.key.length === 1) {
131
131
  event.nativeEvent.stopPropagation();
@@ -135,9 +135,8 @@ const LakeSelectWithRef = ({ title, items, valueStyle, size, color = "current",
135
135
  const selected = items[selectedIndex];
136
136
  if (selected != null) {
137
137
  if (visible) {
138
- const listElement = listRef.current;
139
- if (listElement != null) {
140
- (_b = listItemRefs.current[selectedIndex]) === null || _b === void 0 ? void 0 : _b.focus();
138
+ if (((_b = listRef.current) === null || _b === void 0 ? void 0 : _b.element) != null) {
139
+ (_c = listItemRefs.current[selectedIndex]) === null || _c === void 0 ? void 0 : _c.focus();
141
140
  }
142
141
  }
143
142
  else {
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  import { NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewProps, ViewStyle } from "react-native";
3
3
  export type ScrollViewRef = {
4
+ element: HTMLElement | null;
4
5
  scrollTo: (event: {
5
6
  x?: number;
6
7
  y?: number;
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useCallback, useImperativeHandle, useRef, } from "react";
3
3
  import { StyleSheet, View, } from "react-native";
4
- import { useMergeRefs } from "../hooks/useMergeRefs";
5
4
  const styles = StyleSheet.create({
6
5
  base: {
7
6
  WebkitOverflowScrolling: "touch",
@@ -60,7 +59,6 @@ export const ScrollView = forwardRef(({ children, contentContainerStyle, horizon
60
59
  const innerRef = useRef(null);
61
60
  const stateRef = useRef({ lastTick: 0, scrolling: false });
62
61
  const timeoutRef = useRef(null);
63
- const mergedRef = useMergeRefs(innerRef, forwardedRef);
64
62
  const handleOnScroll = useCallback((event) => {
65
63
  event.stopPropagation();
66
64
  // A scroll happened, so the scroll resets the scrollend timeout.
@@ -89,8 +87,11 @@ export const ScrollView = forwardRef(({ children, contentContainerStyle, horizon
89
87
  }
90
88
  }
91
89
  }, []);
92
- useImperativeHandle(forwardedRef, () => ({ scrollTo }));
93
- return (_jsx(View, { ...viewProps, ref: mergedRef, onScroll: handleOnScroll, style: [
90
+ useImperativeHandle(forwardedRef, () => ({
91
+ element: innerRef.current,
92
+ scrollTo,
93
+ }));
94
+ return (_jsx(View, { ...viewProps, ref: innerRef, onScroll: handleOnScroll, style: [
94
95
  styles.base,
95
96
  style,
96
97
  horizontal && styles.horizontal,