@elliemae/ds-chat-container 3.70.0-next.41 → 3.70.0-next.43

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.
Files changed (20) hide show
  1. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js +6 -5
  2. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  3. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js +4 -3
  4. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  5. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +41 -20
  6. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  7. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js +13 -4
  8. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  9. package/dist/esm/parts/chat-container-messages-list/useActionRef.js +6 -5
  10. package/dist/esm/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  11. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js +4 -3
  12. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  13. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +42 -21
  14. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  15. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js +13 -4
  16. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  17. package/dist/types/parts/chat-container-messages-list/useActionRef.d.ts +3 -2
  18. package/dist/types/parts/chat-container-messages-list/useFocusAndScrollHelpers.d.ts +2 -0
  19. package/dist/types/parts/chat-container-messages-list/useKeyboard.d.ts +2 -2
  20. package/package.json +17 -16
@@ -37,7 +37,8 @@ const useActionRef = ({
37
37
  actionRef,
38
38
  useVirtualHelpers: { scrollToIndex: vScroll },
39
39
  virtualListRef,
40
- onScrollStop,
40
+ updateCache,
41
+ getMessagesInView,
41
42
  onlyFocus,
42
43
  scrollAndFocus
43
44
  }) => {
@@ -48,7 +49,7 @@ const useActionRef = ({
48
49
  vScroll(index, opts);
49
50
  requestAnimationFrame(() => {
50
51
  vScroll(index, opts);
51
- onScrollStop();
52
+ updateCache();
52
53
  });
53
54
  }, 0);
54
55
  };
@@ -59,12 +60,12 @@ const useActionRef = ({
59
60
  virtualListRef.current?.focus();
60
61
  };
61
62
  actionRef.current.scrollToIndex = scrollToIndex;
62
- actionRef.current.getMessagesInView = onScrollStop;
63
- onScrollStop();
63
+ actionRef.current.getMessagesInView = getMessagesInView;
64
+ updateCache();
64
65
  actionRef.current.focusToIndex = focusToIndex;
65
66
  actionRef.current.focusToIndexWithoutScroll = onlyFocus;
66
67
  actionRef.current.focusToList = focusToList;
67
68
  }
68
- }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
69
+ }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
69
70
  };
70
71
  //# sourceMappingURL=useActionRef.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/useActionRef.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n onScrollStop: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n onScrollStop();\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = onScrollStop;\n // I have no idea what the next line refeers to\n // keeping this from original code to avoid any possible breaking-change\n onScrollStop(); // init useMemo due to debounce use.\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAaX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,eAAAA,QAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AAYnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AACnB,yBAAa;AAAA,UACf,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AAGtC,mBAAa;AACb,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,cAAc,WAAW,gBAAgB,SAAS,cAAc,CAAC;AAClF;",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n updateCache: () => void;\n getMessagesInView: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n updateCache();\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = getMessagesInView;\n updateCache(); // populate cache immediately on mount \u2014 leading throttle fires synchronously\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAcX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,eAAAA,QAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AAYnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AACnB,wBAAY;AAAA,UACd,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AACtC,kBAAY;AACZ,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,mBAAmB,WAAW,gBAAgB,SAAS,cAAc,CAAC;AACpG;",
6
6
  "names": ["React"]
7
7
  }
@@ -71,7 +71,7 @@ const useChatContainerMessageList = (props) => {
71
71
  // https://github.com/tannerlinsley/react-virtual/issues/23
72
72
  estimateSize: import_react.default.useCallback(() => 80, [])
73
73
  });
74
- const { onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll } = (0, import_useFocusAndScrollHelpers.useFocusAndScrollHelpers)({
74
+ const { onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } = (0, import_useFocusAndScrollHelpers.useFocusAndScrollHelpers)({
75
75
  propsWithDefault,
76
76
  useVirtualHelpers,
77
77
  pendingOnScroll,
@@ -81,7 +81,8 @@ const useChatContainerMessageList = (props) => {
81
81
  actionRef,
82
82
  useVirtualHelpers,
83
83
  virtualListRef,
84
- onScrollStop,
84
+ updateCache,
85
+ getMessagesInView,
85
86
  onlyFocus,
86
87
  scrollAndFocus
87
88
  });
@@ -98,7 +99,7 @@ const useChatContainerMessageList = (props) => {
98
99
  loadMoreRef,
99
100
  scrollAndFocus,
100
101
  onlyFocus,
101
- onScrollStop
102
+ getMessagesInView
102
103
  });
103
104
  return import_react.default.useMemo(
104
105
  () => ({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/useChatContainerMessageList.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useGetGlobalAttributes,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { useVirtual } from 'react-virtual';\nimport { useActionRef } from './useActionRef.js';\nimport { useGlobalEventListener } from './useGlobalEventListener.js';\nimport { useKeyboard } from './useKeyboard.js';\nimport { useFocusAndScrollHelpers } from './useFocusAndScrollHelpers.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes, defaultPropsMessagesList } from '../../react-desc-prop-types.js';\nimport { DSChatContainerMessagesList } from '../../DSChatContainerDefinitions.js';\n\nconst getPadding = ({ hasMoreItems, bannerPosition, isLoading }: DSChatT.GetPaddingT) => {\n const padding = {\n paddingStart: 0,\n paddingEnd: -5,\n };\n if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'top')) padding.paddingStart = 42;\n else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'bottom')) padding.paddingEnd = 42;\n return padding;\n};\n\ntype UseChatContainerMessageList = (props: DSChatT.MessagesListProps) => {\n propsWithDefault: DSChatT.MessagesListProps;\n globalAttributes: ReturnType<typeof useGetGlobalAttributes>;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n} & ReturnType<typeof useKeyboard>;\n\nexport const useChatContainerMessageList: UseChatContainerMessageList = (props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSChatT.MessagesListProps>(props, defaultPropsMessagesList);\n useValidateTypescriptPropTypes<DSChatT.MessagesListProps>(\n propsWithDefault,\n ChatContainerMessagesListPropTypes,\n DSChatContainerMessagesList,\n );\n const globalAttributes = useGetGlobalAttributes(propsWithDefault);\n const loadMoreRef = React.useRef<HTMLButtonElement>();\n const virtualListRef = React.useRef<HTMLDivElement>();\n\n const pendingOnScroll = React.useRef(false);\n const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;\n const useVirtualHelpers = useVirtual({\n size: messages?.length,\n parentRef: virtualListRef,\n overscan: 15,\n ...getPadding({ hasMoreItems, bannerPosition, isLoading }),\n // estimateSize should not be really required given what was stated on\n // https://github.com/tannerlinsley/react-virtual/issues/23\n estimateSize: React.useCallback(() => 80, []),\n });\n\n const { onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll } = useFocusAndScrollHelpers({\n propsWithDefault,\n useVirtualHelpers,\n pendingOnScroll,\n virtualListRef,\n });\n\n useActionRef({\n actionRef,\n useVirtualHelpers,\n virtualListRef,\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n });\n\n useGlobalEventListener({\n propsWithDefault,\n virtualListRef,\n onScrollStop,\n checkPendingOnScroll,\n });\n\n const keyboardMethods = useKeyboard({\n propsWithDefault,\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n onScrollStop,\n });\n\n return React.useMemo(\n () => ({\n propsWithDefault,\n globalAttributes,\n useVirtualHelpers,\n loadMoreRef,\n virtualListRef,\n ...keyboardMethods,\n }),\n [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAClB,8BAIO;AACP,2BAA2B;AAC3B,0BAA6B;AAC7B,oCAAuC;AACvC,yBAA4B;AAC5B,sCAAyC;AAEzC,mCAA6E;AAC7E,wCAA4C;AAE5C,MAAM,aAAa,CAAC,EAAE,cAAc,gBAAgB,UAAU,MAA2B;AACvF,QAAM,UAAU;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AACA,MAAI,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,KAAK,EAAG,SAAQ,eAAe;AAAA,WAC5F,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,QAAQ,EAAG,SAAQ,aAAa;AAC3G,SAAO;AACT;AAUO,MAAM,8BAA2D,CAAC,UAAU;AACjF,QAAM,uBAAmB,sDAAwD,OAAO,qDAAwB;AAChH;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,uBAAmB,gDAAuB,gBAAgB;AAChE,QAAM,cAAc,aAAAA,QAAM,OAA0B;AACpD,QAAM,iBAAiB,aAAAA,QAAM,OAAuB;AAEpD,QAAM,kBAAkB,aAAAA,QAAM,OAAO,KAAK;AAC1C,QAAM,EAAE,gBAAgB,UAAU,WAAW,cAAc,UAAU,IAAI;AACzE,QAAM,wBAAoB,iCAAW;AAAA,IACnC,MAAM,UAAU;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,GAAG,WAAW,EAAE,cAAc,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA,IAGzD,cAAc,aAAAA,QAAM,YAAY,MAAM,IAAI,CAAC,CAAC;AAAA,EAC9C,CAAC;AAED,QAAM,EAAE,cAAc,WAAW,gBAAgB,qBAAqB,QAAI,0DAAyB;AAAA,IACjG;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,wCAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,4DAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,sBAAkB,gCAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,mBAAmB,aAAa,cAAc;AAAA,EACtG;AACF;",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useGetGlobalAttributes,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { useVirtual } from 'react-virtual';\nimport { useActionRef } from './useActionRef.js';\nimport { useGlobalEventListener } from './useGlobalEventListener.js';\nimport { useKeyboard } from './useKeyboard.js';\nimport { useFocusAndScrollHelpers } from './useFocusAndScrollHelpers.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes, defaultPropsMessagesList } from '../../react-desc-prop-types.js';\nimport { DSChatContainerMessagesList } from '../../DSChatContainerDefinitions.js';\n\nconst getPadding = ({ hasMoreItems, bannerPosition, isLoading }: DSChatT.GetPaddingT) => {\n const padding = {\n paddingStart: 0,\n paddingEnd: -5,\n };\n if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'top')) padding.paddingStart = 42;\n else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'bottom')) padding.paddingEnd = 42;\n return padding;\n};\n\ntype UseChatContainerMessageList = (props: DSChatT.MessagesListProps) => {\n propsWithDefault: DSChatT.MessagesListProps;\n globalAttributes: ReturnType<typeof useGetGlobalAttributes>;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n} & ReturnType<typeof useKeyboard>;\n\nexport const useChatContainerMessageList: UseChatContainerMessageList = (props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSChatT.MessagesListProps>(props, defaultPropsMessagesList);\n useValidateTypescriptPropTypes<DSChatT.MessagesListProps>(\n propsWithDefault,\n ChatContainerMessagesListPropTypes,\n DSChatContainerMessagesList,\n );\n const globalAttributes = useGetGlobalAttributes(propsWithDefault);\n const loadMoreRef = React.useRef<HTMLButtonElement>();\n const virtualListRef = React.useRef<HTMLDivElement>();\n\n const pendingOnScroll = React.useRef(false);\n const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;\n const useVirtualHelpers = useVirtual({\n size: messages?.length,\n parentRef: virtualListRef,\n overscan: 15,\n ...getPadding({ hasMoreItems, bannerPosition, isLoading }),\n // estimateSize should not be really required given what was stated on\n // https://github.com/tannerlinsley/react-virtual/issues/23\n estimateSize: React.useCallback(() => 80, []),\n });\n\n const { onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } =\n useFocusAndScrollHelpers({\n propsWithDefault,\n useVirtualHelpers,\n pendingOnScroll,\n virtualListRef,\n });\n\n useActionRef({\n actionRef,\n useVirtualHelpers,\n virtualListRef,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n });\n\n useGlobalEventListener({\n propsWithDefault,\n virtualListRef,\n onScrollStop,\n checkPendingOnScroll,\n });\n\n const keyboardMethods = useKeyboard({\n propsWithDefault,\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n getMessagesInView,\n });\n\n return React.useMemo(\n () => ({\n propsWithDefault,\n globalAttributes,\n useVirtualHelpers,\n loadMoreRef,\n virtualListRef,\n ...keyboardMethods,\n }),\n [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAClB,8BAIO;AACP,2BAA2B;AAC3B,0BAA6B;AAC7B,oCAAuC;AACvC,yBAA4B;AAC5B,sCAAyC;AAEzC,mCAA6E;AAC7E,wCAA4C;AAE5C,MAAM,aAAa,CAAC,EAAE,cAAc,gBAAgB,UAAU,MAA2B;AACvF,QAAM,UAAU;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AACA,MAAI,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,KAAK,EAAG,SAAQ,eAAe;AAAA,WAC5F,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,QAAQ,EAAG,SAAQ,aAAa;AAC3G,SAAO;AACT;AAUO,MAAM,8BAA2D,CAAC,UAAU;AACjF,QAAM,uBAAmB,sDAAwD,OAAO,qDAAwB;AAChH;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,uBAAmB,gDAAuB,gBAAgB;AAChE,QAAM,cAAc,aAAAA,QAAM,OAA0B;AACpD,QAAM,iBAAiB,aAAAA,QAAM,OAAuB;AAEpD,QAAM,kBAAkB,aAAAA,QAAM,OAAO,KAAK;AAC1C,QAAM,EAAE,gBAAgB,UAAU,WAAW,cAAc,UAAU,IAAI;AACzE,QAAM,wBAAoB,iCAAW;AAAA,IACnC,MAAM,UAAU;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,GAAG,WAAW,EAAE,cAAc,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA,IAGzD,cAAc,aAAAA,QAAM,YAAY,MAAM,IAAI,CAAC,CAAC;AAAA,EAC9C,CAAC;AAED,QAAM,EAAE,cAAc,aAAa,mBAAmB,WAAW,gBAAgB,qBAAqB,QACpG,0DAAyB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAEH,wCAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,4DAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,sBAAkB,gCAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,mBAAmB,aAAa,cAAc;AAAA,EACtG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -40,26 +40,42 @@ const useFocusAndScrollHelpers = ({
40
40
  pendingOnScroll,
41
41
  virtualListRef
42
42
  }) => {
43
+ const computeVisibleItems = import_react.default.useCallback(() => {
44
+ if (document.visibilityState === "hidden") {
45
+ pendingOnScroll.current = true;
46
+ return [];
47
+ }
48
+ if (!virtualListRef.current) return [];
49
+ pendingOnScroll.current = false;
50
+ const { bottom, top } = virtualListRef.current.getBoundingClientRect();
51
+ const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
52
+ const indexList = [];
53
+ list.forEach((item) => {
54
+ const { top: itemTop } = item.getBoundingClientRect();
55
+ const itemPadding = 10;
56
+ if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || "");
57
+ });
58
+ return indexList;
59
+ }, [pendingOnScroll, virtualListRef]);
60
+ const visibleItemsCache = import_react.default.useRef([]);
61
+ const updateCache = import_react.default.useMemo(
62
+ () => (0, import_lodash_es.throttle)(
63
+ () => {
64
+ visibleItemsCache.current = computeVisibleItems();
65
+ },
66
+ 500,
67
+ { leading: true }
68
+ ),
69
+ [computeVisibleItems]
70
+ );
71
+ const getMessagesInView = import_react.default.useCallback(() => [...visibleItemsCache.current], []);
43
72
  const onScrollStop = import_react.default.useMemo(
44
73
  () => (0, import_lodash_es.debounce)(() => {
45
- if (document.visibilityState === "hidden") {
46
- pendingOnScroll.current = true;
47
- return [];
48
- }
49
- if (!virtualListRef.current) return [];
50
- pendingOnScroll.current = false;
51
- const { bottom, top } = virtualListRef.current?.getBoundingClientRect() || {};
52
- const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
53
- const indexList = [];
54
- list.forEach((item) => {
55
- const { top: itemTop } = item.getBoundingClientRect();
56
- const itemPadding = 10;
57
- if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || "");
58
- });
74
+ const indexList = computeVisibleItems();
59
75
  if (onScrollEnds) onScrollEnds(indexList);
60
76
  return indexList;
61
77
  }, 500),
62
- [onScrollEnds, pendingOnScroll, virtualListRef]
78
+ [computeVisibleItems, onScrollEnds]
63
79
  );
