@elliemae/ds-chat-container 3.80.0-next.31 → 3.80.0-next.35

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 (52) hide show
  1. package/dist/cjs/DSChatContainerDefinitions.js +7 -1
  2. package/dist/cjs/DSChatContainerDefinitions.js.map +2 -2
  3. package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js +134 -71
  4. package/dist/cjs/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
  5. package/dist/cjs/parts/chat-container-messages-list/styled.js +33 -43
  6. package/dist/cjs/parts/chat-container-messages-list/styled.js.map +2 -2
  7. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js +3 -9
  8. package/dist/cjs/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  9. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js +30 -22
  10. package/dist/cjs/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  11. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +38 -38
  12. package/dist/cjs/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  13. package/dist/cjs/parts/chat-container-messages-list/useGlobalEventListener.js.map +1 -1
  14. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js +8 -15
  15. package/dist/cjs/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  16. package/dist/cjs/parts/chat-container-messages-list/useMessageFocusTracker.js +132 -0
  17. package/dist/cjs/parts/chat-container-messages-list/useMessageFocusTracker.js.map +7 -0
  18. package/dist/cjs/react-desc-prop-types.js +39 -23
  19. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  20. package/dist/cjs/typescript-testing/typescript-chat-container-valid.js +31 -0
  21. package/dist/cjs/typescript-testing/typescript-chat-container-valid.js.map +2 -2
  22. package/dist/esm/DSChatContainerDefinitions.js +7 -1
  23. package/dist/esm/DSChatContainerDefinitions.js.map +2 -2
  24. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js +135 -74
  25. package/dist/esm/parts/chat-container-messages-list/ChatContainerMessagesList.js.map +2 -2
  26. package/dist/esm/parts/chat-container-messages-list/styled.js +33 -43
  27. package/dist/esm/parts/chat-container-messages-list/styled.js.map +2 -2
  28. package/dist/esm/parts/chat-container-messages-list/useActionRef.js +3 -9
  29. package/dist/esm/parts/chat-container-messages-list/useActionRef.js.map +2 -2
  30. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js +30 -22
  31. package/dist/esm/parts/chat-container-messages-list/useChatContainerMessageList.js.map +2 -2
  32. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js +39 -39
  33. package/dist/esm/parts/chat-container-messages-list/useFocusAndScrollHelpers.js.map +2 -2
  34. package/dist/esm/parts/chat-container-messages-list/useGlobalEventListener.js.map +1 -1
  35. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js +8 -15
  36. package/dist/esm/parts/chat-container-messages-list/useKeyboard.js.map +2 -2
  37. package/dist/esm/parts/chat-container-messages-list/useMessageFocusTracker.js +102 -0
  38. package/dist/esm/parts/chat-container-messages-list/useMessageFocusTracker.js.map +7 -0
  39. package/dist/esm/react-desc-prop-types.js +40 -24
  40. package/dist/esm/react-desc-prop-types.js.map +2 -2
  41. package/dist/esm/typescript-testing/typescript-chat-container-valid.js +31 -0
  42. package/dist/esm/typescript-testing/typescript-chat-container-valid.js.map +2 -2
  43. package/dist/types/DSChatContainerDefinitions.d.ts +8 -0
  44. package/dist/types/parts/chat-container-messages-list/styled.d.ts +18 -5
  45. package/dist/types/parts/chat-container-messages-list/useActionRef.d.ts +4 -6
  46. package/dist/types/parts/chat-container-messages-list/useChatContainerMessageList.d.ts +7 -2
  47. package/dist/types/parts/chat-container-messages-list/useFocusAndScrollHelpers.d.ts +9 -5
  48. package/dist/types/parts/chat-container-messages-list/useGlobalEventListener.d.ts +1 -1
  49. package/dist/types/parts/chat-container-messages-list/useKeyboard.d.ts +7 -3
  50. package/dist/types/parts/chat-container-messages-list/useMessageFocusTracker.d.ts +52 -0
  51. package/dist/types/react-desc-prop-types.d.ts +798 -793
  52. package/package.json +16 -16
@@ -1,13 +1,18 @@
1
1
  import React from 'react';
