@swan-io/lake 15.5.1 → 15.5.3
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/Accordion.js +2 -2
- package/src/components/ContextMenu.js +2 -2
- package/src/components/LakeSelect.js +1 -2
- package/src/components/LakeSlider.d.ts +2 -1
- package/src/components/LakeSlider.js +1 -1
- package/src/components/LakeTagInput.d.ts +1 -1
- package/src/components/LakeTagInput.js +2 -2
- package/src/components/LakeTooltip.js +14 -10
- package/src/components/MultiSelect.js +1 -2
- package/src/components/Tile.js +2 -2
- package/src/hooks/useContextualLayer.d.ts +3 -1
- package/src/hooks/useContextualLayer.js +23 -2
- package/src/hooks/useDisclosure.d.ts +0 -5
- package/src/hooks/useDisclosure.js +0 -12
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useId } from "react";
|
|
3
3
|
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
4
|
import { backgroundColor, colors, spacings } from "../constants/design";
|
|
5
|
-
import {
|
|
5
|
+
import { useBoolean } from "../hooks/useBoolean";
|
|
6
6
|
import { Icon } from "./Icon";
|
|
7
7
|
import { LakeText } from "./LakeText";
|
|
8
8
|
import { Space } from "./Space";
|
|
@@ -40,6 +40,6 @@ const styles = StyleSheet.create({
|
|
|
40
40
|
});
|
|
41
41
|
export const Accordion = ({ children, trigger, style, contentContainerStyle }) => {
|
|
42
42
|
const id = useId();
|
|
43
|
-
const [isOpen, { toggle }] =
|
|
43
|
+
const [isOpen, { toggle }] = useBoolean(false);
|
|
44
44
|
return (_jsxs(View, { children: [_jsxs(Pressable, { "aria-controls": id, role: "button", "aria-expanded": isOpen, onPress: toggle, style: [styles.trigger, style], children: [_jsx(Icon, { name: "chevron-right-filled", size: 12, color: colors.gray[500], style: [styles.arrow, isOpen && styles.arrowOpen] }), _jsx(Space, { width: 20 }), typeof trigger === "string" ? (_jsx(LakeText, { variant: "smallMedium", color: colors.gray[900], children: trigger })) : (trigger)] }), _jsx(View, { "aria-labelledby": id, "aria-hidden": !isOpen, role: "region", style: [styles.contentContainer, isOpen && styles.contentContainerDisplayed], children: _jsx(View, { style: styles.contentInner, children: _jsx(View, { style: [styles.content, contentContainerStyle], children: children }) }) })] }));
|
|
45
45
|
};
|
|
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { createContext, useContext, useRef } from "react";
|
|
3
3
|
import { StyleSheet, View } from "react-native";
|
|
4
4
|
import { colors, spacings } from "../constants/design";
|
|
5
|
-
import {
|
|
5
|
+
import { useBoolean } from "../hooks/useBoolean";
|
|
6
6
|
import { noop } from "../utils/function";
|
|
7
7
|
import { LakeButton } from "./LakeButton";
|
|
8
8
|
import { LakeText } from "./LakeText";
|
|
@@ -28,7 +28,7 @@ const styles = StyleSheet.create({
|
|
|
28
28
|
});
|
|
29
29
|
const ContextMenuContext = createContext({ close: noop });
|
|
30
30
|
export const ContextMenu = ({ children, ariaLabel, withPill = false, verticalPlacement, }) => {
|
|
31
|
-
const [isOpen, { open, close }] =
|
|
31
|
+
const [isOpen, { on: open, off: close }] = useBoolean(false);
|
|
32
32
|
const triggerRef = useRef(null);
|
|
33
33
|
return (_jsxs(ContextMenuContext.Provider, { value: { close }, children: [_jsx(LakeButton, { ref: triggerRef, mode: "tertiary", size: "small", icon: "more-horizontal-filled", color: "gray", onPress: open, ariaLabel: ariaLabel, pill: withPill }), _jsx(Popover, { referenceRef: triggerRef, visible: isOpen, onDismiss: close, verticalPlacement: verticalPlacement, children: _jsx(View, { style: styles.container, children: children }) })] }));
|
|
34
34
|
};
|
|
@@ -5,7 +5,6 @@ import { t } from "../../../shared-business/src/utils/i18n";
|
|
|
5
5
|
import { commonStyles } from "../constants/commonStyles";
|
|
6
6
|
import { backgroundColor, colors, invariantColors, radii, shadows, spacings, texts, } from "../constants/design";
|
|
7
7
|
import { useBoolean } from "../hooks/useBoolean";
|
|
8
|
-
import { useDisclosure } from "../hooks/useDisclosure";
|
|
9
8
|
import { useMergeRefs } from "../hooks/useMergeRefs";
|
|
10
9
|
import { getFocusableElements } from "../utils/a11y";
|
|
11
10
|
import { setHighlightApi } from "../utils/highlights";
|
|
@@ -163,7 +162,7 @@ export const LakeSelect = ({ ref, title, items, valueStyle, size, color = "curre
|
|
|
163
162
|
const currentlyTypedRef = useRef(undefined);
|
|
164
163
|
const listItemRefs = useRef(Array(items.length));
|
|
165
164
|
const mergedRef = useMergeRefs(inputRef, ref);
|
|
166
|
-
const [visible, {
|
|
165
|
+
const [visible, { on: open, off: close }] = useBoolean(false);
|
|
167
166
|
const hasValue = isNotNullish(value);
|
|
168
167
|
const isSmall = size === "small";
|
|
169
168
|
const itemValue = items.find(i => i.value === value);
|
|
@@ -7,7 +7,8 @@ type Props = {
|
|
|
7
7
|
step: number;
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
style?: ViewProps["style"];
|
|
10
|
+
labelledBy?: string;
|
|
10
11
|
onChange: (value: number) => void;
|
|
11
12
|
};
|
|
12
|
-
export declare const LakeSlider: ({ id, min, max, value, step, disabled, style, onChange, }: Props) => import("react").JSX.Element;
|
|
13
|
+
export declare const LakeSlider: ({ id, min, max, value, step, disabled, style, labelledBy, onChange, }: Props) => import("react").JSX.Element;
|
|
13
14
|
export {};
|
|
@@ -8,7 +8,7 @@ const styles = StyleSheet.create({
|
|
|
8
8
|
zIndex: 1,
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
|
-
export const LakeSlider = ({ id, min, max, value, step, disabled = false, style, onChange, }) => (_jsx(View, { style: [styles.container, style], children: _jsx("input", { id: id, type: "range", min: min, max: max, value: value, step: step, disabled: disabled, onChange: useCallback((event) => onChange(Number(event.target.value)), [onChange]), style: {
|
|
11
|
+
export const LakeSlider = ({ id, min, max, value, step, disabled = false, style, labelledBy, onChange, }) => (_jsx(View, { style: [styles.container, style], children: _jsx("input", { id: id, "aria-labelledby": labelledBy, type: "range", min: min, max: max, value: value, step: step, disabled: disabled, onChange: useCallback((event) => onChange(Number(event.target.value)), [onChange]), style: {
|
|
12
12
|
backgroundSize: `${((value - min) / (max - min)) * 100}% 100%`,
|
|
13
13
|
...(disabled ? commonStyles.disabled : {}),
|
|
14
14
|
} }) }));
|
|
@@ -18,4 +18,4 @@ export type LakeTagInputProps = Merge<TextInputProps, {
|
|
|
18
18
|
onValuesChanged: (values: string[]) => void;
|
|
19
19
|
placeholder?: string;
|
|
20
20
|
}>;
|
|
21
|
-
export declare const LakeTagInput: ({ ref, validator, onFocus: originalOnFocus, onBlur: originalOnBlur, validateOnBlur, values, onValuesChanged, readOnly, disabled, valid, hideErrors, placeholder, help, error, }: LakeTagInputProps) => import("react").JSX.Element;
|
|
21
|
+
export declare const LakeTagInput: ({ ref, id, validator, onFocus: originalOnFocus, onBlur: originalOnBlur, validateOnBlur, values, onValuesChanged, readOnly, disabled, valid, hideErrors, placeholder, help, error, }: LakeTagInputProps) => import("react").JSX.Element;
|
|
@@ -77,7 +77,7 @@ const styles = StyleSheet.create({
|
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
const SEPARATORS_REGEX = /,| /;
|
|
80
|
-
export const LakeTagInput = ({ ref, validator = () => true, onFocus: originalOnFocus, onBlur: originalOnBlur, validateOnBlur = true, values, onValuesChanged, readOnly = false, disabled = false, valid = false, hideErrors = false, placeholder, help, error, }) => {
|
|
80
|
+
export const LakeTagInput = ({ ref, id, validator = () => true, onFocus: originalOnFocus, onBlur: originalOnBlur, validateOnBlur = true, values, onValuesChanged, readOnly = false, disabled = false, valid = false, hideErrors = false, placeholder, help, error, }) => {
|
|
81
81
|
const inputRef = useRef(null);
|
|
82
82
|
const containerRef = useRef(null);
|
|
83
83
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -152,5 +152,5 @@ export const LakeTagInput = ({ ref, validator = () => true, onFocus: originalOnF
|
|
|
152
152
|
isHovered && styles.hovered,
|
|
153
153
|
], "aria-errormessage": error, onPress: autoFocus, ref: containerRef, children: [values.map((value, i) => (_jsx(Tag, { onPressRemove: !readOnly && !disabled
|
|
154
154
|
? () => onValuesChanged(values.filter(current => current !== value))
|
|
155
|
-
: undefined, style: styles.tag, color: validator(value) ? "gray" : "negative", children: value }, i))), _jsx(TextInput, { ref: mergedRef, style: [styles.input, disabled && styles.disabled], onFocus: onFocus, onBlur: onBlur, "aria-disabled": disabled, onChangeText: onTextInputChange, onKeyPress: onTextInputKeyPress, readOnly: readOnly, placeholder: placeholder })] }), !hideErrors && (_jsx(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 !== null && help !== void 0 ? help : " " })) }))] }));
|
|
155
|
+
: undefined, style: styles.tag, color: validator(value) ? "gray" : "negative", children: value }, i))), _jsx(TextInput, { ref: mergedRef, id: id, style: [styles.input, disabled && styles.disabled], onFocus: onFocus, onBlur: onBlur, "aria-disabled": disabled, onChangeText: onTextInputChange, onKeyPress: onTextInputKeyPress, readOnly: readOnly, placeholder: placeholder })] }), !hideErrors && (_jsx(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 !== null && help !== void 0 ? help : " " })) }))] }));
|
|
156
156
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
3
3
|
import { StyleSheet, View } from "react-native";
|
|
4
|
-
import { match } from "ts-pattern";
|
|
4
|
+
import { match, P } from "ts-pattern";
|
|
5
5
|
import { colors, shadows, spacings } from "../constants/design";
|
|
6
6
|
import { useContextualLayer } from "../hooks/useContextualLayer";
|
|
7
7
|
import { useHover } from "../hooks/useHover";
|
|
@@ -57,6 +57,7 @@ const Tooltip = memo(({ ref, children, content, describedBy, matchReferenceWidth
|
|
|
57
57
|
placement,
|
|
58
58
|
visible,
|
|
59
59
|
matchReferenceWidth,
|
|
60
|
+
withArrow: !hideArrow,
|
|
60
61
|
});
|
|
61
62
|
const rootElement = getRootElement(referenceRef.current);
|
|
62
63
|
useImperativeHandle(ref, () => ({
|
|
@@ -113,14 +114,17 @@ const Tooltip = memo(({ ref, children, content, describedBy, matchReferenceWidth
|
|
|
113
114
|
useEffect(() => {
|
|
114
115
|
return () => clearTimeout(timeoutRef.current);
|
|
115
116
|
}, []);
|
|
116
|
-
return (_jsxs(_Fragment, { children: [_jsx(View, { ref: referenceRef, style: containerStyle, children: children }), isNotNullish(rootElement) && position.isSome() && !disabled && (_jsx(Portal, { container: rootElement, children: _jsx(View, { style: [position.get().rootStyle, styles.root], children: _jsxs(View, { ref: contentRef, role: "tooltip", "aria-describedby": describedBy, style: [styles.base, position.get().style], children: [position.get().verticalPosition === "bottom" ? (_jsx(
|
|
117
|
-
.with("left", () => "start")
|
|
118
|
-
.with("center", () => "center")
|
|
119
|
-
.with("right", () => "end")
|
|
120
|
-
.exhaustive(), style: [styles.arrowBar, styles.arrowBarTop], children: _jsx(Svg, { width: 16, height: 8, viewBox: "0 0 16 8", children: _jsx(Polygon, { points: "8 0 16 8 0 8", fill: hideArrow ? "transparent" : colors.gray[900] }) }) })) : null, _jsx(View, { style: [styles.content, { width, maxWidth }], children: typeof content === "string" || typeof content === "number" ? (_jsx(LakeText, { align: "center", color: colors.gray.contrast, children: content })) : (content) }), position.get().verticalPosition === "top" ? (_jsx(Box, { direction: "row", justifyContent: match(position.get().horizontalPosition)
|
|
121
|
-
.with("left", () => "start")
|
|
122
|
-
.with("center", () => "center")
|
|
123
|
-
.with("right", () => "end")
|
|
124
|
-
.exhaustive(), style: [styles.arrowBar, styles.arrowBarBottom], children: _jsx(Svg, { width: 16, height: 8, viewBox: "0 0 16 8", children: _jsx(Polygon, { points: "8 8 16 0 0 0", fill: hideArrow ? "transparent" : colors.gray[900] }) }) })) : null] }) }) }))] }));
|
|
117
|
+
return (_jsxs(_Fragment, { children: [_jsx(View, { ref: referenceRef, style: containerStyle, children: children }), isNotNullish(rootElement) && position.isSome() && !disabled && (_jsx(Portal, { container: rootElement, children: _jsx(View, { style: [position.get().rootStyle, styles.root], children: _jsxs(View, { ref: contentRef, role: "tooltip", "aria-describedby": describedBy, style: [styles.base, position.get().style], children: [position.get().verticalPosition === "bottom" ? (_jsx(TooltipArrow, { verticalPosition: "bottom", position: position.get().arrowPosition, hideArrow: hideArrow })) : null, _jsx(View, { style: [styles.content, { width, maxWidth }], children: typeof content === "string" || typeof content === "number" ? (_jsx(LakeText, { align: "center", color: colors.gray.contrast, children: content })) : (content) }), position.get().verticalPosition === "top" ? (_jsx(TooltipArrow, { verticalPosition: "top", position: position.get().arrowPosition, hideArrow: hideArrow })) : null] }) }) }))] }));
|
|
125
118
|
});
|
|
119
|
+
const TooltipArrow = ({ verticalPosition, position, hideArrow }) => {
|
|
120
|
+
const { polygonPoints, top, bottom } = verticalPosition === "top"
|
|
121
|
+
? { polygonPoints: "8 8 16 0 0 0", top: undefined, bottom: 1 }
|
|
122
|
+
: { polygonPoints: "8 0 16 8 0 8", top: 1, bottom: undefined };
|
|
123
|
+
const { justifyContent, left } = match(position)
|
|
124
|
+
.with("left", () => ({ justifyContent: "start", left: undefined }))
|
|
125
|
+
.with("right", () => ({ justifyContent: "end", left: undefined }))
|
|
126
|
+
.with(P.number, value => ({ justifyContent: "center", left: value }))
|
|
127
|
+
.exhaustive();
|
|
128
|
+
return (_jsx(Box, { direction: "row", justifyContent: justifyContent, style: [styles.arrowBar, styles.arrowBarBottom, { top, bottom, left }], children: _jsx(Svg, { width: 16, height: 8, viewBox: "0 0 16 8", children: _jsx(Polygon, { points: polygonPoints, fill: hideArrow ? "transparent" : colors.gray[900] }) }) }));
|
|
129
|
+
};
|
|
126
130
|
export const InformationTooltip = ({ ref, text, placement = "center", icon = "info-regular", iconSize = 24, }) => (_jsx(LakeTooltip, { ref: ref, describedBy: "copy", placement: placement, togglableOnFocus: true, width: 300, content: text, children: _jsx(View, { style: styles.info, children: _jsx(Icon, { name: icon, size: iconSize, color: colors.gray[900] }) }) }));
|
|
@@ -4,7 +4,6 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import { Pressable, StyleSheet, Text, TextInput, View, } from "react-native";
|
|
5
5
|
import { backgroundColor, colors, radii, shadows, texts } from "../constants/design";
|
|
6
6
|
import { useBoolean } from "../hooks/useBoolean";
|
|
7
|
-
import { useDisclosure } from "../hooks/useDisclosure";
|
|
8
7
|
import { groupBy } from "../utils/array";
|
|
9
8
|
import { isNotNullish, isNotNullishOrEmpty } from "../utils/nullish";
|
|
10
9
|
import { safeSplitAround } from "../utils/string";
|
|
@@ -143,7 +142,7 @@ export const MultiSelect = ({ color = "gray", disabled = false, emptyResultText,
|
|
|
143
142
|
const shouldScrollToBottomRef = useRef(false);
|
|
144
143
|
const selectedTagListRef = useRef(null);
|
|
145
144
|
const inputRef = useRef(null);
|
|
146
|
-
const [visible, { open, close }] =
|
|
145
|
+
const [visible, { on: open, off: close }] = useBoolean(false);
|
|
147
146
|
const tint50 = colors[color][50];
|
|
148
147
|
const tint100 = colors[color][100];
|
|
149
148
|
useEffect(() => {
|
package/src/components/Tile.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Children, cloneElement, Fragment, useCallback, useId, useState, } from "react";
|
|
3
3
|
import { Pressable, StyleSheet, Text, View, } from "react-native";
|
|
4
4
|
import { backgroundColor, colors, negativeSpacings, radii, shadows, spacings, texts, } from "../constants/design";
|
|
5
|
-
import {
|
|
5
|
+
import { useBoolean } from "../hooks/useBoolean";
|
|
6
6
|
import { isNotNullish } from "../utils/nullish";
|
|
7
7
|
import { Box } from "./Box";
|
|
8
8
|
import { Icon } from "./Icon";
|
|
@@ -99,7 +99,7 @@ const styles = StyleSheet.create({
|
|
|
99
99
|
});
|
|
100
100
|
export const Tile = ({ icon, title, description, headerEnd, footer, flexBasis, children, numberOfLines, paddingVertical = 32, paddingHorizontal = 32, hovered = false, flexGrow = 0, flexShrink = 0, disabled = false, selected, collapsible = false, defaultExpanded = true, style, }) => {
|
|
101
101
|
const contentId = useId();
|
|
102
|
-
const [expanded, { toggle }] =
|
|
102
|
+
const [expanded, { toggle }] = useBoolean(defaultExpanded);
|
|
103
103
|
const hasHeader = isNotNullish(title) || isNotNullish(headerEnd) || isNotNullish(description) || collapsible;
|
|
104
104
|
const header = (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.header, children: [_jsxs(View, { style: styles.headerTitleIcon, children: [isNotNullish(icon) && (_jsxs(_Fragment, { children: [icon, _jsx(Space, { height: 12 })] })), isNotNullish(title) && (_jsx(Text, { style: styles.title, role: "heading", "aria-level": 3, children: title }))] }), collapsible ? (_jsx(Icon, { name: "chevron-down-filled", size: 16, color: colors.gray[500], style: [styles.chevron, expanded && styles.chevronOpen] })) : isNotNullish(headerEnd) ? (_jsx(View, { children: headerEnd })) : null] }), isNotNullish(description) && (_jsxs(_Fragment, { children: [isNotNullish(title) && _jsx(Space, { height: 12 }), _jsx(View, { style: styles.descriptionContainer, children: _jsx(LakeText, { numberOfLines: numberOfLines, style: styles.description, children: description }) })] }))] }));
|
|
105
105
|
const content = (_jsxs(_Fragment, { children: [children, isNotNullish(footer) && (_jsx(View, { style: [styles.footer, { marginTop: paddingVertical, marginBottom: -paddingVertical }], children: footer }))] }));
|
|
@@ -24,17 +24,19 @@ type Config = {
|
|
|
24
24
|
matchReferenceWidth?: boolean;
|
|
25
25
|
matchReferenceMinWidth?: boolean;
|
|
26
26
|
referenceRef?: RefObject<View | Text | null>;
|
|
27
|
+
withArrow?: boolean;
|
|
27
28
|
};
|
|
28
29
|
export type ContextualLayerPosition = {
|
|
29
30
|
rootStyle: ViewStyle;
|
|
30
31
|
style: ViewStyle;
|
|
31
32
|
verticalPosition: "top" | "bottom";
|
|
32
33
|
horizontalPosition: "left" | "center" | "right";
|
|
34
|
+
arrowPosition: "left" | "right" | number;
|
|
33
35
|
};
|
|
34
36
|
type ContextualLayerConfig = {
|
|
35
37
|
referenceRef: RefObject<View | Text | null>;
|
|
36
38
|
contentRef: RefObject<View | Text | null>;
|
|
37
39
|
position: Option<ContextualLayerPosition>;
|
|
38
40
|
};
|
|
39
|
-
export declare const useContextualLayer: ({ placement, verticalPlacement, visible, matchReferenceWidth, matchReferenceMinWidth, referenceRef: externalReferenceRef, }: Config) => ContextualLayerConfig;
|
|
41
|
+
export declare const useContextualLayer: ({ placement, verticalPlacement, visible, matchReferenceWidth, matchReferenceMinWidth, withArrow, referenceRef: externalReferenceRef, }: Config) => ContextualLayerConfig;
|
|
40
42
|
export {};
|
|
@@ -3,7 +3,19 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import { match, P } from "ts-pattern";
|
|
4
4
|
const MAX_OFFSET_FOR_CENTER_PLACEMENT = 100;
|
|
5
5
|
const HORIZONTAL_SAFETY_MARGIN = 16;
|
|
6
|
-
|
|
6
|
+
const getArrowPosition = (placement, referenceWidth, contentWidth) => {
|
|
7
|
+
if (placement === "center") {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
if (contentWidth <= referenceWidth) {
|
|
11
|
+
return placement;
|
|
12
|
+
}
|
|
13
|
+
const maxOffset = contentWidth / 2 - 12; // avoid arrow to be too close to the edge of the tooltip
|
|
14
|
+
const offset = (contentWidth - referenceWidth) / 2;
|
|
15
|
+
const arrowOffset = Math.min(offset, maxOffset);
|
|
16
|
+
return placement === "left" ? -arrowOffset : arrowOffset;
|
|
17
|
+
};
|
|
18
|
+
export const useContextualLayer = ({ placement, verticalPlacement, visible, matchReferenceWidth = false, matchReferenceMinWidth = false, withArrow = false, referenceRef: externalReferenceRef, }) => {
|
|
7
19
|
const referenceRef = useRef(null);
|
|
8
20
|
const contentRef = useRef(null);
|
|
9
21
|
const usedRef = externalReferenceRef !== null && externalReferenceRef !== void 0 ? externalReferenceRef : referenceRef;
|
|
@@ -53,6 +65,7 @@ export const useContextualLayer = ({ placement, verticalPlacement, visible, matc
|
|
|
53
65
|
.with("right", () => ({ right: window.innerWidth - rect.right }))
|
|
54
66
|
.with("center", () => ({ left: rect.left + width / 2, transform: "translateX(-50%)" }))
|
|
55
67
|
.exhaustive();
|
|
68
|
+
const arrowPosition = withArrow ? getArrowPosition(inferedPlacement, width, contentWidth) : 0;
|
|
56
69
|
const maxHeight = openAbove ? availableSpaceAbove : window.innerHeight - rect.top - height;
|
|
57
70
|
const rootStyle = {
|
|
58
71
|
position: "absolute",
|
|
@@ -80,10 +93,18 @@ export const useContextualLayer = ({ placement, verticalPlacement, visible, matc
|
|
|
80
93
|
return Option.Some({
|
|
81
94
|
rootStyle,
|
|
82
95
|
horizontalPosition: inferedPlacement,
|
|
96
|
+
arrowPosition,
|
|
83
97
|
verticalPosition: openAbove ? "top" : "bottom",
|
|
84
98
|
style,
|
|
85
99
|
});
|
|
86
|
-
}, [
|
|
100
|
+
}, [
|
|
101
|
+
placement,
|
|
102
|
+
verticalPlacement,
|
|
103
|
+
matchReferenceWidth,
|
|
104
|
+
matchReferenceMinWidth,
|
|
105
|
+
usedRef,
|
|
106
|
+
withArrow,
|
|
107
|
+
]);
|
|
87
108
|
useEffect(() => {
|
|
88
109
|
if (visible) {
|
|
89
110
|
setPosition(getPosition());
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useMemo, useState } from "react";
|
|
2
|
-
export const useDisclosure = (initialValue) => {
|
|
3
|
-
const [value, setValue] = useState(initialValue);
|
|
4
|
-
return [
|
|
5
|
-
value,
|
|
6
|
-
useMemo(() => ({
|
|
7
|
-
open: () => setValue(true),
|
|
8
|
-
close: () => setValue(false),
|
|
9
|
-
toggle: () => setValue(prevValue => !prevValue),
|
|
10
|
-
}), []),
|
|
11
|
-
];
|
|
12
|
-
};
|