64
80
  const onlyFocus = import_react.default.useCallback(
65
81
  (index) => {
@@ -76,21 +92,26 @@ const useFocusAndScrollHelpers = ({
76
92
  setTimeout(() => {
77
93
  onlyFocus(index.toString());
78
94
  }, 300);
79
- onScrollStop();
95
+ updateCache();
80
96
  },
81
- [onScrollStop, onlyFocus, vScroll]
97
+ [updateCache, onlyFocus, vScroll]
82
98
  );
83
99
  const checkPendingOnScroll = import_react.default.useCallback(() => {
84
- if (pendingOnScroll.current === true) onScrollStop();
85
- }, [onScrollStop, pendingOnScroll]);
100
+ if (pendingOnScroll.current === true) {
101
+ updateCache();
102
+ onScrollStop();
103
+ }
104
+ }, [updateCache, onScrollStop, pendingOnScroll]);
86
105
  return import_react.default.useMemo(
87
106
  () => ({
88
107
  onScrollStop,
108
+ updateCache,
109
+ getMessagesInView,
89
110
  onlyFocus,
90
111
  scrollAndFocus,
91
112
  checkPendingOnScroll
92
113
  }),
93
- [onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll]
114
+ [onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll]
94
115
  );
95
116
  };
96
117
  //# sourceMappingURL=useFocusAndScrollHelpers.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/useFocusAndScrollHelpers.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport { debounce } from 'lodash-es';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseFocusAndScrollHelpersArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n pendingOnScroll: React.MutableRefObject<boolean>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n};\n\nexport const useFocusAndScrollHelpers = ({\n propsWithDefault: { onScrollEnds },\n useVirtualHelpers: { scrollToIndex: vScroll },\n pendingOnScroll,\n virtualListRef,\n}: UseFocusAndScrollHelpersArgs) => {\n const onScrollStop = React.useMemo(\n () =>\n debounce((): string[] => {\n if (document.visibilityState === 'hidden') {\n pendingOnScroll.current = true;\n return [];\n }\n if (!virtualListRef.current) return [];\n pendingOnScroll.current = false;\n const { bottom, top } = virtualListRef.current?.getBoundingClientRect() || {};\n\n const list = virtualListRef.current.querySelectorAll<HTMLElement>('[data-element=\"chat-element-list-item\"]');\n const indexList: Array<string> = [];\n list.forEach((item: HTMLElement) => {\n const { top: itemTop } = item.getBoundingClientRect();\n\n const itemPadding = 10;\n if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || '');\n });\n if (onScrollEnds) onScrollEnds(indexList);\n return indexList;\n }, 500),\n [onScrollEnds, pendingOnScroll, virtualListRef],\n ) as () => string[];\n\n const onlyFocus = React.useCallback(\n (index: string) => {\n (virtualListRef.current?.querySelector(`[data-index=\"${index}\"]`) as HTMLDivElement)?.focus();\n },\n [virtualListRef],\n );\n\n const scrollAndFocus = React.useCallback(\n (index: number) => {\n vScroll(index, { align: 'center' });\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, { align: 'center' });\n });\n\n setTimeout(() => {\n onlyFocus(index.toString());\n }, 300);\n\n onScrollStop();\n },\n [onScrollStop, onlyFocus, vScroll],\n );\n\n const checkPendingOnScroll = React.useCallback(() => {\n if (pendingOnScroll.current === true) onScrollStop();\n }, [onScrollStop, pendingOnScroll]);\n\n return React.useMemo(\n () => ({\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n checkPendingOnScroll,\n }),\n [onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAElB,uBAAyB;AAUlB,MAAM,2BAA2B,CAAC;AAAA,EACvC,kBAAkB,EAAE,aAAa;AAAA,EACjC,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AACF,MAAoC;AAClC,QAAM,eAAe,aAAAA,QAAM;AAAA,IACzB,UACE,2BAAS,MAAgB;AACvB,UAAI,SAAS,oBAAoB,UAAU;AACzC,wBAAgB,UAAU;AAC1B,eAAO,CAAC;AAAA,MACV;AACA,UAAI,CAAC,eAAe,QAAS,QAAO,CAAC;AACrC,sBAAgB,UAAU;AAC1B,YAAM,EAAE,QAAQ,IAAI,IAAI,eAAe,SAAS,sBAAsB,KAAK,CAAC;AAE5E,YAAM,OAAO,eAAe,QAAQ,iBAA8B,yCAAyC;AAC3G,YAAM,YAA2B,CAAC;AAClC,WAAK,QAAQ,CAAC,SAAsB;AAClC,cAAM,EAAE,KAAK,QAAQ,IAAI,KAAK,sBAAsB;AAEpD,cAAM,cAAc;AACpB,YAAI,UAAU,cAAc,UAAU,UAAU,cAAc,IAAK,WAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAAA,MAC5G,CAAC;AACD,UAAI,aAAc,cAAa,SAAS;AACxC,aAAO;AAAA,IACT,GAAG,GAAG;AAAA,IACR,CAAC,cAAc,iBAAiB,cAAc;AAAA,EAChD;AAEA,QAAM,YAAY,aAAAA,QAAM;AAAA,IACtB,CAAC,UAAkB;AACjB,MAAC,eAAe,SAAS,cAAc,gBAAgB,KAAK,IAAI,GAAsB,MAAM;AAAA,IAC9F;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,iBAAiB,aAAAA,QAAM;AAAA,IAC3B,CAAC,UAAkB;AACjB,cAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAYlC,4BAAsB,MAAM;AAC1B,gBAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,MACpC,CAAC;AAED,iBAAW,MAAM;AACf,kBAAU,MAAM,SAAS,CAAC;AAAA,MAC5B,GAAG,GAAG;AAEN,mBAAa;AAAA,IACf;AAAA,IACA,CAAC,cAAc,WAAW,OAAO;AAAA,EACnC;AAEA,QAAM,uBAAuB,aAAAA,QAAM,YAAY,MAAM;AACnD,QAAI,gBAAgB,YAAY,KAAM,cAAa;AAAA,EACrD,GAAG,CAAC,cAAc,eAAe,CAAC;AAElC,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,cAAc,WAAW,gBAAgB,oBAAoB;AAAA,EAChE;AACF;",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport { debounce, throttle } from 'lodash-es';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseFocusAndScrollHelpersArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n pendingOnScroll: React.MutableRefObject<boolean>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n};\n\nexport const useFocusAndScrollHelpers = ({\n propsWithDefault: { onScrollEnds },\n useVirtualHelpers: { scrollToIndex: vScroll },\n pendingOnScroll,\n virtualListRef,\n}: UseFocusAndScrollHelpersArgs) => {\n // Pure DOM read \u2014 no side effects beyond pendingOnScroll flag and getBoundingClientRect queries.\n const computeVisibleItems = React.useCallback((): string[] => {\n if (document.visibilityState === 'hidden') {\n pendingOnScroll.current = true;\n return [];\n }\n if (!virtualListRef.current) return [];\n pendingOnScroll.current = false;\n const { bottom, top } = virtualListRef.current.getBoundingClientRect();\n const list = virtualListRef.current.querySelectorAll<HTMLElement>('[data-element=\"chat-element-list-item\"]');\n const indexList: string[] = [];\n list.forEach((item: HTMLElement) => {\n const { top: itemTop } = item.getBoundingClientRect();\n const itemPadding = 10;\n if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || '');\n });\n return indexList;\n }, [pendingOnScroll, virtualListRef]);\n\n // Throttled with leading: populates the cache immediately on first call and keeps it\n // fresh. No side effects beyond DOM reads \u2014 onScrollEnds is not involved.\n const visibleItemsCache = React.useRef<string[]>([]);\n const updateCache = React.useMemo(\n () =>\n throttle(\n () => {\n visibleItemsCache.current = computeVisibleItems();\n },\n 500,\n { leading: true },\n ),\n [computeVisibleItems],\n );\n\n // Synchronous getter \u2014 returns a copy so callers using .pop()/.shift() don't mutate the cache.\n const getMessagesInView = React.useCallback((): string[] => [...visibleItemsCache.current], []);\n\n // Debounced trailing: notifies onScrollEnds consumers after scrolling settles.\n // Semantics and timing unchanged \u2014 this path is isolated from the cache.\n const onScrollStop = React.useMemo(\n () =>\n debounce((): string[] => {\n const indexList = computeVisibleItems();\n if (onScrollEnds) onScrollEnds(indexList);\n return indexList;\n }, 500),\n [computeVisibleItems, onScrollEnds],\n ) as () => string[];\n\n const onlyFocus = React.useCallback(\n (index: string) => {\n (virtualListRef.current?.querySelector(`[data-index=\"${index}\"]`) as HTMLDivElement)?.focus();\n },\n [virtualListRef],\n );\n\n const scrollAndFocus = React.useCallback(\n (index: number) => {\n vScroll(index, { align: 'center' });\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, { align: 'center' });\n });\n\n setTimeout(() => {\n onlyFocus(index.toString());\n }, 300);\n\n updateCache();\n },\n [updateCache, onlyFocus, vScroll],\n );\n\n const checkPendingOnScroll = React.useCallback(() => {\n if (pendingOnScroll.current === true) {\n updateCache();\n onScrollStop();\n }\n }, [updateCache, onScrollStop, pendingOnScroll]);\n\n return React.useMemo(\n () => ({\n onScrollStop,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n checkPendingOnScroll,\n }),\n [onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,mBAAkB;AAElB,uBAAmC;AAU5B,MAAM,2BAA2B,CAAC;AAAA,EACvC,kBAAkB,EAAE,aAAa;AAAA,EACjC,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AACF,MAAoC;AAElC,QAAM,sBAAsB,aAAAA,QAAM,YAAY,MAAgB;AAC5D,QAAI,SAAS,oBAAoB,UAAU;AACzC,sBAAgB,UAAU;AAC1B,aAAO,CAAC;AAAA,IACV;AACA,QAAI,CAAC,eAAe,QAAS,QAAO,CAAC;AACrC,oBAAgB,UAAU;AAC1B,UAAM,EAAE,QAAQ,IAAI,IAAI,eAAe,QAAQ,sBAAsB;AACrE,UAAM,OAAO,eAAe,QAAQ,iBAA8B,yCAAyC;AAC3G,UAAM,YAAsB,CAAC;AAC7B,SAAK,QAAQ,CAAC,SAAsB;AAClC,YAAM,EAAE,KAAK,QAAQ,IAAI,KAAK,sBAAsB;AACpD,YAAM,cAAc;AACpB,UAAI,UAAU,cAAc,UAAU,UAAU,cAAc,IAAK,WAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAAA,IAC5G,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,cAAc,CAAC;AAIpC,QAAM,oBAAoB,aAAAA,QAAM,OAAiB,CAAC,CAAC;AACnD,QAAM,cAAc,aAAAA,QAAM;AAAA,IACxB,UACE;AAAA,MACE,MAAM;AACJ,0BAAkB,UAAU,oBAAoB;AAAA,MAClD;AAAA,MACA;AAAA,MACA,EAAE,SAAS,KAAK;AAAA,IAClB;AAAA,IACF,CAAC,mBAAmB;AAAA,EACtB;AAGA,QAAM,oBAAoB,aAAAA,QAAM,YAAY,MAAgB,CAAC,GAAG,kBAAkB,OAAO,GAAG,CAAC,CAAC;AAI9F,QAAM,eAAe,aAAAA,QAAM;AAAA,IACzB,UACE,2BAAS,MAAgB;AACvB,YAAM,YAAY,oBAAoB;AACtC,UAAI,aAAc,cAAa,SAAS;AACxC,aAAO;AAAA,IACT,GAAG,GAAG;AAAA,IACR,CAAC,qBAAqB,YAAY;AAAA,EACpC;AAEA,QAAM,YAAY,aAAAA,QAAM;AAAA,IACtB,CAAC,UAAkB;AACjB,MAAC,eAAe,SAAS,cAAc,gBAAgB,KAAK,IAAI,GAAsB,MAAM;AAAA,IAC9F;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,iBAAiB,aAAAA,QAAM;AAAA,IAC3B,CAAC,UAAkB;AACjB,cAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAYlC,4BAAsB,MAAM;AAC1B,gBAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,MACpC,CAAC;AAED,iBAAW,MAAM;AACf,kBAAU,MAAM,SAAS,CAAC;AAAA,MAC5B,GAAG,GAAG;AAEN,kBAAY;AAAA,IACd;AAAA,IACA,CAAC,aAAa,WAAW,OAAO;AAAA,EAClC;AAEA,QAAM,uBAAuB,aAAAA,QAAM,YAAY,MAAM;AACnD,QAAI,gBAAgB,YAAY,MAAM;AACpC,kBAAY;AACZ,mBAAa;AAAA,IACf;AAAA,EACF,GAAG,CAAC,aAAa,cAAc,eAAe,CAAC;AAE/C,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,cAAc,aAAa,mBAAmB,WAAW,gBAAgB,oBAAoB;AAAA,EAChG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -41,7 +41,7 @@ const useKeyboard = ({
