@envive-ai/react-toolkit-v3 0.3.6 → 0.3.7
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/dist/AnimatedText/AnimatedText.d.cts +3 -3
- package/dist/AnimatedText/AnimatedText.d.ts +3 -3
- package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.cts +2 -2
- package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.ts +2 -2
- package/dist/Carousel/Carousel.d.cts +2 -2
- package/dist/Carousel/Carousel.d.ts +2 -2
- package/dist/ChatFooter/ChatFooter.d.cts +2 -2
- package/dist/ChatFooter/ChatFooter.d.ts +2 -2
- package/dist/ChatFooter/components/index.d.cts +5 -5
- package/dist/ChatFooter/components/index.d.ts +5 -5
- package/dist/ChatFooter/hooks/useGetContainerProperties.cjs +2 -2
- package/dist/ChatFooter/hooks/useGetContainerProperties.js +2 -2
- package/dist/ChatHeader/ChatHeader.cjs +3 -2
- package/dist/ChatHeader/ChatHeader.d.cts +3 -2
- package/dist/ChatHeader/ChatHeader.d.ts +3 -2
- package/dist/ChatHeader/ChatHeader.js +3 -2
- package/dist/ChatHeader/components/Handle.cjs +27 -1
- package/dist/ChatHeader/components/Handle.js +27 -1
- package/dist/ChatHeader/types/index.d.cts +2 -0
- package/dist/ChatHeader/types/index.d.ts +2 -0
- package/dist/ChatPreview/ChatPreview.d.cts +2 -2
- package/dist/ChatPreview/ChatPreview.d.ts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
- package/dist/Container/Container.d.cts +176 -176
- package/dist/Container/Container.d.ts +176 -176
- package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
- package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
- package/dist/FloatingButton/FloatingButton.cjs +2 -1
- package/dist/FloatingButton/FloatingButton.d.cts +4 -3
- package/dist/FloatingButton/FloatingButton.d.ts +4 -3
- package/dist/FloatingButton/FloatingButton.js +2 -1
- package/dist/FloatingButton/components/Container.cjs +2 -2
- package/dist/FloatingButton/components/Container.js +2 -2
- package/dist/FloatingButton/hooks/useGetContainerProperties.cjs +2 -2
- package/dist/FloatingButton/hooks/useGetContainerProperties.js +2 -2
- package/dist/FloatingButton/types/types.cjs +4 -4
- package/dist/FloatingButton/types/types.d.cts +8 -4
- package/dist/FloatingButton/types/types.d.ts +8 -4
- package/dist/FloatingButton/types/types.js +4 -4
- package/dist/FloatingChat/FloatingChat.cjs +106 -39
- package/dist/FloatingChat/FloatingChat.d.cts +3 -2
- package/dist/FloatingChat/FloatingChat.d.ts +3 -2
- package/dist/FloatingChat/FloatingChat.js +108 -41
- package/dist/FloatingChat/components/AgentMessage.cjs +3 -2
- package/dist/FloatingChat/components/AgentMessage.js +3 -2
- package/dist/FloatingChat/components/ChatMessages.cjs +59 -41
- package/dist/FloatingChat/components/ChatMessages.js +58 -40
- package/dist/FloatingChat/components/Layout.cjs +2 -2
- package/dist/FloatingChat/components/Layout.js +2 -2
- package/dist/FloatingChat/components/ModalSheet.cjs +184 -0
- package/dist/FloatingChat/components/ModalSheet.js +182 -0
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.cjs +3 -2
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.js +3 -2
- package/dist/FloatingChat/components/index.cjs +1 -0
- package/dist/FloatingChat/components/index.js +1 -0
- package/dist/FloatingChat/hooks/useChatSuggestions.cjs +25 -0
- package/dist/FloatingChat/hooks/useChatSuggestions.js +24 -0
- package/dist/FloatingChat/hooks/useFilteredChatMessages.cjs +24 -0
- package/dist/FloatingChat/hooks/useFilteredChatMessages.js +23 -0
- package/dist/FloatingChat/hooks/usePreventScroll.cjs +117 -0
- package/dist/FloatingChat/hooks/usePreventScroll.js +116 -0
- package/dist/FloatingChat/hooks/useSnapCalculator.cjs +37 -0
- package/dist/FloatingChat/hooks/useSnapCalculator.js +35 -0
- package/dist/FloatingChat/hooks/useSnapControl.cjs +82 -0
- package/dist/FloatingChat/hooks/useSnapControl.js +81 -0
- package/dist/FloatingChat/hooks/useSnapSetup.cjs +59 -0
- package/dist/FloatingChat/hooks/useSnapSetup.js +58 -0
- package/dist/FloatingChat/types/types.d.cts +4 -0
- package/dist/FloatingChat/types/types.d.ts +4 -0
- package/dist/Image/Image.d.cts +2 -2
- package/dist/Image/Image.d.ts +2 -2
- package/dist/ImageGallery/ImageGallery.d.cts +2 -2
- package/dist/ImageGallery/ImageGallery.d.ts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
- package/dist/PromptButton/PromptButton.d.cts +2 -2
- package/dist/PromptButton/PromptButton.d.ts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
- package/dist/PromptCarousel/PromptCarousel.cjs +0 -1
- package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
- package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
- package/dist/PromptCarousel/PromptCarousel.js +0 -1
- package/dist/ReviewCard/ReviewCard.d.cts +2 -2
- package/dist/ReviewCard/ReviewCard.d.ts +2 -2
- package/dist/ReviewCard/components/index.d.cts +6 -6
- package/dist/ReviewCard/components/index.d.ts +6 -6
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
- package/dist/SalesAgentProductCard/components/index.d.cts +2 -2
- package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
- package/dist/SocialProof/SocialProof.cjs +9 -2
- package/dist/SocialProof/SocialProof.d.cts +2 -2
- package/dist/SocialProof/SocialProof.d.ts +2 -2
- package/dist/SocialProof/SocialProof.js +9 -2
- package/dist/SocialProof/hooks/index.cjs +1 -0
- package/dist/SocialProof/hooks/index.js +3 -0
- package/dist/SocialProof/hooks/useSocialProofCount.cjs +48 -0
- package/dist/SocialProof/hooks/useSocialProofCount.d.cts +15 -0
- package/dist/SocialProof/hooks/useSocialProofCount.d.ts +15 -0
- package/dist/SocialProof/hooks/useSocialProofCount.js +46 -0
- package/dist/SocialProof/index.cjs +5 -1
- package/dist/SocialProof/index.d.cts +3 -2
- package/dist/SocialProof/index.d.ts +3 -2
- package/dist/SocialProof/index.js +4 -2
- package/dist/SocialProof/types/types.cjs +8 -1
- package/dist/SocialProof/types/types.d.cts +16 -6
- package/dist/SocialProof/types/types.d.ts +16 -6
- package/dist/SocialProof/types/types.js +7 -1
- package/dist/Stack/Stack.d.cts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
- package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
- package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
- package/dist/Typography/Typography.d.cts +4 -4
- package/dist/Typography/Typography.d.ts +4 -4
- package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
- package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
- package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
- package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
- package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ChatFooter/hooks/useGetContainerProperties.ts +2 -2
- package/src/components/ChatHeader/ChatHeader.tsx +2 -0
- package/src/components/ChatHeader/components/Handle.tsx +29 -1
- package/src/components/ChatHeader/types/index.ts +3 -0
- package/src/components/FloatingButton/FloatingButton.tsx +2 -0
- package/src/components/FloatingButton/components/Container.tsx +3 -0
- package/src/components/FloatingButton/hooks/useGetContainerProperties.ts +2 -1
- package/src/components/FloatingButton/types/types.ts +9 -4
- package/src/components/FloatingChat/FloatingChat.tsx +160 -59
- package/src/components/FloatingChat/components/AgentMessage.tsx +3 -0
- package/src/components/FloatingChat/components/ChatMessages.tsx +25 -0
- package/src/components/FloatingChat/components/Layout.tsx +2 -2
- package/src/components/FloatingChat/components/ModalSheet.tsx +288 -0
- package/src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx +7 -2
- package/src/components/FloatingChat/components/index.ts +3 -0
- package/src/components/FloatingChat/hooks/useChatSuggestions.ts +49 -0
- package/src/components/FloatingChat/hooks/useFilteredChatMessages.ts +43 -0
- package/src/components/FloatingChat/hooks/usePreventScroll.ts +207 -0
- package/src/components/FloatingChat/hooks/useSnapCalculator.ts +41 -0
- package/src/components/FloatingChat/hooks/useSnapControl.ts +131 -0
- package/src/components/FloatingChat/hooks/useSnapSetup.ts +106 -0
- package/src/components/FloatingChat/types/types.ts +4 -0
- package/src/components/PromptCarousel/PromptCarousel.tsx +0 -1
- package/src/components/SocialProof/SocialProof.tsx +8 -2
- package/src/components/SocialProof/__tests__/SocialProof.test.tsx +66 -17
- package/src/components/SocialProof/hooks/index.ts +2 -0
- package/src/components/SocialProof/hooks/useSocialProofCount.ts +67 -0
- package/src/components/SocialProof/index.ts +2 -1
- package/src/components/SocialProof/types/types.ts +18 -6
|
@@ -5,14 +5,15 @@ import { SalesAgentProductCard } from "../../SalesAgentProductCard/SalesAgentPro
|
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx
|
|
8
|
-
const SalesAgentProductCardsCarousel = ({ products, theme, hideNavigation = false, numberOfProducts }) => {
|
|
8
|
+
const SalesAgentProductCardsCarousel = ({ products, theme, hideNavigation = false, numberOfProducts, variant = SalesAgentProductCardVariant.LARGE, isPartialView = false }) => {
|
|
9
9
|
const finalTheme = resolveTheme(theme);
|
|
10
|
+
const finalVariant = isPartialView ? SalesAgentProductCardVariant.SMALL : variant;
|
|
10
11
|
const forceShowCurrentPriceSpace = products.some((product) => product.currentPrice && product.previousPrice !== product.currentPrice);
|
|
11
12
|
return /* @__PURE__ */ jsx(Carousel, {
|
|
12
13
|
hideNavigation,
|
|
13
14
|
badgeLabel: numberOfProducts && numberOfProducts > 1 ? `${numberOfProducts} Products` : void 0,
|
|
14
15
|
elements: products.map((product) => /* @__PURE__ */ jsx(SalesAgentProductCard, {
|
|
15
|
-
variant:
|
|
16
|
+
variant: finalVariant,
|
|
16
17
|
productName: product.productName,
|
|
17
18
|
currentPrice: product.currentPrice,
|
|
18
19
|
previousPrice: product.previousPrice,
|
|
@@ -8,6 +8,7 @@ const require_AgentMessage = require('./AgentMessage.cjs');
|
|
|
8
8
|
const require_MessageDivider = require('./MessageDivider.cjs');
|
|
9
9
|
const require_ChatMessages = require('./ChatMessages.cjs');
|
|
10
10
|
const require_ScrollToBottomButton = require('./ScrollToBottomButton.cjs');
|
|
11
|
+
const require_ModalSheet = require('./ModalSheet.cjs');
|
|
11
12
|
|
|
12
13
|
//#region src/components/FloatingChat/components/index.ts
|
|
13
14
|
const FloatingChatComponents = {
|
|
@@ -8,6 +8,7 @@ import { AgentMessage } from "./AgentMessage.js";
|
|
|
8
8
|
import { MessageDivider } from "./MessageDivider.js";
|
|
9
9
|
import { ChatMessages } from "./ChatMessages.js";
|
|
10
10
|
import { ScrollToBottomButton } from "./ScrollToBottomButton.js";
|
|
11
|
+
import { ModalSheet } from "./ModalSheet.js";
|
|
11
12
|
|
|
12
13
|
//#region src/components/FloatingChat/components/index.ts
|
|
13
14
|
const FloatingChatComponents = {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
|
|
4
|
+
//#region src/components/FloatingChat/hooks/useChatSuggestions.ts
|
|
5
|
+
const useChatSuggestions = ({ suggestions, isPendingResponse, isResponseStreaming }) => {
|
|
6
|
+
const [answerSuggestions, setAnswerSuggestions] = (0, react.useState)([]);
|
|
7
|
+
const [generalSuggestions, setGeneralSuggestions] = (0, react.useState)([]);
|
|
8
|
+
const showAnswerSuggestions = answerSuggestions.length > 0 && !isPendingResponse && !isResponseStreaming;
|
|
9
|
+
(0, react.useEffect)(() => {
|
|
10
|
+
if (suggestions.length > 0) {
|
|
11
|
+
setAnswerSuggestions(suggestions.filter((suggestion) => suggestion.isAnswer).map((suggestion) => suggestion.content));
|
|
12
|
+
setGeneralSuggestions(suggestions.filter((suggestion) => !suggestion.isAnswer).map((suggestion) => suggestion.content));
|
|
13
|
+
}
|
|
14
|
+
}, [suggestions]);
|
|
15
|
+
return {
|
|
16
|
+
answerSuggestions,
|
|
17
|
+
generalSuggestions,
|
|
18
|
+
showAnswerSuggestions,
|
|
19
|
+
setAnswerSuggestions,
|
|
20
|
+
setGeneralSuggestions
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
exports.useChatSuggestions = useChatSuggestions;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/FloatingChat/hooks/useChatSuggestions.ts
|
|
4
|
+
const useChatSuggestions = ({ suggestions, isPendingResponse, isResponseStreaming }) => {
|
|
5
|
+
const [answerSuggestions, setAnswerSuggestions] = useState([]);
|
|
6
|
+
const [generalSuggestions, setGeneralSuggestions] = useState([]);
|
|
7
|
+
const showAnswerSuggestions = answerSuggestions.length > 0 && !isPendingResponse && !isResponseStreaming;
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (suggestions.length > 0) {
|
|
10
|
+
setAnswerSuggestions(suggestions.filter((suggestion) => suggestion.isAnswer).map((suggestion) => suggestion.content));
|
|
11
|
+
setGeneralSuggestions(suggestions.filter((suggestion) => !suggestion.isAnswer).map((suggestion) => suggestion.content));
|
|
12
|
+
}
|
|
13
|
+
}, [suggestions]);
|
|
14
|
+
return {
|
|
15
|
+
answerSuggestions,
|
|
16
|
+
generalSuggestions,
|
|
17
|
+
showAnswerSuggestions,
|
|
18
|
+
setAnswerSuggestions,
|
|
19
|
+
setGeneralSuggestions
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { useChatSuggestions };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
let __envive_ai_react_hooks_hooks_MessageFilter = require("@envive-ai/react-hooks/hooks/MessageFilter");
|
|
4
|
+
|
|
5
|
+
//#region src/components/FloatingChat/hooks/useFilteredChatMessages.ts
|
|
6
|
+
const useFilteredChatMessages = ({ messages, isMobile, currentSnapPercentage, modalSheetControl }) => {
|
|
7
|
+
const { getFilteredMessages } = (0, __envive_ai_react_hooks_hooks_MessageFilter.useMessageFilter)();
|
|
8
|
+
const keepMessagesExpanded = !isMobile || isMobile && currentSnapPercentage === 100;
|
|
9
|
+
const filteredMessages = (0, react.useMemo)(() => getFilteredMessages(messages, keepMessagesExpanded), [
|
|
10
|
+
getFilteredMessages,
|
|
11
|
+
messages,
|
|
12
|
+
keepMessagesExpanded
|
|
13
|
+
]);
|
|
14
|
+
const hasFilteredMessages = filteredMessages.length !== messages.length && isMobile;
|
|
15
|
+
const handlePreviousDiscussions = () => modalSheetControl.current?.jumpToSnap(2);
|
|
16
|
+
return {
|
|
17
|
+
filteredMessages,
|
|
18
|
+
hasFilteredMessages,
|
|
19
|
+
handlePreviousDiscussions
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
exports.useFilteredChatMessages = useFilteredChatMessages;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useMessageFilter } from "@envive-ai/react-hooks/hooks/MessageFilter";
|
|
3
|
+
|
|
4
|
+
//#region src/components/FloatingChat/hooks/useFilteredChatMessages.ts
|
|
5
|
+
const useFilteredChatMessages = ({ messages, isMobile, currentSnapPercentage, modalSheetControl }) => {
|
|
6
|
+
const { getFilteredMessages } = useMessageFilter();
|
|
7
|
+
const keepMessagesExpanded = !isMobile || isMobile && currentSnapPercentage === 100;
|
|
8
|
+
const filteredMessages = useMemo(() => getFilteredMessages(messages, keepMessagesExpanded), [
|
|
9
|
+
getFilteredMessages,
|
|
10
|
+
messages,
|
|
11
|
+
keepMessagesExpanded
|
|
12
|
+
]);
|
|
13
|
+
const hasFilteredMessages = filteredMessages.length !== messages.length && isMobile;
|
|
14
|
+
const handlePreviousDiscussions = () => modalSheetControl.current?.jumpToSnap(2);
|
|
15
|
+
return {
|
|
16
|
+
filteredMessages,
|
|
17
|
+
hasFilteredMessages,
|
|
18
|
+
handlePreviousDiscussions
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { useFilteredChatMessages };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
|
|
4
|
+
//#region src/components/FloatingChat/hooks/usePreventScroll.ts
|
|
5
|
+
/**
|
|
6
|
+
* Prevent the body element from scrolling when a modal (partial view) is open.
|
|
7
|
+
*
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
const usePreventScroll = () => {
|
|
11
|
+
const gestureRef = (0, react.useRef)(null);
|
|
12
|
+
/**
|
|
13
|
+
* Calculate the angle of a user gesture (grab/drop).
|
|
14
|
+
*
|
|
15
|
+
* @param startX
|
|
16
|
+
* @param startY
|
|
17
|
+
* @param endX
|
|
18
|
+
* @param endY
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
const calculateAngle = (startX, startY, endX, endY) => {
|
|
22
|
+
const deltaX = endX - startX;
|
|
23
|
+
const deltaY = endY - startY;
|
|
24
|
+
return (Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 360) % 360;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Test if an element has scrollable capabilities.
|
|
28
|
+
*
|
|
29
|
+
* @param node
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
const isScrollable = (node) => {
|
|
33
|
+
const style = window.getComputedStyle(node);
|
|
34
|
+
return /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Find the parent node that has scrollable capabilities.
|
|
38
|
+
*
|
|
39
|
+
* @param node
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
const getScrollParent = (node, ignoreCurrentNode = false) => {
|
|
43
|
+
let parentNode = ignoreCurrentNode ? node?.parentElement : node;
|
|
44
|
+
if (!parentNode) return null;
|
|
45
|
+
if (isScrollable(parentNode)) return parentNode;
|
|
46
|
+
while (parentNode && !isScrollable(parentNode)) parentNode = parentNode.parentElement;
|
|
47
|
+
if (!parentNode && isScrollable(document.body)) return document.body;
|
|
48
|
+
return parentNode || document.scrollingElement || document.documentElement;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Get the scrollable directions an element can scroll.
|
|
52
|
+
*
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
const getScrollDirections = (scrollableElement) => {
|
|
56
|
+
const horizontalScroll = (scrollableElement?.scrollWidth || 0) > (scrollableElement?.clientWidth || 0);
|
|
57
|
+
const verticalScroll = (scrollableElement?.scrollHeight || 0) > (scrollableElement?.clientHeight || 0);
|
|
58
|
+
const scrollDirections = [];
|
|
59
|
+
if (horizontalScroll) scrollDirections.push("horizontal");
|
|
60
|
+
if (verticalScroll) scrollDirections.push("vertical");
|
|
61
|
+
return scrollDirections;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Determine the direction of a gesture event based on the angle of a grab/drop event.
|
|
65
|
+
*
|
|
66
|
+
* @param fingerX
|
|
67
|
+
* @param fingerY
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
const getGestureDirection = (fingerX, fingerY) => {
|
|
71
|
+
const directionAngle = calculateAngle(gestureRef?.current?.event?.clientX || 0, gestureRef?.current?.event?.clientY || 0, fingerX, fingerY);
|
|
72
|
+
if (directionAngle < 45 || directionAngle > 315) return "right";
|
|
73
|
+
if (directionAngle > 45 && directionAngle < 135) return "down";
|
|
74
|
+
if (directionAngle > 135 && directionAngle < 225) return "left";
|
|
75
|
+
return "up";
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Determine whether the direction of the gesture can scroll the element in context.
|
|
79
|
+
*
|
|
80
|
+
* @param param0
|
|
81
|
+
* @param direction
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
const isScrollDirectionAllowed = ({ element, scrollableDirections }, direction) => {
|
|
85
|
+
if (element?.tagName === "BODY" || element?.tagName === "HTML" || scrollableDirections?.length === 0) return false;
|
|
86
|
+
const { clientHeight = 0, clientWidth = 0, scrollHeight = 0, scrollWidth = 0, scrollTop = 0, scrollLeft = 0 } = element || {};
|
|
87
|
+
const atTop = scrollTop === 0;
|
|
88
|
+
const atLeft = scrollLeft === 0;
|
|
89
|
+
const atBottom = 100 / scrollHeight * (scrollTop + clientHeight) > 99.9;
|
|
90
|
+
const atRight = 100 / scrollWidth * (scrollLeft + clientWidth) > 99.9;
|
|
91
|
+
const verticalScrollBlocked = atBottom && direction === "up" || atTop && direction === "down" || direction === "left" || direction === "right";
|
|
92
|
+
if (scrollableDirections?.includes("vertical") && verticalScrollBlocked) return false;
|
|
93
|
+
const horizontalScrollBlocked = atRight && direction === "left" || atLeft && direction === "right" || direction === "up" || direction === "down";
|
|
94
|
+
if (scrollableDirections?.includes("horizontal") && horizontalScrollBlocked) return false;
|
|
95
|
+
return true;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Test if the selected scrollable element can scroll in the direction of the grab/drop event.
|
|
99
|
+
*
|
|
100
|
+
* @param direction
|
|
101
|
+
* @returns
|
|
102
|
+
*/
|
|
103
|
+
const isScrollableArea = (direction) => {
|
|
104
|
+
const { scrollableElements } = gestureRef.current || {};
|
|
105
|
+
return scrollableElements?.some((el) => isScrollDirectionAllowed(el, direction));
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
gestureRef,
|
|
109
|
+
getScrollParent,
|
|
110
|
+
isScrollableArea,
|
|
111
|
+
getGestureDirection,
|
|
112
|
+
getScrollDirections
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
exports.usePreventScroll = usePreventScroll;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useRef } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/FloatingChat/hooks/usePreventScroll.ts
|
|
4
|
+
/**
|
|
5
|
+
* Prevent the body element from scrolling when a modal (partial view) is open.
|
|
6
|
+
*
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
const usePreventScroll = () => {
|
|
10
|
+
const gestureRef = useRef(null);
|
|
11
|
+
/**
|
|
12
|
+
* Calculate the angle of a user gesture (grab/drop).
|
|
13
|
+
*
|
|
14
|
+
* @param startX
|
|
15
|
+
* @param startY
|
|
16
|
+
* @param endX
|
|
17
|
+
* @param endY
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
const calculateAngle = (startX, startY, endX, endY) => {
|
|
21
|
+
const deltaX = endX - startX;
|
|
22
|
+
const deltaY = endY - startY;
|
|
23
|
+
return (Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 360) % 360;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Test if an element has scrollable capabilities.
|
|
27
|
+
*
|
|
28
|
+
* @param node
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
const isScrollable = (node) => {
|
|
32
|
+
const style = window.getComputedStyle(node);
|
|
33
|
+
return /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Find the parent node that has scrollable capabilities.
|
|
37
|
+
*
|
|
38
|
+
* @param node
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
41
|
+
const getScrollParent = (node, ignoreCurrentNode = false) => {
|
|
42
|
+
let parentNode = ignoreCurrentNode ? node?.parentElement : node;
|
|
43
|
+
if (!parentNode) return null;
|
|
44
|
+
if (isScrollable(parentNode)) return parentNode;
|
|
45
|
+
while (parentNode && !isScrollable(parentNode)) parentNode = parentNode.parentElement;
|
|
46
|
+
if (!parentNode && isScrollable(document.body)) return document.body;
|
|
47
|
+
return parentNode || document.scrollingElement || document.documentElement;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Get the scrollable directions an element can scroll.
|
|
51
|
+
*
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
const getScrollDirections = (scrollableElement) => {
|
|
55
|
+
const horizontalScroll = (scrollableElement?.scrollWidth || 0) > (scrollableElement?.clientWidth || 0);
|
|
56
|
+
const verticalScroll = (scrollableElement?.scrollHeight || 0) > (scrollableElement?.clientHeight || 0);
|
|
57
|
+
const scrollDirections = [];
|
|
58
|
+
if (horizontalScroll) scrollDirections.push("horizontal");
|
|
59
|
+
if (verticalScroll) scrollDirections.push("vertical");
|
|
60
|
+
return scrollDirections;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Determine the direction of a gesture event based on the angle of a grab/drop event.
|
|
64
|
+
*
|
|
65
|
+
* @param fingerX
|
|
66
|
+
* @param fingerY
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
const getGestureDirection = (fingerX, fingerY) => {
|
|
70
|
+
const directionAngle = calculateAngle(gestureRef?.current?.event?.clientX || 0, gestureRef?.current?.event?.clientY || 0, fingerX, fingerY);
|
|
71
|
+
if (directionAngle < 45 || directionAngle > 315) return "right";
|
|
72
|
+
if (directionAngle > 45 && directionAngle < 135) return "down";
|
|
73
|
+
if (directionAngle > 135 && directionAngle < 225) return "left";
|
|
74
|
+
return "up";
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Determine whether the direction of the gesture can scroll the element in context.
|
|
78
|
+
*
|
|
79
|
+
* @param param0
|
|
80
|
+
* @param direction
|
|
81
|
+
* @returns
|
|
82
|
+
*/
|
|
83
|
+
const isScrollDirectionAllowed = ({ element, scrollableDirections }, direction) => {
|
|
84
|
+
if (element?.tagName === "BODY" || element?.tagName === "HTML" || scrollableDirections?.length === 0) return false;
|
|
85
|
+
const { clientHeight = 0, clientWidth = 0, scrollHeight = 0, scrollWidth = 0, scrollTop = 0, scrollLeft = 0 } = element || {};
|
|
86
|
+
const atTop = scrollTop === 0;
|
|
87
|
+
const atLeft = scrollLeft === 0;
|
|
88
|
+
const atBottom = 100 / scrollHeight * (scrollTop + clientHeight) > 99.9;
|
|
89
|
+
const atRight = 100 / scrollWidth * (scrollLeft + clientWidth) > 99.9;
|
|
90
|
+
const verticalScrollBlocked = atBottom && direction === "up" || atTop && direction === "down" || direction === "left" || direction === "right";
|
|
91
|
+
if (scrollableDirections?.includes("vertical") && verticalScrollBlocked) return false;
|
|
92
|
+
const horizontalScrollBlocked = atRight && direction === "left" || atLeft && direction === "right" || direction === "up" || direction === "down";
|
|
93
|
+
if (scrollableDirections?.includes("horizontal") && horizontalScrollBlocked) return false;
|
|
94
|
+
return true;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Test if the selected scrollable element can scroll in the direction of the grab/drop event.
|
|
98
|
+
*
|
|
99
|
+
* @param direction
|
|
100
|
+
* @returns
|
|
101
|
+
*/
|
|
102
|
+
const isScrollableArea = (direction) => {
|
|
103
|
+
const { scrollableElements } = gestureRef.current || {};
|
|
104
|
+
return scrollableElements?.some((el) => isScrollDirectionAllowed(el, direction));
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
gestureRef,
|
|
108
|
+
getScrollParent,
|
|
109
|
+
isScrollableArea,
|
|
110
|
+
getGestureDirection,
|
|
111
|
+
getScrollDirections
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
export { usePreventScroll };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
|
|
4
|
+
//#region src/components/FloatingChat/hooks/useSnapCalculator.ts
|
|
5
|
+
let Unit = /* @__PURE__ */ function(Unit$1) {
|
|
6
|
+
Unit$1["PERCENT"] = "percent";
|
|
7
|
+
Unit$1["PIXEL"] = "pixel";
|
|
8
|
+
return Unit$1;
|
|
9
|
+
}({});
|
|
10
|
+
const useSnapCalculator = (snaps, maxHeight, unit) => {
|
|
11
|
+
const viewportHeightPx = document.documentElement.clientHeight;
|
|
12
|
+
const swipeviewHeightPx = unit === Unit.PERCENT ? Math.floor(viewportHeightPx * (maxHeight / 100)) : maxHeight;
|
|
13
|
+
const snapsToPixels = (0, react.useMemo)(() => snaps?.map((snap) => Math.abs((unit === Unit.PERCENT ? Math.floor(swipeviewHeightPx * (snap / 100)) : snap) - swipeviewHeightPx)), [
|
|
14
|
+
swipeviewHeightPx,
|
|
15
|
+
unit,
|
|
16
|
+
snaps
|
|
17
|
+
]);
|
|
18
|
+
const getPixelToSnap = (pixels) => {
|
|
19
|
+
const snapIdx = snapsToPixels?.indexOf(pixels) || 0;
|
|
20
|
+
return snaps?.[snapIdx] || 0;
|
|
21
|
+
};
|
|
22
|
+
const getSnapToPixel = (snap) => {
|
|
23
|
+
const snapIdx = snaps?.indexOf(snap) || 0;
|
|
24
|
+
return snapsToPixels?.[snapIdx] || 0;
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
viewportHeightPx,
|
|
28
|
+
snapsToPixels,
|
|
29
|
+
swipeviewHeightPx,
|
|
30
|
+
getPixelToSnap,
|
|
31
|
+
getSnapToPixel
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.Unit = Unit;
|
|
37
|
+
exports.useSnapCalculator = useSnapCalculator;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/FloatingChat/hooks/useSnapCalculator.ts
|
|
4
|
+
let Unit = /* @__PURE__ */ function(Unit$1) {
|
|
5
|
+
Unit$1["PERCENT"] = "percent";
|
|
6
|
+
Unit$1["PIXEL"] = "pixel";
|
|
7
|
+
return Unit$1;
|
|
8
|
+
}({});
|
|
9
|
+
const useSnapCalculator = (snaps, maxHeight, unit) => {
|
|
10
|
+
const viewportHeightPx = document.documentElement.clientHeight;
|
|
11
|
+
const swipeviewHeightPx = unit === Unit.PERCENT ? Math.floor(viewportHeightPx * (maxHeight / 100)) : maxHeight;
|
|
12
|
+
const snapsToPixels = useMemo(() => snaps?.map((snap) => Math.abs((unit === Unit.PERCENT ? Math.floor(swipeviewHeightPx * (snap / 100)) : snap) - swipeviewHeightPx)), [
|
|
13
|
+
swipeviewHeightPx,
|
|
14
|
+
unit,
|
|
15
|
+
snaps
|
|
16
|
+
]);
|
|
17
|
+
const getPixelToSnap = (pixels) => {
|
|
18
|
+
const snapIdx = snapsToPixels?.indexOf(pixels) || 0;
|
|
19
|
+
return snaps?.[snapIdx] || 0;
|
|
20
|
+
};
|
|
21
|
+
const getSnapToPixel = (snap) => {
|
|
22
|
+
const snapIdx = snaps?.indexOf(snap) || 0;
|
|
23
|
+
return snapsToPixels?.[snapIdx] || 0;
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
viewportHeightPx,
|
|
27
|
+
snapsToPixels,
|
|
28
|
+
swipeviewHeightPx,
|
|
29
|
+
getPixelToSnap,
|
|
30
|
+
getSnapToPixel
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { Unit, useSnapCalculator };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_useSnapCalculator = require('./useSnapCalculator.cjs');
|
|
3
|
+
let react = require("react");
|
|
4
|
+
let framer_motion = require("framer-motion");
|
|
5
|
+
|
|
6
|
+
//#region src/components/FloatingChat/hooks/useSnapControl.ts
|
|
7
|
+
const MIDDLE_SNAP_OFFSET = 5;
|
|
8
|
+
const useSnapControl = ({ animationKey, animation, height, unit, snaps, initSnap, onSnapComplete, overlayOpacity }) => {
|
|
9
|
+
const [scope, animate] = (0, framer_motion.useAnimate)();
|
|
10
|
+
const defaultAnimationKey = (0, framer_motion.useMotionValue)(-1);
|
|
11
|
+
const animatedY = animationKey || defaultAnimationKey;
|
|
12
|
+
const { swipeviewHeightPx, snapsToPixels, getPixelToSnap, getSnapToPixel } = require_useSnapCalculator.useSnapCalculator(snaps, height, unit);
|
|
13
|
+
const contentHeight = (0, framer_motion.useTransform)(animatedY, [0, swipeviewHeightPx], [swipeviewHeightPx, 0]);
|
|
14
|
+
const snapOverlayReference = (0, react.useMemo)(() => [
|
|
15
|
+
getSnapToPixel(snaps[0]),
|
|
16
|
+
getSnapToPixel(snaps[1]) - MIDDLE_SNAP_OFFSET,
|
|
17
|
+
getSnapToPixel(snaps[2])
|
|
18
|
+
], [getSnapToPixel, snaps]);
|
|
19
|
+
const displayOverlay = (0, framer_motion.useTransform)(() => animatedY.get() === -1 ? "none" : (0, framer_motion.transform)(animatedY.get(), snapOverlayReference, [
|
|
20
|
+
"none",
|
|
21
|
+
"none",
|
|
22
|
+
"block"
|
|
23
|
+
]));
|
|
24
|
+
const opacityOverlay = (0, framer_motion.useTransform)(() => animatedY.get() === -1 ? 0 : (0, framer_motion.transform)(animatedY.get(), snapOverlayReference, [
|
|
25
|
+
0,
|
|
26
|
+
0,
|
|
27
|
+
overlayOpacity
|
|
28
|
+
]));
|
|
29
|
+
const initSnapInPixels = snapsToPixels?.[initSnap];
|
|
30
|
+
const getInitSnap = () => snaps?.[initSnap];
|
|
31
|
+
const [currentSnap, setCurrentSnap] = (0, react.useState)(getInitSnap());
|
|
32
|
+
const defineNextSnapByPosition = () => {
|
|
33
|
+
const currentY = animatedY.get();
|
|
34
|
+
let closestSnap = snapsToPixels[0];
|
|
35
|
+
let minDistance = Math.abs(currentY - snapsToPixels[0]);
|
|
36
|
+
snapsToPixels.forEach((snapPx) => {
|
|
37
|
+
const distance = Math.abs(currentY - snapPx);
|
|
38
|
+
if (distance < minDistance) {
|
|
39
|
+
minDistance = distance;
|
|
40
|
+
closestSnap = snapPx;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return closestSnap;
|
|
44
|
+
};
|
|
45
|
+
const jumpTo = (snapPx) => {
|
|
46
|
+
const collapsed = snapPx === swipeviewHeightPx;
|
|
47
|
+
const nextSnap = getPixelToSnap(snapPx);
|
|
48
|
+
animate(scope.current, { y: snapPx }, {
|
|
49
|
+
...animation,
|
|
50
|
+
onComplete: () => {
|
|
51
|
+
onSnapComplete(currentSnap, nextSnap, collapsed);
|
|
52
|
+
setCurrentSnap(nextSnap);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
nextSnap,
|
|
57
|
+
collapsed
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const resetControls = () => {
|
|
61
|
+
setCurrentSnap(getInitSnap());
|
|
62
|
+
return 0;
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
scope,
|
|
66
|
+
animatedY,
|
|
67
|
+
animate,
|
|
68
|
+
swipeviewHeightPx,
|
|
69
|
+
initSnapInPixels,
|
|
70
|
+
contentHeight,
|
|
71
|
+
currentSnap,
|
|
72
|
+
displayOverlay,
|
|
73
|
+
opacityOverlay,
|
|
74
|
+
getSnapToPixel,
|
|
75
|
+
jumpTo,
|
|
76
|
+
defineNextSnapByPosition,
|
|
77
|
+
resetControls
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
exports.useSnapControl = useSnapControl;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useSnapCalculator } from "./useSnapCalculator.js";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { transform, useAnimate, useMotionValue, useTransform } from "framer-motion";
|
|
4
|
+
|
|
5
|
+
//#region src/components/FloatingChat/hooks/useSnapControl.ts
|
|
6
|
+
const MIDDLE_SNAP_OFFSET = 5;
|
|
7
|
+
const useSnapControl = ({ animationKey, animation, height, unit, snaps, initSnap, onSnapComplete, overlayOpacity }) => {
|
|
8
|
+
const [scope, animate] = useAnimate();
|
|
9
|
+
const defaultAnimationKey = useMotionValue(-1);
|
|
10
|
+
const animatedY = animationKey || defaultAnimationKey;
|
|
11
|
+
const { swipeviewHeightPx, snapsToPixels, getPixelToSnap, getSnapToPixel } = useSnapCalculator(snaps, height, unit);
|
|
12
|
+
const contentHeight = useTransform(animatedY, [0, swipeviewHeightPx], [swipeviewHeightPx, 0]);
|
|
13
|
+
const snapOverlayReference = useMemo(() => [
|
|
14
|
+
getSnapToPixel(snaps[0]),
|
|
15
|
+
getSnapToPixel(snaps[1]) - MIDDLE_SNAP_OFFSET,
|
|
16
|
+
getSnapToPixel(snaps[2])
|
|
17
|
+
], [getSnapToPixel, snaps]);
|
|
18
|
+
const displayOverlay = useTransform(() => animatedY.get() === -1 ? "none" : transform(animatedY.get(), snapOverlayReference, [
|
|
19
|
+
"none",
|
|
20
|
+
"none",
|
|
21
|
+
"block"
|
|
22
|
+
]));
|
|
23
|
+
const opacityOverlay = useTransform(() => animatedY.get() === -1 ? 0 : transform(animatedY.get(), snapOverlayReference, [
|
|
24
|
+
0,
|
|
25
|
+
0,
|
|
26
|
+
overlayOpacity
|
|
27
|
+
]));
|
|
28
|
+
const initSnapInPixels = snapsToPixels?.[initSnap];
|
|
29
|
+
const getInitSnap = () => snaps?.[initSnap];
|
|
30
|
+
const [currentSnap, setCurrentSnap] = useState(getInitSnap());
|
|
31
|
+
const defineNextSnapByPosition = () => {
|
|
32
|
+
const currentY = animatedY.get();
|
|
33
|
+
let closestSnap = snapsToPixels[0];
|
|
34
|
+
let minDistance = Math.abs(currentY - snapsToPixels[0]);
|
|
35
|
+
snapsToPixels.forEach((snapPx) => {
|
|
36
|
+
const distance = Math.abs(currentY - snapPx);
|
|
37
|
+
if (distance < minDistance) {
|
|
38
|
+
minDistance = distance;
|
|
39
|
+
closestSnap = snapPx;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return closestSnap;
|
|
43
|
+
};
|
|
44
|
+
const jumpTo = (snapPx) => {
|
|
45
|
+
const collapsed = snapPx === swipeviewHeightPx;
|
|
46
|
+
const nextSnap = getPixelToSnap(snapPx);
|
|
47
|
+
animate(scope.current, { y: snapPx }, {
|
|
48
|
+
...animation,
|
|
49
|
+
onComplete: () => {
|
|
50
|
+
onSnapComplete(currentSnap, nextSnap, collapsed);
|
|
51
|
+
setCurrentSnap(nextSnap);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
nextSnap,
|
|
56
|
+
collapsed
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const resetControls = () => {
|
|
60
|
+
setCurrentSnap(getInitSnap());
|
|
61
|
+
return 0;
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
scope,
|
|
65
|
+
animatedY,
|
|
66
|
+
animate,
|
|
67
|
+
swipeviewHeightPx,
|
|
68
|
+
initSnapInPixels,
|
|
69
|
+
contentHeight,
|
|
70
|
+
currentSnap,
|
|
71
|
+
displayOverlay,
|
|
72
|
+
opacityOverlay,
|
|
73
|
+
getSnapToPixel,
|
|
74
|
+
jumpTo,
|
|
75
|
+
defineNextSnapByPosition,
|
|
76
|
+
resetControls
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
export { useSnapControl };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_useCheckIsMobile = require('../../utils/useCheckIsMobile.cjs');
|
|
3
|
+
let react = require("react");
|
|
4
|
+
let framer_motion = require("framer-motion");
|
|
5
|
+
|
|
6
|
+
//#region src/components/FloatingChat/hooks/useSnapSetup.ts
|
|
7
|
+
const useSnapSetup = ({ isFloatingChatOpen }) => {
|
|
8
|
+
const maxSwipeableViewHeight = 89;
|
|
9
|
+
const modalSheetControl = (0, react.useRef)(null);
|
|
10
|
+
const { viewportWidth } = require_useCheckIsMobile.useCheckIsMobile();
|
|
11
|
+
const isMobile = viewportWidth !== void 0 && viewportWidth < 512;
|
|
12
|
+
const shouldAutoExpand = Boolean(isMobile && window?._spiffy?.selectedCustomizeOption);
|
|
13
|
+
const snaps = shouldAutoExpand ? [43, 100] : [
|
|
14
|
+
0,
|
|
15
|
+
43,
|
|
16
|
+
100
|
|
17
|
+
];
|
|
18
|
+
const initialSnap = 1;
|
|
19
|
+
const [currentSnapPercentage, setCurrentSnapPercentage] = (0, react.useState)(snaps[initialSnap] || 43);
|
|
20
|
+
const animationKey = (0, framer_motion.useMotionValue)(0);
|
|
21
|
+
const snap43Percent = 57 / 100 * window.innerHeight;
|
|
22
|
+
const snap100Percent = 0;
|
|
23
|
+
const mobileHeaderHeight = (0, framer_motion.useTransform)(animationKey, [snap100Percent, snap43Percent], [56, 0]);
|
|
24
|
+
const [shouldShowHeader, setShouldShowHeader] = (0, react.useState)(false);
|
|
25
|
+
const [shouldShowScrolled, setShouldShowScrolled] = (0, react.useState)(false);
|
|
26
|
+
(0, react.useEffect)(() => {
|
|
27
|
+
return animationKey.on("change", (value) => {
|
|
28
|
+
setShouldShowHeader(value < snap43Percent - 10);
|
|
29
|
+
setShouldShowScrolled(value > snap43Percent);
|
|
30
|
+
});
|
|
31
|
+
}, [animationKey, snap43Percent]);
|
|
32
|
+
const isFullView = isMobile && currentSnapPercentage === 100;
|
|
33
|
+
const isPartialView = isMobile && currentSnapPercentage >= 0 && currentSnapPercentage <= 43;
|
|
34
|
+
const handleSnapChange = (snapPercentage) => {
|
|
35
|
+
setCurrentSnapPercentage(snapPercentage);
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
modalSheetControl,
|
|
39
|
+
maxSwipeableViewHeight,
|
|
40
|
+
isOpen: window?._spiffy?.selectedCustomizeOption === "SalesAgent" ? true : Boolean(isFloatingChatOpen),
|
|
41
|
+
isMobile,
|
|
42
|
+
snaps,
|
|
43
|
+
initialSnap,
|
|
44
|
+
shouldAutoExpand,
|
|
45
|
+
currentSnapPercentage,
|
|
46
|
+
handleSnapChange,
|
|
47
|
+
animationKey,
|
|
48
|
+
mobileHeaderHeight,
|
|
49
|
+
snap43Percent,
|
|
50
|
+
snap100Percent,
|
|
51
|
+
shouldShowHeader,
|
|
52
|
+
shouldShowScrolled,
|
|
53
|
+
isFullView,
|
|
54
|
+
isPartialView
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
exports.useSnapSetup = useSnapSetup;
|