2
2
  import { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';
3
+ import type { DSFastListT } from '@elliemae/ds-fast-list';
3
4
  import { useKeyboard } from './useKeyboard.js';
5
+ import { useMessageFocusTracker } from './useMessageFocusTracker.js';
4
6
  import type { DSChatT } from '../../react-desc-prop-types.js';
5
7
  type UseChatContainerMessageList = (props: DSChatT.MessagesListProps) => {
6
8
  propsWithDefault: DSChatT.MessagesListProps;
7
9
  globalAttributes: ReturnType<typeof useGetGlobalAttributes>;
8
- useVirtualHelpers: DSChatT.ChatVirtualizer;
10
+ fastListActionRef: React.MutableRefObject<DSFastListT.ActionRef>;
11
+ paddingStart: number;
12
+ paddingEnd: number;
9
13
  loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;
10
- virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;
14
+ virtualListRef: React.MutableRefObject<HTMLDivElement | null>;
15
+ focusTracker: ReturnType<typeof useMessageFocusTracker>;
11
16
  } & ReturnType<typeof useKeyboard>;
12
17
  export declare const useChatContainerMessageList: UseChatContainerMessageList;
13
18
  export {};
@@ -1,17 +1,21 @@
1
1
  import React from 'react';
2
+ import type { DSFastListT } from '@elliemae/ds-fast-list';
2
3
  import type { DSChatT } from '../../react-desc-prop-types.js';
4
+ import type { MessageId } from './useMessageFocusTracker.js';
3
5
  type UseFocusAndScrollHelpersArgs = {
4
6
  propsWithDefault: DSChatT.MessagesListProps;
5
- useVirtualHelpers: DSChatT.ChatVirtualizer;
7
+ fastListActionRef: React.MutableRefObject<DSFastListT.ActionRef>;
6
8
  pendingOnScroll: React.MutableRefObject<boolean>;
7
- virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;
9
+ trackFocusMessage: (messageId: MessageId, options?: {
10
+ preventScroll?: boolean;
11
+ }) => void;
8
12
  };
9
- export declare const useFocusAndScrollHelpers: ({ propsWithDefault: { onScrollEnds }, useVirtualHelpers: { scrollToIndex: vScroll, calculateRange }, pendingOnScroll, virtualListRef, }: UseFocusAndScrollHelpersArgs) => {
13
+ export declare const useFocusAndScrollHelpers: ({ propsWithDefault: { onScrollEnds, messages }, fastListActionRef, pendingOnScroll, trackFocusMessage, }: UseFocusAndScrollHelpersArgs) => {
14
+ vScroll: (index: number, opts?: DSChatT.ScrollActionOptions) => void;
10
15
  onScrollStop: () => string[];
11
- updateCache: import("lodash").DebouncedFuncLeading<() => void>;
12
16
  getMessagesInView: () => string[];
13
17
  onlyFocus: (index: string) => void;
14
- scrollAndFocus: (index: number) => void;
18
+ scrollAndFocus: (index: number, opts?: DSChatT.ScrollActionOptions) => void;
15
19
  checkPendingOnScroll: () => void;
16
20
  };
17
21
  export {};
@@ -3,7 +3,7 @@ import { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';
3
3
  import { type DSChatT } from '../../react-desc-prop-types.js';
4
4
  type UseGlobalEventListenerArgs = {
5
5
  propsWithDefault: DSChatT.MessagesListProps;
6
- virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;
6
+ virtualListRef: React.MutableRefObject<HTMLDivElement | null>;
7
7
  onScrollStop: () => string[];
8
8
  checkPendingOnScroll: TypescriptHelpersT.GenericFunc;
9
9
  };
@@ -1,15 +1,19 @@
1
1
  import React from 'react';
2
2
  import type { DSChatT } from '../../react-desc-prop-types.js';
3
+ import type { MessageId } from './useMessageFocusTracker.js';
3
4
  type UseKeyboardArgs = {
4
5
  propsWithDefault: DSChatT.MessagesListProps;
5
6
  actionRef: DSChatT.ActionRef;
6
- virtualListRef: React.MutableRefObject<HTMLDivElement | undefined>;
7
+ virtualListRef: React.MutableRefObject<HTMLDivElement | null>;
7
8
  loadMoreRef: React.MutableRefObject<HTMLButtonElement | undefined>;
8
- scrollAndFocus: (index: number, opts?: DSChatT.ScrollToIndexOptions) => void;
9
+ scrollAndFocus: (index: number, opts?: DSChatT.ScrollActionOptions) => void;
9
10
  onlyFocus: (index: string) => void;
10
11
  getMessagesInView: () => string[];
12
+ trackFocusMessage: (messageId: MessageId, options?: {
13
+ preventScroll?: boolean;
14
+ }) => void;
11
15
  };
12
- export declare const useKeyboard: ({ propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef }, actionRef, virtualListRef, loadMoreRef, scrollAndFocus, onlyFocus, getMessagesInView, }: UseKeyboardArgs) => {
16
+ export declare const useKeyboard: ({ propsWithDefault: { hasMoreItems, messages, bannerPosition, bannerRef }, actionRef, virtualListRef, loadMoreRef, scrollAndFocus, onlyFocus, getMessagesInView, trackFocusMessage, }: UseKeyboardArgs) => {
13
17
  handleKey: (e: React.KeyboardEvent<HTMLElement>) => void;
14
18
  handleListKey: (e: React.KeyboardEvent) => void;
15
19
  };
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ /** Focus identity of a message, from `getMessageFocusId`. */
3
+ export type MessageId = string;
4
+ /**
5
+ * Identity the focus intent is kept by: the message's `dsId`, which survives index shifts. `dsId` is required by
6
+ * the types but not at runtime, so a message without one falls back to its index (the focus then follows the
7
+ * position, as it did before the focus tracker) instead of matching every other id-less message. The two forms
8
+ * carry different prefixes so a `dsId` can never equal an index fallback, and the type of the `dsId` is kept so
9
+ * `3` and `'3'` stay different messages, as with a direct comparison.
10
+ */
11
+ export declare const getMessageFocusId: (message: {
12
+ dsId?: string | number | null;
13
+ }, index: number) => MessageId;
14
+ /**
15
+ * Target by position, for a request made before the message exists in the rendered list (for example
16
+ * `focusToIndex` called right after the consumer adds a message): the item at that index focuses itself when it
17
+ * mounts, and its real focus then moves the intent to its identity.
18
+ */
19
+ export declare const getMessagePositionId: (index: number) => MessageId;
20
+ export type MessageFocusRequest = {
21
+ /** Identity of the message to focus, from `getMessageFocusId`. */
22
+ messageId: MessageId;
23
+ /** Incremented by every explicit request, so asking again for the current target focuses it again. */
24
+ requestId: number;
25
+ /** `true` when the caller scrolls to the message itself, so focusing must not scroll as well. */
26
+ preventScroll: boolean;
27
+ };
28
+ type TrackFocusOptions = {
29
+ preventScroll?: boolean;
30
+ };
31
+ /**
32
+ * Message focus through the focus-tracker pattern: handlers declare which message should have the focus, and
33
+ * only that message's `ItemRenderer` focuses itself from its ref callback, once React has committed it. Nothing
34
+ * here moves the focus directly.
35
+ *
36
+ * Removing a focused message never clears the intent: React does not dispatch `onBlur` for a focused node it
37
+ * removes itself (measured for a prepend and for a message scrolled out of the virtual window). The intent is
38
+ * cleared by real focus moves: leaving the list (`handleFocusOut`), a `focusin` on a non-message element of the
39
+ * list, any `focusin` outside the list while an intent exists (also when the focus was on the page, where no
40
+ * event crosses the list), and a remount that finds the focus elsewhere (`mayTakeFocus`).
41
+ */
42
+ export declare const useMessageFocusTracker: (virtualListRef: React.MutableRefObject<HTMLDivElement | null>) => {
43
+ focusRequest: MessageFocusRequest | null;
44
+ trackFocusMessage: (messageId: MessageId, { preventScroll }?: TrackFocusOptions) => void;
45
+ trackFocusResetter: () => void;
46
+ trackFocusedMessage: (messageId: MessageId) => void;
47
+ mayTakeFocus: (requestId: number, target: Element | null) => "request" | "restore" | null;
48
+ markFulfilled: (requestId: number) => void;
49
+ handleFocusOut: (e: React.FocusEvent<HTMLElement>) => void;
50
+ listRootRef: (node: HTMLElement | null) => void;
51
+ };
52
+ export {};