41
41
  loadMoreRef,
42
42
  scrollAndFocus,
43
43
  onlyFocus,
44
- onScrollStop
44
+ getMessagesInView
45
45
  }) => {
46
46
  const handleKey = import_react.default.useCallback(
47
47
  (e) => {
@@ -102,7 +102,7 @@ const useKeyboard = ({
102
102
  case "ArrowUp":
103
103
  e.preventDefault();
104
104
  if (document.activeElement !== loadMoreRef.current) {
105
- const id = onScrollStop()?.shift();
105
+ const id = getMessagesInView()?.shift();
106
106
  if (id) onlyFocus(id);
107
107
  }
108
108
  break;
@@ -111,7 +111,7 @@ const useKeyboard = ({
111
111
  if (document.activeElement === loadMoreRef.current) {
112
112
  virtualListRef.current?.querySelector(`[data-index="0"]`)?.focus();
113
113
  } else {
114
- const id = onScrollStop()?.pop();
114
+ const id = getMessagesInView()?.pop();
115
115
  if (id) onlyFocus(id);
116
116
  }
117
117
  break;
@@ -144,7 +144,16 @@ const useKeyboard = ({
144
144
  break;
145
145
  }
146
146
  },
147
- [actionRef, hasMoreItems, loadMoreRef, messages.length, onScrollStop, onlyFocus, scrollAndFocus, virtualListRef]
147
+ [
148
+ actionRef,
149
+ hasMoreItems,
150
+ loadMoreRef,
151
+ messages.length,
152
+ getMessagesInView,
153
+ onlyFocus,
154
+ scrollAndFocus,
155
+ virtualListRef
156
+ ]
148
157
  );
149
158
  return import_react.default.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);
150
159
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/chat-container-messages-list/useKeyboard.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseKeyboardArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n actionRef: DSChatT.ActionRef;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n onlyFocus: (index: string) => void;\n onScrollStop: () => string[];\n // useVirtualHelpers: ReturnType<typeof useVirtual>;\n};\n\nconst getIsNumber = (val: unknown): val is number => Number.isInteger(val);\n\nexport const useKeyboard = ({\n propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef },\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n onScrollStop,\n}: UseKeyboardArgs) => {\n const handleKey = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>) => {\n const { key, currentTarget } = e;\n const index = currentTarget.dataset?.index ? Number(currentTarget.dataset.index) : undefined;\n const isIndexNumber = getIsNumber(index);\n e.stopPropagation();\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (index && index > 0) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index - 1}\"]`) as HTMLDivElement).focus();\n } else if (hasMoreItems === 'top') {\n loadMoreRef.current?.focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (messages?.length && isIndexNumber && index < messages.length - 1) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index + 1}\"]`) as HTMLDivElement).focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (hasMoreItems === 'top' && e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n if (bannerPosition) {\n e.preventDefault();\n bannerRef?.current?.focusOnWrapper();\n }\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [hasMoreItems, messages.length, scrollAndFocus, virtualListRef, loadMoreRef, bannerPosition, bannerRef],\n );\n const handleListKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (document.activeElement !== loadMoreRef.current) {\n const id = onScrollStop()?.shift();\n if (id) onlyFocus(id);\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (document.activeElement === loadMoreRef.current) {\n (virtualListRef.current?.querySelector(`[data-index=\"0\"]`) as HTMLDivElement)?.focus();\n } else {\n const id = onScrollStop()?.pop();\n if (id) onlyFocus(id);\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (document.activeElement !== loadMoreRef.current) {\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n }\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [actionRef, hasMoreItems, loadMoreRef, messages.length, onScrollStop, onlyFocus, scrollAndFocus, virtualListRef],\n );\n\n return React.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseKeyboardArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n actionRef: DSChatT.ActionRef;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n onlyFocus: (index: string) => void;\n getMessagesInView: () => string[];\n};\n\nconst getIsNumber = (val: unknown): val is number => Number.isInteger(val);\n\nexport const useKeyboard = ({\n propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef },\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n getMessagesInView,\n}: UseKeyboardArgs) => {\n const handleKey = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>) => {\n const { key, currentTarget } = e;\n const index = currentTarget.dataset?.index ? Number(currentTarget.dataset.index) : undefined;\n const isIndexNumber = getIsNumber(index);\n e.stopPropagation();\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (index && index > 0) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index - 1}\"]`) as HTMLDivElement).focus();\n } else if (hasMoreItems === 'top') {\n loadMoreRef.current?.focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (messages?.length && isIndexNumber && index < messages.length - 1) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index + 1}\"]`) as HTMLDivElement).focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (hasMoreItems === 'top' && e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n if (bannerPosition) {\n e.preventDefault();\n bannerRef?.current?.focusOnWrapper();\n }\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [hasMoreItems, messages.length, scrollAndFocus, virtualListRef, loadMoreRef, bannerPosition, bannerRef],\n );\n const handleListKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (document.activeElement !== loadMoreRef.current) {\n const id = getMessagesInView()?.shift();\n if (id) onlyFocus(id);\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (document.activeElement === loadMoreRef.current) {\n (virtualListRef.current?.querySelector(`[data-index=\"0\"]`) as HTMLDivElement)?.focus();\n } else {\n const id = getMessagesInView()?.pop();\n if (id) onlyFocus(id);\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (document.activeElement !== loadMoreRef.current) {\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n }\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [\n actionRef,\n hasMoreItems,\n loadMoreRef,\n messages.length,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n virtualListRef,\n ],\n );\n\n return React.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": "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",
6
6
  "names": ["React"]
7
7
  }
@@ -4,7 +4,8 @@ const useActionRef = ({
4
4
  actionRef,
5
5
  useVirtualHelpers: { scrollToIndex: vScroll },
6
6
  virtualListRef,
7
- onScrollStop,
7
+ updateCache,
8
+ getMessagesInView,
8
9
  onlyFocus,
9
10
  scrollAndFocus
10
11
  }) => {
@@ -15,7 +16,7 @@ const useActionRef = ({
15
16
  vScroll(index, opts);
16
17
  requestAnimationFrame(() => {
17
18
  vScroll(index, opts);
18
- onScrollStop();
19
+ updateCache();
19
20
  });
20
21
  }, 0);
21
22
  };
@@ -26,13 +27,13 @@ const useActionRef = ({
26
27
  virtualListRef.current?.focus();
27
28
  };
28
29
  actionRef.current.scrollToIndex = scrollToIndex;
29
- actionRef.current.getMessagesInView = onScrollStop;
30
- onScrollStop();
30
+ actionRef.current.getMessagesInView = getMessagesInView;
31
+ updateCache();
31
32
  actionRef.current.focusToIndex = focusToIndex;
32
33
  actionRef.current.focusToIndexWithoutScroll = onlyFocus;
33
34
  actionRef.current.focusToList = focusToList;
34
35
  }
35
- }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
36
+ }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);
36
37
  };
37
38
  export {
38
39
  useActionRef
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/chat-container-messages-list/useActionRef.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n onScrollStop: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n onScrollStop();\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = onScrollStop;\n // I have no idea what the next line refeers to\n // keeping this from original code to avoid any possible breaking-change\n onScrollStop(); // init useMemo due to debounce use.\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, onScrollStop, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAaX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,EAAAA,OAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AAYnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AACnB,yBAAa;AAAA,UACf,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AAGtC,mBAAa;AACb,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,cAAc,WAAW,gBAAgB,SAAS,cAAc,CAAC;AAClF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseActionRefArgs = {\n actionRef: DSChatT.ActionRef;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n updateCache: () => void;\n getMessagesInView: () => string[];\n onlyFocus: (index: string) => void;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n};\n\nexport const useActionRef = ({\n actionRef,\n useVirtualHelpers: { scrollToIndex: vScroll },\n virtualListRef,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n}: UseActionRefArgs) => {\n React.useEffect(() => {\n if (actionRef && actionRef.current) {\n const scrollToIndex: DSChatT.ActionRef['current']['scrollToIndex'] = (index, opts = { align: 'center' }) => {\n setTimeout(() => {\n vScroll(index, opts);\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, opts);\n updateCache();\n });\n }, 0);\n };\n const focusToIndex: DSChatT.ActionRef['current']['focusToIndex'] = (index, opts = { align: 'center' }) => {\n scrollAndFocus(index, opts);\n };\n const focusToList = () => {\n virtualListRef.current?.focus();\n };\n\n actionRef.current.scrollToIndex = scrollToIndex;\n actionRef.current.getMessagesInView = getMessagesInView;\n updateCache(); // populate cache immediately on mount \u2014 leading throttle fires synchronously\n actionRef.current.focusToIndex = focusToIndex;\n actionRef.current.focusToIndexWithoutScroll = onlyFocus;\n actionRef.current.focusToList = focusToList;\n }\n }, [actionRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, vScroll, virtualListRef]);\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAcX,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAwB;AACtB,EAAAA,OAAM,UAAU,MAAM;AACpB,QAAI,aAAa,UAAU,SAAS;AAClC,YAAM,gBAA+D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AAC1G,mBAAW,MAAM;AACf,kBAAQ,OAAO,IAAI;AAYnB,gCAAsB,MAAM;AAC1B,oBAAQ,OAAO,IAAI;AACnB,wBAAY;AAAA,UACd,CAAC;AAAA,QACH,GAAG,CAAC;AAAA,MACN;AACA,YAAM,eAA6D,CAAC,OAAO,OAAO,EAAE,OAAO,SAAS,MAAM;AACxG,uBAAe,OAAO,IAAI;AAAA,MAC5B;AACA,YAAM,cAAc,MAAM;AACxB,uBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,gBAAU,QAAQ,gBAAgB;AAClC,gBAAU,QAAQ,oBAAoB;AACtC,kBAAY;AACZ,gBAAU,QAAQ,eAAe;AACjC,gBAAU,QAAQ,4BAA4B;AAC9C,gBAAU,QAAQ,cAAc;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,mBAAmB,WAAW,gBAAgB,SAAS,cAAc,CAAC;AACpG;",
6
6
  "names": ["React"]
7
7
  }
@@ -42,7 +42,7 @@ const useChatContainerMessageList = (props) => {
42
42
  // https://github.com/tannerlinsley/react-virtual/issues/23
43
43
  estimateSize: React2.useCallback(() => 80, [])
44
44
  });
45
- const { onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll } = useFocusAndScrollHelpers({
45
+ const { onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } = useFocusAndScrollHelpers({
46
46
  propsWithDefault,
47
47
  useVirtualHelpers,
48
48
  pendingOnScroll,
@@ -52,7 +52,8 @@ const useChatContainerMessageList = (props) => {
52
52
  actionRef,
53
53
  useVirtualHelpers,
54
54
  virtualListRef,
55
- onScrollStop,
55
+ updateCache,
56
+ getMessagesInView,
56
57
  onlyFocus,
57
58
  scrollAndFocus
58
59
  });
@@ -69,7 +70,7 @@ const useChatContainerMessageList = (props) => {
69
70
  loadMoreRef,
70
71
  scrollAndFocus,
71
72
  onlyFocus,
72
- onScrollStop
73
+ getMessagesInView
73
74
  });
74
75
  return React2.useMemo(
75
76
  () => ({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/chat-container-messages-list/useChatContainerMessageList.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useGetGlobalAttributes,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { useVirtual } from 'react-virtual';\nimport { useActionRef } from './useActionRef.js';\nimport { useGlobalEventListener } from './useGlobalEventListener.js';\nimport { useKeyboard } from './useKeyboard.js';\nimport { useFocusAndScrollHelpers } from './useFocusAndScrollHelpers.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes, defaultPropsMessagesList } from '../../react-desc-prop-types.js';\nimport { DSChatContainerMessagesList } from '../../DSChatContainerDefinitions.js';\n\nconst getPadding = ({ hasMoreItems, bannerPosition, isLoading }: DSChatT.GetPaddingT) => {\n const padding = {\n paddingStart: 0,\n paddingEnd: -5,\n };\n if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'top')) padding.paddingStart = 42;\n else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'bottom')) padding.paddingEnd = 42;\n return padding;\n};\n\ntype UseChatContainerMessageList = (props: DSChatT.MessagesListProps) => {\n propsWithDefault: DSChatT.MessagesListProps;\n globalAttributes: ReturnType<typeof useGetGlobalAttributes>;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n} & ReturnType<typeof useKeyboard>;\n\nexport const useChatContainerMessageList: UseChatContainerMessageList = (props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSChatT.MessagesListProps>(props, defaultPropsMessagesList);\n useValidateTypescriptPropTypes<DSChatT.MessagesListProps>(\n propsWithDefault,\n ChatContainerMessagesListPropTypes,\n DSChatContainerMessagesList,\n );\n const globalAttributes = useGetGlobalAttributes(propsWithDefault);\n const loadMoreRef = React.useRef<HTMLButtonElement>();\n const virtualListRef = React.useRef<HTMLDivElement>();\n\n const pendingOnScroll = React.useRef(false);\n const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;\n const useVirtualHelpers = useVirtual({\n size: messages?.length,\n parentRef: virtualListRef,\n overscan: 15,\n ...getPadding({ hasMoreItems, bannerPosition, isLoading }),\n // estimateSize should not be really required given what was stated on\n // https://github.com/tannerlinsley/react-virtual/issues/23\n estimateSize: React.useCallback(() => 80, []),\n });\n\n const { onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll } = useFocusAndScrollHelpers({\n propsWithDefault,\n useVirtualHelpers,\n pendingOnScroll,\n virtualListRef,\n });\n\n useActionRef({\n actionRef,\n useVirtualHelpers,\n virtualListRef,\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n });\n\n useGlobalEventListener({\n propsWithDefault,\n virtualListRef,\n onScrollStop,\n checkPendingOnScroll,\n });\n\n const keyboardMethods = useKeyboard({\n propsWithDefault,\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n onScrollStop,\n });\n\n return React.useMemo(\n () => ({\n propsWithDefault,\n globalAttributes,\n useVirtualHelpers,\n loadMoreRef,\n virtualListRef,\n ...keyboardMethods,\n }),\n [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef],\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AAEzC,SAAS,oCAAoC,gCAAgC;AAC7E,SAAS,mCAAmC;AAE5C,MAAM,aAAa,CAAC,EAAE,cAAc,gBAAgB,UAAU,MAA2B;AACvF,QAAM,UAAU;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AACA,MAAI,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,KAAK,EAAG,SAAQ,eAAe;AAAA,WAC5F,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,QAAQ,EAAG,SAAQ,aAAa;AAC3G,SAAO;AACT;AAUO,MAAM,8BAA2D,CAAC,UAAU;AACjF,QAAM,mBAAmB,6BAAwD,OAAO,wBAAwB;AAChH;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,mBAAmB,uBAAuB,gBAAgB;AAChE,QAAM,cAAcA,OAAM,OAA0B;AACpD,QAAM,iBAAiBA,OAAM,OAAuB;AAEpD,QAAM,kBAAkBA,OAAM,OAAO,KAAK;AAC1C,QAAM,EAAE,gBAAgB,UAAU,WAAW,cAAc,UAAU,IAAI;AACzE,QAAM,oBAAoB,WAAW;AAAA,IACnC,MAAM,UAAU;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,GAAG,WAAW,EAAE,cAAc,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA,IAGzD,cAAcA,OAAM,YAAY,MAAM,IAAI,CAAC,CAAC;AAAA,EAC9C,CAAC;AAED,QAAM,EAAE,cAAc,WAAW,gBAAgB,qBAAqB,IAAI,yBAAyB;AAAA,IACjG;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,eAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,yBAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,mBAAmB,aAAa,cAAc;AAAA,EACtG;AACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useGetGlobalAttributes,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { useVirtual } from 'react-virtual';\nimport { useActionRef } from './useActionRef.js';\nimport { useGlobalEventListener } from './useGlobalEventListener.js';\nimport { useKeyboard } from './useKeyboard.js';\nimport { useFocusAndScrollHelpers } from './useFocusAndScrollHelpers.js';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\nimport { ChatContainerMessagesListPropTypes, defaultPropsMessagesList } from '../../react-desc-prop-types.js';\nimport { DSChatContainerMessagesList } from '../../DSChatContainerDefinitions.js';\n\nconst getPadding = ({ hasMoreItems, bannerPosition, isLoading }: DSChatT.GetPaddingT) => {\n const padding = {\n paddingStart: 0,\n paddingEnd: -5,\n };\n if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'top')) padding.paddingStart = 42;\n else if ([hasMoreItems, bannerPosition, isLoading].some((item) => item === 'bottom')) padding.paddingEnd = 42;\n return padding;\n};\n\ntype UseChatContainerMessageList = (props: DSChatT.MessagesListProps) => {\n propsWithDefault: DSChatT.MessagesListProps;\n globalAttributes: ReturnType<typeof useGetGlobalAttributes>;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n} & ReturnType<typeof useKeyboard>;\n\nexport const useChatContainerMessageList: UseChatContainerMessageList = (props) => {\n const propsWithDefault = useMemoMergePropsWithDefault<DSChatT.MessagesListProps>(props, defaultPropsMessagesList);\n useValidateTypescriptPropTypes<DSChatT.MessagesListProps>(\n propsWithDefault,\n ChatContainerMessagesListPropTypes,\n DSChatContainerMessagesList,\n );\n const globalAttributes = useGetGlobalAttributes(propsWithDefault);\n const loadMoreRef = React.useRef<HTMLButtonElement>();\n const virtualListRef = React.useRef<HTMLDivElement>();\n\n const pendingOnScroll = React.useRef(false);\n const { bannerPosition, messages, actionRef, hasMoreItems, isLoading } = propsWithDefault;\n const useVirtualHelpers = useVirtual({\n size: messages?.length,\n parentRef: virtualListRef,\n overscan: 15,\n ...getPadding({ hasMoreItems, bannerPosition, isLoading }),\n // estimateSize should not be really required given what was stated on\n // https://github.com/tannerlinsley/react-virtual/issues/23\n estimateSize: React.useCallback(() => 80, []),\n });\n\n const { onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll } =\n useFocusAndScrollHelpers({\n propsWithDefault,\n useVirtualHelpers,\n pendingOnScroll,\n virtualListRef,\n });\n\n useActionRef({\n actionRef,\n useVirtualHelpers,\n virtualListRef,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n });\n\n useGlobalEventListener({\n propsWithDefault,\n virtualListRef,\n onScrollStop,\n checkPendingOnScroll,\n });\n\n const keyboardMethods = useKeyboard({\n propsWithDefault,\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n getMessagesInView,\n });\n\n return React.useMemo(\n () => ({\n propsWithDefault,\n globalAttributes,\n useVirtualHelpers,\n loadMoreRef,\n virtualListRef,\n ...keyboardMethods,\n }),\n [globalAttributes, keyboardMethods, propsWithDefault, useVirtualHelpers, loadMoreRef, virtualListRef],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AAEzC,SAAS,oCAAoC,gCAAgC;AAC7E,SAAS,mCAAmC;AAE5C,MAAM,aAAa,CAAC,EAAE,cAAc,gBAAgB,UAAU,MAA2B;AACvF,QAAM,UAAU;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AACA,MAAI,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,KAAK,EAAG,SAAQ,eAAe;AAAA,WAC5F,CAAC,cAAc,gBAAgB,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,QAAQ,EAAG,SAAQ,aAAa;AAC3G,SAAO;AACT;AAUO,MAAM,8BAA2D,CAAC,UAAU;AACjF,QAAM,mBAAmB,6BAAwD,OAAO,wBAAwB;AAChH;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,mBAAmB,uBAAuB,gBAAgB;AAChE,QAAM,cAAcA,OAAM,OAA0B;AACpD,QAAM,iBAAiBA,OAAM,OAAuB;AAEpD,QAAM,kBAAkBA,OAAM,OAAO,KAAK;AAC1C,QAAM,EAAE,gBAAgB,UAAU,WAAW,cAAc,UAAU,IAAI;AACzE,QAAM,oBAAoB,WAAW;AAAA,IACnC,MAAM,UAAU;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,GAAG,WAAW,EAAE,cAAc,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA,IAGzD,cAAcA,OAAM,YAAY,MAAM,IAAI,CAAC,CAAC;AAAA,EAC9C,CAAC;AAED,QAAM,EAAE,cAAc,aAAa,mBAAmB,WAAW,gBAAgB,qBAAqB,IACpG,yBAAyB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAEH,eAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,yBAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,mBAAmB,aAAa,cAAc;AAAA,EACtG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -1,32 +1,48 @@
1
1
  import * as React from "react";
2
2
  import React2 from "react";
3
- import { debounce } from "lodash-es";
3
+ import { debounce, throttle } from "lodash-es";
4
4
  const useFocusAndScrollHelpers = ({
5
5
  propsWithDefault: { onScrollEnds },
6
6
  useVirtualHelpers: { scrollToIndex: vScroll },
7
7
  pendingOnScroll,
8
8
  virtualListRef
9
9
  }) => {
10
+ const computeVisibleItems = React2.useCallback(() => {
11
+ if (document.visibilityState === "hidden") {
12
+ pendingOnScroll.current = true;
13
+ return [];
14
+ }
15
+ if (!virtualListRef.current) return [];
16
+ pendingOnScroll.current = false;
17
+ const { bottom, top } = virtualListRef.current.getBoundingClientRect();
18
+ const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
19
+ const indexList = [];
20
+ list.forEach((item) => {
21
+ const { top: itemTop } = item.getBoundingClientRect();
22
+ const itemPadding = 10;
23
+ if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || "");
24
+ });
25
+ return indexList;
26
+ }, [pendingOnScroll, virtualListRef]);
27
+ const visibleItemsCache = React2.useRef([]);
28
+ const updateCache = React2.useMemo(
29
+ () => throttle(
30
+ () => {
31
+ visibleItemsCache.current = computeVisibleItems();
32
+ },
33
+ 500,
34
+ { leading: true }
35
+ ),
36
+ [computeVisibleItems]
37
+ );
38
+ const getMessagesInView = React2.useCallback(() => [...visibleItemsCache.current], []);
10
39
  const onScrollStop = React2.useMemo(
11
40
  () => debounce(() => {
12
- if (document.visibilityState === "hidden") {
13
- pendingOnScroll.current = true;
14
- return [];
15
- }
16
- if (!virtualListRef.current) return [];
17
- pendingOnScroll.current = false;
18
- const { bottom, top } = virtualListRef.current?.getBoundingClientRect() || {};
19
- const list = virtualListRef.current.querySelectorAll('[data-element="chat-element-list-item"]');
20
- const indexList = [];
21
- list.forEach((item) => {
22
- const { top: itemTop } = item.getBoundingClientRect();
23
- const itemPadding = 10;
24
- if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || "");
25
- });
41
+ const indexList = computeVisibleItems();
26
42
  if (onScrollEnds) onScrollEnds(indexList);
27
43
  return indexList;
28
44
  }, 500),
29
- [onScrollEnds, pendingOnScroll, virtualListRef]
45
+ [computeVisibleItems, onScrollEnds]
30
46
  );
31
47
  const onlyFocus = React2.useCallback(
32
48
  (index) => {
@@ -43,21 +59,26 @@ const useFocusAndScrollHelpers = ({
43
59
  setTimeout(() => {
44
60
  onlyFocus(index.toString());
45
61
  }, 300);
46
- onScrollStop();
62
+ updateCache();
47
63
  },
48
- [onScrollStop, onlyFocus, vScroll]
64
+ [updateCache, onlyFocus, vScroll]
49
65
  );
50
66
  const checkPendingOnScroll = React2.useCallback(() => {
51
- if (pendingOnScroll.current === true) onScrollStop();
52
- }, [onScrollStop, pendingOnScroll]);
67
+ if (pendingOnScroll.current === true) {
68
+ updateCache();
69
+ onScrollStop();
70
+ }
71
+ }, [updateCache, onScrollStop, pendingOnScroll]);
53
72
  return React2.useMemo(
54
73
  () => ({
55
74
  onScrollStop,
75
+ updateCache,
76
+ getMessagesInView,
56
77
  onlyFocus,
57
78
  scrollAndFocus,
58
79
  checkPendingOnScroll
59
80
  }),
60
- [onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll]
81
+ [onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll]
61
82
  );
62
83
  };
63
84
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/chat-container-messages-list/useFocusAndScrollHelpers.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport { debounce } from 'lodash-es';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseFocusAndScrollHelpersArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n pendingOnScroll: React.MutableRefObject<boolean>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n};\n\nexport const useFocusAndScrollHelpers = ({\n propsWithDefault: { onScrollEnds },\n useVirtualHelpers: { scrollToIndex: vScroll },\n pendingOnScroll,\n virtualListRef,\n}: UseFocusAndScrollHelpersArgs) => {\n const onScrollStop = React.useMemo(\n () =>\n debounce((): string[] => {\n if (document.visibilityState === 'hidden') {\n pendingOnScroll.current = true;\n return [];\n }\n if (!virtualListRef.current) return [];\n pendingOnScroll.current = false;\n const { bottom, top } = virtualListRef.current?.getBoundingClientRect() || {};\n\n const list = virtualListRef.current.querySelectorAll<HTMLElement>('[data-element=\"chat-element-list-item\"]');\n const indexList: Array<string> = [];\n list.forEach((item: HTMLElement) => {\n const { top: itemTop } = item.getBoundingClientRect();\n\n const itemPadding = 10;\n if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || '');\n });\n if (onScrollEnds) onScrollEnds(indexList);\n return indexList;\n }, 500),\n [onScrollEnds, pendingOnScroll, virtualListRef],\n ) as () => string[];\n\n const onlyFocus = React.useCallback(\n (index: string) => {\n (virtualListRef.current?.querySelector(`[data-index=\"${index}\"]`) as HTMLDivElement)?.focus();\n },\n [virtualListRef],\n );\n\n const scrollAndFocus = React.useCallback(\n (index: number) => {\n vScroll(index, { align: 'center' });\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, { align: 'center' });\n });\n\n setTimeout(() => {\n onlyFocus(index.toString());\n }, 300);\n\n onScrollStop();\n },\n [onScrollStop, onlyFocus, vScroll],\n );\n\n const checkPendingOnScroll = React.useCallback(() => {\n if (pendingOnScroll.current === true) onScrollStop();\n }, [onScrollStop, pendingOnScroll]);\n\n return React.useMemo(\n () => ({\n onScrollStop,\n onlyFocus,\n scrollAndFocus,\n checkPendingOnScroll,\n }),\n [onScrollStop, onlyFocus, scrollAndFocus, checkPendingOnScroll],\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAElB,SAAS,gBAAgB;AAUlB,MAAM,2BAA2B,CAAC;AAAA,EACvC,kBAAkB,EAAE,aAAa;AAAA,EACjC,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AACF,MAAoC;AAClC,QAAM,eAAeA,OAAM;AAAA,IACzB,MACE,SAAS,MAAgB;AACvB,UAAI,SAAS,oBAAoB,UAAU;AACzC,wBAAgB,UAAU;AAC1B,eAAO,CAAC;AAAA,MACV;AACA,UAAI,CAAC,eAAe,QAAS,QAAO,CAAC;AACrC,sBAAgB,UAAU;AAC1B,YAAM,EAAE,QAAQ,IAAI,IAAI,eAAe,SAAS,sBAAsB,KAAK,CAAC;AAE5E,YAAM,OAAO,eAAe,QAAQ,iBAA8B,yCAAyC;AAC3G,YAAM,YAA2B,CAAC;AAClC,WAAK,QAAQ,CAAC,SAAsB;AAClC,cAAM,EAAE,KAAK,QAAQ,IAAI,KAAK,sBAAsB;AAEpD,cAAM,cAAc;AACpB,YAAI,UAAU,cAAc,UAAU,UAAU,cAAc,IAAK,WAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAAA,MAC5G,CAAC;AACD,UAAI,aAAc,cAAa,SAAS;AACxC,aAAO;AAAA,IACT,GAAG,GAAG;AAAA,IACR,CAAC,cAAc,iBAAiB,cAAc;AAAA,EAChD;AAEA,QAAM,YAAYA,OAAM;AAAA,IACtB,CAAC,UAAkB;AACjB,MAAC,eAAe,SAAS,cAAc,gBAAgB,KAAK,IAAI,GAAsB,MAAM;AAAA,IAC9F;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,iBAAiBA,OAAM;AAAA,IAC3B,CAAC,UAAkB;AACjB,cAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAYlC,4BAAsB,MAAM;AAC1B,gBAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,MACpC,CAAC;AAED,iBAAW,MAAM;AACf,kBAAU,MAAM,SAAS,CAAC;AAAA,MAC5B,GAAG,GAAG;AAEN,mBAAa;AAAA,IACf;AAAA,IACA,CAAC,cAAc,WAAW,OAAO;AAAA,EACnC;AAEA,QAAM,uBAAuBA,OAAM,YAAY,MAAM;AACnD,QAAI,gBAAgB,YAAY,KAAM,cAAa;AAAA,EACrD,GAAG,CAAC,cAAc,eAAe,CAAC;AAElC,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,cAAc,WAAW,gBAAgB,oBAAoB;AAAA,EAChE;AACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport { debounce, throttle } from 'lodash-es';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseFocusAndScrollHelpersArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n useVirtualHelpers: ReturnType<typeof useVirtual>;\n pendingOnScroll: React.MutableRefObject<boolean>;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n};\n\nexport const useFocusAndScrollHelpers = ({\n propsWithDefault: { onScrollEnds },\n useVirtualHelpers: { scrollToIndex: vScroll },\n pendingOnScroll,\n virtualListRef,\n}: UseFocusAndScrollHelpersArgs) => {\n // Pure DOM read \u2014 no side effects beyond pendingOnScroll flag and getBoundingClientRect queries.\n const computeVisibleItems = React.useCallback((): string[] => {\n if (document.visibilityState === 'hidden') {\n pendingOnScroll.current = true;\n return [];\n }\n if (!virtualListRef.current) return [];\n pendingOnScroll.current = false;\n const { bottom, top } = virtualListRef.current.getBoundingClientRect();\n const list = virtualListRef.current.querySelectorAll<HTMLElement>('[data-element=\"chat-element-list-item\"]');\n const indexList: string[] = [];\n list.forEach((item: HTMLElement) => {\n const { top: itemTop } = item.getBoundingClientRect();\n const itemPadding = 10;\n if (itemTop + itemPadding < bottom && itemTop + itemPadding > top) indexList.push(item.dataset.index || '');\n });\n return indexList;\n }, [pendingOnScroll, virtualListRef]);\n\n // Throttled with leading: populates the cache immediately on first call and keeps it\n // fresh. No side effects beyond DOM reads \u2014 onScrollEnds is not involved.\n const visibleItemsCache = React.useRef<string[]>([]);\n const updateCache = React.useMemo(\n () =>\n throttle(\n () => {\n visibleItemsCache.current = computeVisibleItems();\n },\n 500,\n { leading: true },\n ),\n [computeVisibleItems],\n );\n\n // Synchronous getter \u2014 returns a copy so callers using .pop()/.shift() don't mutate the cache.\n const getMessagesInView = React.useCallback((): string[] => [...visibleItemsCache.current], []);\n\n // Debounced trailing: notifies onScrollEnds consumers after scrolling settles.\n // Semantics and timing unchanged \u2014 this path is isolated from the cache.\n const onScrollStop = React.useMemo(\n () =>\n debounce((): string[] => {\n const indexList = computeVisibleItems();\n if (onScrollEnds) onScrollEnds(indexList);\n return indexList;\n }, 500),\n [computeVisibleItems, onScrollEnds],\n ) as () => string[];\n\n const onlyFocus = React.useCallback(\n (index: string) => {\n (virtualListRef.current?.querySelector(`[data-index=\"${index}\"]`) as HTMLDivElement)?.focus();\n },\n [virtualListRef],\n );\n\n const scrollAndFocus = React.useCallback(\n (index: number) => {\n vScroll(index, { align: 'center' });\n /* [PUI-15629](https://jira.elliemae.io/browse/PUI-15629)\n * requestAnimationFrame is needed because the first scroll might not calculate positions\n * correctly if the DOM hasn't been fully updated yet. By waiting for the next animation\n * frame, we ensure that:\n * 1. The DOM has been updated with new positions after the first scroll\n * 2. Element height and position measurements are accurate\n * 3. The second scroll can center the element with correct measurements\n *\n * TODO: It might be worth consider upgrading to react-virtual v3(@tanstack/react-virtual), which handles DOM measurements and scroll\n * synchronization better. This RAF workaround might not be necessary with v3.\n */\n requestAnimationFrame(() => {\n vScroll(index, { align: 'center' });\n });\n\n setTimeout(() => {\n onlyFocus(index.toString());\n }, 300);\n\n updateCache();\n },\n [updateCache, onlyFocus, vScroll],\n );\n\n const checkPendingOnScroll = React.useCallback(() => {\n if (pendingOnScroll.current === true) {\n updateCache();\n onScrollStop();\n }\n }, [updateCache, onScrollStop, pendingOnScroll]);\n\n return React.useMemo(\n () => ({\n onScrollStop,\n updateCache,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n checkPendingOnScroll,\n }),\n [onScrollStop, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, checkPendingOnScroll],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACGvB,OAAOA,YAAW;AAElB,SAAS,UAAU,gBAAgB;AAU5B,MAAM,2BAA2B,CAAC;AAAA,EACvC,kBAAkB,EAAE,aAAa;AAAA,EACjC,mBAAmB,EAAE,eAAe,QAAQ;AAAA,EAC5C;AAAA,EACA;AACF,MAAoC;AAElC,QAAM,sBAAsBA,OAAM,YAAY,MAAgB;AAC5D,QAAI,SAAS,oBAAoB,UAAU;AACzC,sBAAgB,UAAU;AAC1B,aAAO,CAAC;AAAA,IACV;AACA,QAAI,CAAC,eAAe,QAAS,QAAO,CAAC;AACrC,oBAAgB,UAAU;AAC1B,UAAM,EAAE,QAAQ,IAAI,IAAI,eAAe,QAAQ,sBAAsB;AACrE,UAAM,OAAO,eAAe,QAAQ,iBAA8B,yCAAyC;AAC3G,UAAM,YAAsB,CAAC;AAC7B,SAAK,QAAQ,CAAC,SAAsB;AAClC,YAAM,EAAE,KAAK,QAAQ,IAAI,KAAK,sBAAsB;AACpD,YAAM,cAAc;AACpB,UAAI,UAAU,cAAc,UAAU,UAAU,cAAc,IAAK,WAAU,KAAK,KAAK,QAAQ,SAAS,EAAE;AAAA,IAC5G,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,cAAc,CAAC;AAIpC,QAAM,oBAAoBA,OAAM,OAAiB,CAAC,CAAC;AACnD,QAAM,cAAcA,OAAM;AAAA,IACxB,MACE;AAAA,MACE,MAAM;AACJ,0BAAkB,UAAU,oBAAoB;AAAA,MAClD;AAAA,MACA;AAAA,MACA,EAAE,SAAS,KAAK;AAAA,IAClB;AAAA,IACF,CAAC,mBAAmB;AAAA,EACtB;AAGA,QAAM,oBAAoBA,OAAM,YAAY,MAAgB,CAAC,GAAG,kBAAkB,OAAO,GAAG,CAAC,CAAC;AAI9F,QAAM,eAAeA,OAAM;AAAA,IACzB,MACE,SAAS,MAAgB;AACvB,YAAM,YAAY,oBAAoB;AACtC,UAAI,aAAc,cAAa,SAAS;AACxC,aAAO;AAAA,IACT,GAAG,GAAG;AAAA,IACR,CAAC,qBAAqB,YAAY;AAAA,EACpC;AAEA,QAAM,YAAYA,OAAM;AAAA,IACtB,CAAC,UAAkB;AACjB,MAAC,eAAe,SAAS,cAAc,gBAAgB,KAAK,IAAI,GAAsB,MAAM;AAAA,IAC9F;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,iBAAiBA,OAAM;AAAA,IAC3B,CAAC,UAAkB;AACjB,cAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAYlC,4BAAsB,MAAM;AAC1B,gBAAQ,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,MACpC,CAAC;AAED,iBAAW,MAAM;AACf,kBAAU,MAAM,SAAS,CAAC;AAAA,MAC5B,GAAG,GAAG;AAEN,kBAAY;AAAA,IACd;AAAA,IACA,CAAC,aAAa,WAAW,OAAO;AAAA,EAClC;AAEA,QAAM,uBAAuBA,OAAM,YAAY,MAAM;AACnD,QAAI,gBAAgB,YAAY,MAAM;AACpC,kBAAY;AACZ,mBAAa;AAAA,IACf;AAAA,EACF,GAAG,CAAC,aAAa,cAAc,eAAe,CAAC;AAE/C,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,cAAc,aAAa,mBAAmB,WAAW,gBAAgB,oBAAoB;AAAA,EAChG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -8,7 +8,7 @@ const useKeyboard = ({
8
8
  loadMoreRef,
9
9
  scrollAndFocus,
10
10
  onlyFocus,
11
- onScrollStop
11
+ getMessagesInView
12
12
  }) => {
13
13
  const handleKey = React2.useCallback(
14
14
  (e) => {
@@ -69,7 +69,7 @@ const useKeyboard = ({
69
69
  case "ArrowUp":
70
70
  e.preventDefault();
71
71
  if (document.activeElement !== loadMoreRef.current) {
72
- const id = onScrollStop()?.shift();
72
+ const id = getMessagesInView()?.shift();
73
73
  if (id) onlyFocus(id);
74
74
  }
75
75
  break;
@@ -78,7 +78,7 @@ const useKeyboard = ({
78
78
  if (document.activeElement === loadMoreRef.current) {
79
79
  virtualListRef.current?.querySelector(`[data-index="0"]`)?.focus();
80
80
  } else {
81
- const id = onScrollStop()?.pop();
81
+ const id = getMessagesInView()?.pop();
82
82
  if (id) onlyFocus(id);
83
83
  }
84
84
  break;
@@ -111,7 +111,16 @@ const useKeyboard = ({
111
111
  break;
112
112
  }
113
113
  },
114
- [actionRef, hasMoreItems, loadMoreRef, messages.length, onScrollStop, onlyFocus, scrollAndFocus, virtualListRef]
114
+ [
115
+ actionRef,
116
+ hasMoreItems,
117
+ loadMoreRef,
118
+ messages.length,
119
+ getMessagesInView,
120
+ onlyFocus,
121
+ scrollAndFocus,
122
+ virtualListRef
123
+ ]
115
124
  );
116
125
  return React2.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);
117
126
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/chat-container-messages-list/useKeyboard.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseKeyboardArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n actionRef: DSChatT.ActionRef;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n onlyFocus: (index: string) => void;\n onScrollStop: () => string[];\n // useVirtualHelpers: ReturnType<typeof useVirtual>;\n};\n\nconst getIsNumber = (val: unknown): val is number => Number.isInteger(val);\n\nexport const useKeyboard = ({\n propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef },\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n onScrollStop,\n}: UseKeyboardArgs) => {\n const handleKey = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>) => {\n const { key, currentTarget } = e;\n const index = currentTarget.dataset?.index ? Number(currentTarget.dataset.index) : undefined;\n const isIndexNumber = getIsNumber(index);\n e.stopPropagation();\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (index && index > 0) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index - 1}\"]`) as HTMLDivElement).focus();\n } else if (hasMoreItems === 'top') {\n loadMoreRef.current?.focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (messages?.length && isIndexNumber && index < messages.length - 1) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index + 1}\"]`) as HTMLDivElement).focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (hasMoreItems === 'top' && e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n if (bannerPosition) {\n e.preventDefault();\n bannerRef?.current?.focusOnWrapper();\n }\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [hasMoreItems, messages.length, scrollAndFocus, virtualListRef, loadMoreRef, bannerPosition, bannerRef],\n );\n const handleListKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (document.activeElement !== loadMoreRef.current) {\n const id = onScrollStop()?.shift();\n if (id) onlyFocus(id);\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (document.activeElement === loadMoreRef.current) {\n (virtualListRef.current?.querySelector(`[data-index=\"0\"]`) as HTMLDivElement)?.focus();\n } else {\n const id = onScrollStop()?.pop();\n if (id) onlyFocus(id);\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (document.activeElement !== loadMoreRef.current) {\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n }\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [actionRef, hasMoreItems, loadMoreRef, messages.length, onScrollStop, onlyFocus, scrollAndFocus, virtualListRef],\n );\n\n return React.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\n/* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n/* eslint-disable max-lines */\nimport React from 'react';\nimport type { DSChatT } from '../../react-desc-prop-types.js';\n\ntype UseKeyboardArgs = {\n propsWithDefault: DSChatT.MessagesListProps;\n actionRef: DSChatT.ActionRef;\n virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;\n loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;\n scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;\n onlyFocus: (index: string) => void;\n getMessagesInView: () => string[];\n};\n\nconst getIsNumber = (val: unknown): val is number => Number.isInteger(val);\n\nexport const useKeyboard = ({\n propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef },\n actionRef,\n virtualListRef,\n loadMoreRef,\n scrollAndFocus,\n onlyFocus,\n getMessagesInView,\n}: UseKeyboardArgs) => {\n const handleKey = React.useCallback(\n (e: React.KeyboardEvent<HTMLElement>) => {\n const { key, currentTarget } = e;\n const index = currentTarget.dataset?.index ? Number(currentTarget.dataset.index) : undefined;\n const isIndexNumber = getIsNumber(index);\n e.stopPropagation();\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (index && index > 0) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index - 1}\"]`) as HTMLDivElement).focus();\n } else if (hasMoreItems === 'top') {\n loadMoreRef.current?.focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (messages?.length && isIndexNumber && index < messages.length - 1) {\n (virtualListRef.current?.querySelector(`[data-index=\"${index + 1}\"]`) as HTMLDivElement).focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (hasMoreItems === 'top' && e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n if (bannerPosition) {\n e.preventDefault();\n bannerRef?.current?.focusOnWrapper();\n }\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [hasMoreItems, messages.length, scrollAndFocus, virtualListRef, loadMoreRef, bannerPosition, bannerRef],\n );\n const handleListKey = React.useCallback(\n (e: React.KeyboardEvent) => {\n const { key } = e;\n switch (key) {\n case 'ArrowUp':\n e.preventDefault();\n if (document.activeElement !== loadMoreRef.current) {\n const id = getMessagesInView()?.shift();\n if (id) onlyFocus(id);\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (document.activeElement === loadMoreRef.current) {\n (virtualListRef.current?.querySelector(`[data-index=\"0\"]`) as HTMLDivElement)?.focus();\n } else {\n const id = getMessagesInView()?.pop();\n if (id) onlyFocus(id);\n }\n break;\n case 'Home':\n e.preventDefault();\n scrollAndFocus(0);\n break;\n case 'End':\n e.preventDefault();\n if (messages?.length) scrollAndFocus(messages.length - 1);\n break;\n case 'Tab':\n if (document.activeElement !== loadMoreRef.current) {\n if (hasMoreItems === 'bottom' && !e.shiftKey) {\n e.preventDefault();\n loadMoreRef.current?.focus();\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n }\n } else if (!e.shiftKey) {\n e.preventDefault();\n actionRef.current?.focusToComposer?.();\n } else {\n e.preventDefault();\n virtualListRef.current?.focus();\n }\n break;\n default:\n break;\n }\n },\n [\n actionRef,\n hasMoreItems,\n loadMoreRef,\n messages.length,\n getMessagesInView,\n onlyFocus,\n scrollAndFocus,\n virtualListRef,\n ],\n );\n\n return React.useMemo(() => ({ handleKey, handleListKey }), [handleKey, handleListKey]);\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["React"]
7
7
  }
@@ -5,9 +5,10 @@ type UseActionRefArgs = {
5
5
  actionRef: DSChatT.ActionRef;
6
6
  useVirtualHelpers: ReturnType<typeof useVirtual>;
7
7
  virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;
8
- onScrollStop: () => string[];
8
+ updateCache: () => void;
9
+ getMessagesInView: () => string[];
9
10
  onlyFocus: (index: string) => void;
10
11
  scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;
11
12
  };
12
- export declare const useActionRef: ({ actionRef, useVirtualHelpers: { scrollToIndex: vScroll }, virtualListRef, onScrollStop, onlyFocus, scrollAndFocus, }: UseActionRefArgs) => void;
13
+ export declare const useActionRef: ({ actionRef, useVirtualHelpers: { scrollToIndex: vScroll }, virtualListRef, updateCache, getMessagesInView, onlyFocus, scrollAndFocus, }: UseActionRefArgs) => void;
13
14
  export {};
@@ -9,6 +9,8 @@ type UseFocusAndScrollHelpersArgs = {
9
9
  };
10
10
  export declare const useFocusAndScrollHelpers: ({ propsWithDefault: { onScrollEnds }, useVirtualHelpers: { scrollToIndex: vScroll }, pendingOnScroll, virtualListRef, }: UseFocusAndScrollHelpersArgs) => {
11
11
  onScrollStop: () => string[];
12
+ updateCache: import("lodash").DebouncedFuncLeading<() => void>;
13
+ getMessagesInView: () => string[];
12
14
  onlyFocus: (index: string) => void;
13
15
  scrollAndFocus: (index: number) => void;
14
16
  checkPendingOnScroll: () => void;
@@ -7,9 +7,9 @@ type UseKeyboardArgs = {
7
7
  loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;
8
8
  scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;
9
9
  onlyFocus: (index: string) => void;
10
- onScrollStop: () => string[];
10
+ getMessagesInView: () => string[];
11
11
  };
12
- export declare const useKeyboard: ({ propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef }, actionRef, virtualListRef, loadMoreRef, scrollAndFocus, onlyFocus, onScrollStop, }: UseKeyboardArgs) => {
12
+ export declare const useKeyboard: ({ propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef }, actionRef, virtualListRef, loadMoreRef, scrollAndFocus, onlyFocus, getMessagesInView, }: UseKeyboardArgs) => {
13
13
  handleKey: (e: React.KeyboardEvent<HTMLElement>) => void;
14
14
  handleListKey: (e: React.KeyboardEvent) => void;
15
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-chat-container",
3
- "version": "3.70.0-next.41",
3
+ "version": "3.70.0-next.43",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Chat Container",
6
6
  "files": [
@@ -37,25 +37,26 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "react-virtual": "~2.10.4",
40
- "@elliemae/ds-banner": "3.70.0-next.41",
41
- "@elliemae/ds-button-v2": "3.70.0-next.41",
42
- "@elliemae/ds-chat-container-header": "3.70.0-next.41",
43
- "@elliemae/ds-chat-message-delimeter": "3.70.0-next.41",
44
- "@elliemae/ds-chat-system-message": "3.70.0-next.41",
45
- "@elliemae/ds-chat-bubble": "3.70.0-next.41",
46
- "@elliemae/ds-grid": "3.70.0-next.41",
47
- "@elliemae/ds-icons": "3.70.0-next.41",
48
- "@elliemae/ds-indeterminate-progress-indicator": "3.70.0-next.41",
49
- "@elliemae/ds-props-helpers": "3.70.0-next.41",
50
- "@elliemae/ds-system": "3.70.0-next.41",
51
- "@elliemae/ds-typescript-helpers": "3.70.0-next.41"
40
+ "@elliemae/ds-banner": "3.70.0-next.43",
41
+ "@elliemae/ds-button-v2": "3.70.0-next.43",
42
+ "@elliemae/ds-chat-bubble": "3.70.0-next.43",
43
+ "@elliemae/ds-chat-container-header": "3.70.0-next.43",
44
+ "@elliemae/ds-chat-message-delimeter": "3.70.0-next.43",
45
+ "@elliemae/ds-chat-system-message": "3.70.0-next.43",
46
+ "@elliemae/ds-grid": "3.70.0-next.43",
47
+ "@elliemae/ds-indeterminate-progress-indicator": "3.70.0-next.43",
48
+ "@elliemae/ds-icons": "3.70.0-next.43",
49
+ "@elliemae/ds-props-helpers": "3.70.0-next.43",
50
+ "@elliemae/ds-system": "3.70.0-next.43",
51
+ "@elliemae/ds-typescript-helpers": "3.70.0-next.43"
52
52
  },
53
53
  "devDependencies": {
54
+ "@playwright/experimental-ct-react": "^1.60.0",
54
55
  "@types/react": "^18.0.0",
55
56
  "jest": "^30.0.0",
56
57
  "styled-components": "~5.3.9",
57
- "@elliemae/ds-monorepo-devops": "3.70.0-next.41",
58
- "@elliemae/ds-test-utils": "3.70.0-next.41"
58
+ "@elliemae/ds-monorepo-devops": "3.70.0-next.43",
59
+ "@elliemae/ds-test-utils": "3.70.0-next.43"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "lodash-es": "^4.18.1",
@@ -64,7 +65,7 @@
64
65
  "styled-components": "~5.3.9"
65
66
  },
66
67
  "scripts": {
67
- "test": "ds-monorepo-devops test --passWithNoTests --coverage=\"false\"",
68
+ "test": "playwright test -c ./playwright.config.mjs && ds-monorepo-devops test --passWithNoTests --coverage=\"false\"",
68
69
  "lint": "node ../../../scripts/lint.mjs --fix",
69
70
  "lint:strict": "node ../../../scripts/lint-strict.mjs",
70
71
  "dts": "node ../../../scripts/dts.mjs",