@elliemae/ds-fast-list 3.80.0-next.31 → 3.80.0-next.36

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.
@@ -3,6 +3,7 @@ import React2 from "react";
3
3
  import { uid } from "uid";
4
4
  import { useVirtualizer } from "@tanstack/react-virtual";
5
5
  import { useMemoMergePropsWithDefault } from "@elliemae/ds-props-helpers";
6
+ import { setMultipleRefs } from "@elliemae/ds-system";
6
7
  import { DSFastListPropTypes, defaultProps } from "../react-desc-prop-types.js";
7
8
  import { useValidateProps } from "./useValidateProps.js";
8
9
  const useFastList = (propsFromUser) => {
@@ -11,13 +12,19 @@ const useFastList = (propsFromUser) => {
11
12
  defaultProps
12
13
  );
13
14
  useValidateProps(propsWithDefault, DSFastListPropTypes);
14
- const { actionRef, count, estimateSize } = propsWithDefault;
15
+ const { actionRef, count, estimateSize, paddingStart, paddingEnd, innerRef, remountOnCountChange } = propsWithDefault;
15
16
  const parentRef = React2.useRef(null);
17
+ const containerRef = React2.useMemo(
18
+ () => innerRef ? setMultipleRefs([parentRef, innerRef]) : parentRef,
19
+ [innerRef]
20
+ );
16
21
  const useVirtualHelpers = useVirtualizer({
17
22
  count,
18
23
  getScrollElement: () => parentRef.current,
19
24
  overscan: 15,
20
- estimateSize
25
+ estimateSize,
26
+ paddingStart,
27
+ paddingEnd
21
28
  });
22
29
  const totalSize = useVirtualHelpers.getTotalSize();
23
30
  if (actionRef && actionRef.current) {
@@ -26,22 +33,33 @@ const useFastList = (propsFromUser) => {
26
33
  actionRef.current.getVisibleItems = () => {
27
34
  const range = useVirtualHelpers.calculateRange();
28
35
  if (!range) return [];
36
+ const viewportStart = useVirtualHelpers.scrollOffset ?? 0;
37
+ const viewportEnd = viewportStart + (useVirtualHelpers.scrollRect?.height ?? 0);
29
38
  const indices = [];
30
- for (let index = range.startIndex; index <= range.endIndex; index += 1) indices.push(index);
39
+ for (let index = range.startIndex; index <= range.endIndex; index += 1) {
40
+ const item = useVirtualHelpers.measurementsCache[index];
41
+ if (item && item.end > viewportStart && item.start < viewportEnd) indices.push(index);
42
+ }
31
43
  return indices;
32
44
  };
33
45
  actionRef.current.getMountedItems = () => useVirtualHelpers.getVirtualItems().map((item) => item.index);
46
+ actionRef.current.getOffsetForIndex = (index, align) => useVirtualHelpers.getOffsetForIndex(index, align)?.[0];
47
+ actionRef.current.scrollToOffset = useVirtualHelpers.scrollToOffset;
34
48
  }
35
- const instanceUid = React2.useMemo(() => `ds-fast-list-${uid(6)}${count}`, [count]);
49
+ const stableUid = React2.useMemo(() => uid(6), []);
50
+ const instanceUid = React2.useMemo(
51
+ () => remountOnCountChange === false ? `ds-fast-list-${stableUid}` : `ds-fast-list-${uid(6)}${count}`,
52
+ [count, remountOnCountChange, stableUid]
53
+ );
36
54
  return React2.useMemo(
37
55
  () => ({
38
56
  instanceUid,
39
- parentRef,
57
+ containerRef,
40
58
  getVirtualItems: useVirtualHelpers.getVirtualItems,
41
59
  totalSize,
42
60
  measureElement: useVirtualHelpers.measureElement
43
61
  }),
44
- [useVirtualHelpers.getVirtualItems, useVirtualHelpers.measureElement, totalSize, instanceUid]
62
+ [useVirtualHelpers.getVirtualItems, useVirtualHelpers.measureElement, totalSize, instanceUid, containerRef]
45
63
  );
46
64
  };
47
65
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/hooks/useFastList.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { uid } from 'uid';\nimport { useVirtualizer, type Virtualizer } from '@tanstack/react-virtual';\nimport { useMemoMergePropsWithDefault } from '@elliemae/ds-props-helpers';\nimport { type DSFastListT, DSFastListPropTypes, defaultProps } from '../react-desc-prop-types.js';\nimport { useValidateProps } from './useValidateProps.js';\n\nexport type FastListCTX = {\n instanceUid: string;\n parentRef: React.MutableRefObject<HTMLDivElement | null>;\n getVirtualItems: Virtualizer<HTMLDivElement, HTMLElement>['getVirtualItems'];\n totalSize: ReturnType<Virtualizer<HTMLDivElement, HTMLElement>['getTotalSize']>;\n measureElement: Virtualizer<HTMLDivElement, HTMLElement>['measureElement'];\n};\nexport const useFastList = <T,>(propsFromUser: DSFastListT.Props<T>): FastListCTX => {\n // =============================================================================\n // MERGE WITH DEFAULT AND VALIDATE PROPS\n // =============================================================================\n const propsWithDefault = useMemoMergePropsWithDefault<DSFastListT.InternalProps<T>>(\n propsFromUser,\n defaultProps as Partial<DSFastListT.InternalProps<T>>,\n );\n useValidateProps(propsWithDefault, DSFastListPropTypes);\n // =============================================================================\n // AD HOC PER COMPONENT LOGIC\n // =============================================================================\n const { actionRef, count, estimateSize } = propsWithDefault;\n const parentRef = React.useRef<HTMLDivElement>(null);\n const useVirtualHelpers = useVirtualizer({\n count,\n getScrollElement: () => parentRef.current,\n overscan: 15,\n estimateSize,\n });\n const totalSize = useVirtualHelpers.getTotalSize();\n\n if (actionRef && actionRef.current) {\n actionRef.current.scrollTo = useVirtualHelpers.scrollToIndex;\n actionRef.current.measure = useVirtualHelpers.measure;\n // `getVirtualItems()` includes the overscan buffer on each side \u2014 not what \"visible\" means.\n // `calculateRange()` is the virtualizer's own pre-overscan viewport calculation (pure scroll\n // geometry, no DOM scraping) and is what \"currently visible\" should actually be backed by.\n actionRef.current.getVisibleItems = () => {\n const range = useVirtualHelpers.calculateRange();\n if (!range) return [];\n const indices: number[] = [];\n for (let index = range.startIndex; index <= range.endIndex; index += 1) indices.push(index);\n return indices;\n };\n // The overscanned set (viewport + the 15-item buffer on each side) \u2014 everything currently\n // mounted in the DOM, as opposed to `getVisibleItems()`'s true-viewport-only set above.\n actionRef.current.getMountedItems = () => useVirtualHelpers.getVirtualItems().map((item) => item.index);\n }\n\n const instanceUid = React.useMemo(() => `ds-fast-list-${uid(6)}${count}`, [count]);\n return React.useMemo(\n () => ({\n instanceUid,\n parentRef,\n getVirtualItems: useVirtualHelpers.getVirtualItems,\n totalSize,\n measureElement: useVirtualHelpers.measureElement,\n }),\n [useVirtualHelpers.getVirtualItems, useVirtualHelpers.measureElement, totalSize, instanceUid],\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,YAAW;AAClB,SAAS,WAAW;AACpB,SAAS,sBAAwC;AACjD,SAAS,oCAAoC;AAC7C,SAA2B,qBAAqB,oBAAoB;AACpE,SAAS,wBAAwB;AAS1B,MAAM,cAAc,CAAK,kBAAqD;AAInF,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,EACF;AACA,mBAAiB,kBAAkB,mBAAmB;AAItD,QAAM,EAAE,WAAW,OAAO,aAAa,IAAI;AAC3C,QAAM,YAAYA,OAAM,OAAuB,IAAI;AACnD,QAAM,oBAAoB,eAAe;AAAA,IACvC;AAAA,IACA,kBAAkB,MAAM,UAAU;AAAA,IAClC,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AACD,QAAM,YAAY,kBAAkB,aAAa;AAEjD,MAAI,aAAa,UAAU,SAAS;AAClC,cAAU,QAAQ,WAAW,kBAAkB;AAC/C,cAAU,QAAQ,UAAU,kBAAkB;AAI9C,cAAU,QAAQ,kBAAkB,MAAM;AACxC,YAAM,QAAQ,kBAAkB,eAAe;AAC/C,UAAI,CAAC,MAAO,QAAO,CAAC;AACpB,YAAM,UAAoB,CAAC;AAC3B,eAAS,QAAQ,MAAM,YAAY,SAAS,MAAM,UAAU,SAAS,EAAG,SAAQ,KAAK,KAAK;AAC1F,aAAO;AAAA,IACT;AAGA,cAAU,QAAQ,kBAAkB,MAAM,kBAAkB,gBAAgB,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;AAAA,EACxG;AAEA,QAAM,cAAcA,OAAM,QAAQ,MAAM,gBAAgB,IAAI,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC;AACjF,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,iBAAiB,kBAAkB;AAAA,MACnC;AAAA,MACA,gBAAgB,kBAAkB;AAAA,IACpC;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,gBAAgB,WAAW,WAAW;AAAA,EAC9F;AACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { uid } from 'uid';\nimport { useVirtualizer, type Virtualizer } from '@tanstack/react-virtual';\nimport { useMemoMergePropsWithDefault } from '@elliemae/ds-props-helpers';\nimport { setMultipleRefs } from '@elliemae/ds-system';\nimport { type DSFastListT, DSFastListPropTypes, defaultProps } from '../react-desc-prop-types.js';\nimport { useValidateProps } from './useValidateProps.js';\n\nexport type FastListCTX = {\n instanceUid: string;\n containerRef: React.MutableRefObject<HTMLDivElement | null> | React.RefCallback<HTMLDivElement>;\n getVirtualItems: Virtualizer<HTMLDivElement, HTMLElement>['getVirtualItems'];\n totalSize: ReturnType<Virtualizer<HTMLDivElement, HTMLElement>['getTotalSize']>;\n measureElement: Virtualizer<HTMLDivElement, HTMLElement>['measureElement'];\n};\nexport const useFastList = <T,>(propsFromUser: DSFastListT.Props<T>): FastListCTX => {\n // =============================================================================\n // MERGE WITH DEFAULT AND VALIDATE PROPS\n // =============================================================================\n const propsWithDefault = useMemoMergePropsWithDefault<DSFastListT.InternalProps<T>>(\n propsFromUser,\n defaultProps as Partial<DSFastListT.InternalProps<T>>,\n );\n useValidateProps(propsWithDefault, DSFastListPropTypes);\n // =============================================================================\n // AD HOC PER COMPONENT LOGIC\n // =============================================================================\n const { actionRef, count, estimateSize, paddingStart, paddingEnd, innerRef, remountOnCountChange } = propsWithDefault;\n const parentRef = React.useRef<HTMLDivElement>(null);\n const containerRef = React.useMemo(\n () => (innerRef ? setMultipleRefs<HTMLDivElement>([parentRef, innerRef]) : parentRef),\n [innerRef],\n );\n const useVirtualHelpers = useVirtualizer({\n count,\n getScrollElement: () => parentRef.current,\n overscan: 15,\n estimateSize,\n paddingStart,\n paddingEnd,\n });\n const totalSize = useVirtualHelpers.getTotalSize();\n\n if (actionRef && actionRef.current) {\n actionRef.current.scrollTo = useVirtualHelpers.scrollToIndex;\n actionRef.current.measure = useVirtualHelpers.measure;\n // `getVirtualItems()` includes the overscan buffer on each side \u2014 not what \"visible\" means.\n // `calculateRange()` is the virtualizer's own pre-overscan viewport calculation (pure scroll\n // geometry, no DOM scraping) and is what \"currently visible\" should actually be backed by.\n actionRef.current.getVisibleItems = () => {\n const range = useVirtualHelpers.calculateRange();\n if (!range) return [];\n /**\n * `calculateRange()` always seeds the item nearest to the scroll offset, even when only padding is in view\n * (a `paddingStart` or `paddingEnd` larger than the viewport), so each index is kept only if its item\n * actually intersects the viewport.\n */\n const viewportStart = useVirtualHelpers.scrollOffset ?? 0;\n const viewportEnd = viewportStart + (useVirtualHelpers.scrollRect?.height ?? 0);\n const indices: number[] = [];\n for (let index = range.startIndex; index <= range.endIndex; index += 1) {\n const item = useVirtualHelpers.measurementsCache[index];\n if (item && item.end > viewportStart && item.start < viewportEnd) indices.push(index);\n }\n return indices;\n };\n // The overscanned set (viewport + the 15-item buffer on each side) \u2014 everything currently\n // mounted in the DOM, as opposed to `getVisibleItems()`'s true-viewport-only set above.\n actionRef.current.getMountedItems = () => useVirtualHelpers.getVirtualItems().map((item) => item.index);\n actionRef.current.getOffsetForIndex = (index, align) => useVirtualHelpers.getOffsetForIndex(index, align)?.[0];\n actionRef.current.scrollToOffset = useVirtualHelpers.scrollToOffset;\n }\n\n const stableUid = React.useMemo(() => uid(6), []);\n const instanceUid = React.useMemo(\n () => (remountOnCountChange === false ? `ds-fast-list-${stableUid}` : `ds-fast-list-${uid(6)}${count}`),\n [count, remountOnCountChange, stableUid],\n );\n return React.useMemo(\n () => ({\n instanceUid,\n containerRef,\n getVirtualItems: useVirtualHelpers.getVirtualItems,\n totalSize,\n measureElement: useVirtualHelpers.measureElement,\n }),\n [useVirtualHelpers.getVirtualItems, useVirtualHelpers.measureElement, totalSize, instanceUid, containerRef],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,YAAW;AAClB,SAAS,WAAW;AACpB,SAAS,sBAAwC;AACjD,SAAS,oCAAoC;AAC7C,SAAS,uBAAuB;AAChC,SAA2B,qBAAqB,oBAAoB;AACpE,SAAS,wBAAwB;AAS1B,MAAM,cAAc,CAAK,kBAAqD;AAInF,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,EACF;AACA,mBAAiB,kBAAkB,mBAAmB;AAItD,QAAM,EAAE,WAAW,OAAO,cAAc,cAAc,YAAY,UAAU,qBAAqB,IAAI;AACrG,QAAM,YAAYA,OAAM,OAAuB,IAAI;AACnD,QAAM,eAAeA,OAAM;AAAA,IACzB,MAAO,WAAW,gBAAgC,CAAC,WAAW,QAAQ,CAAC,IAAI;AAAA,IAC3E,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,oBAAoB,eAAe;AAAA,IACvC;AAAA,IACA,kBAAkB,MAAM,UAAU;AAAA,IAClC,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,YAAY,kBAAkB,aAAa;AAEjD,MAAI,aAAa,UAAU,SAAS;AAClC,cAAU,QAAQ,WAAW,kBAAkB;AAC/C,cAAU,QAAQ,UAAU,kBAAkB;AAI9C,cAAU,QAAQ,kBAAkB,MAAM;AACxC,YAAM,QAAQ,kBAAkB,eAAe;AAC/C,UAAI,CAAC,MAAO,QAAO,CAAC;AAMpB,YAAM,gBAAgB,kBAAkB,gBAAgB;AACxD,YAAM,cAAc,iBAAiB,kBAAkB,YAAY,UAAU;AAC7E,YAAM,UAAoB,CAAC;AAC3B,eAAS,QAAQ,MAAM,YAAY,SAAS,MAAM,UAAU,SAAS,GAAG;AACtE,cAAM,OAAO,kBAAkB,kBAAkB,KAAK;AACtD,YAAI,QAAQ,KAAK,MAAM,iBAAiB,KAAK,QAAQ,YAAa,SAAQ,KAAK,KAAK;AAAA,MACtF;AACA,aAAO;AAAA,IACT;AAGA,cAAU,QAAQ,kBAAkB,MAAM,kBAAkB,gBAAgB,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;AACtG,cAAU,QAAQ,oBAAoB,CAAC,OAAO,UAAU,kBAAkB,kBAAkB,OAAO,KAAK,IAAI,CAAC;AAC7G,cAAU,QAAQ,iBAAiB,kBAAkB;AAAA,EACvD;AAEA,QAAM,YAAYA,OAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,QAAM,cAAcA,OAAM;AAAA,IACxB,MAAO,yBAAyB,QAAQ,gBAAgB,SAAS,KAAK,gBAAgB,IAAI,CAAC,CAAC,GAAG,KAAK;AAAA,IACpG,CAAC,OAAO,sBAAsB,SAAS;AAAA,EACzC;AACA,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,iBAAiB,kBAAkB;AAAA,MACnC;AAAA,MACA,gBAAgB,kBAAkB;AAAA,IACpC;AAAA,IACA,CAAC,kBAAkB,iBAAiB,kBAAkB,gBAAgB,WAAW,aAAa,YAAY;AAAA,EAC5G;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import React2, { useCallback } from "react";
4
4
  import { styled } from "@elliemae/ds-system";
5
5
  import { useGetGlobalAttributes } from "@elliemae/ds-props-helpers";
@@ -21,6 +21,10 @@ const StyledListItem = styled("div", {
21
21
  left: 0;
22
22
  width: 100%;
23
23
  `;
24
+ const StyledExtraContent = styled("div", {
25
+ name: DSFastListName,
26
+ slot: DSFastListSlots.EXTRA_CONTENT
27
+ })``;
24
28
  const StyledListContainer = styled("div", {
25
29
  name: DSFastListName,
26
30
  slot: DSFastListSlots.CONTAINER
@@ -31,8 +35,9 @@ const StyledListContainer = styled("div", {
31
35
  padding-bottom: 0;
32
36
  `;
33
37
  const List = (props) => {
34
- const { parentRef, getVirtualItems, totalSize, instanceUid, measureElement } = useFastList(props);
35
- const { ItemRenderer, extraItemProps, getId } = props;
38
+ const { containerRef, getVirtualItems, totalSize, instanceUid, measureElement } = useFastList(props);
39
+ const { ItemRenderer, extraItemProps, getId, extraContent } = props;
40
+ const hasExtraContent = extraContent !== null && extraContent !== void 0 && typeof extraContent !== "boolean";
36
41
  const virtualItems = getVirtualItems();
37
42
  const measureRef = React2.useCallback(
38
43
  (node) => measureElement(node),
@@ -43,11 +48,11 @@ const List = (props) => {
43
48
  return /* @__PURE__ */ jsx(
44
49
  StyledListContainer,
45
50
  {
46
- innerRef: parentRef,
51
+ innerRef: containerRef,
47
52
  tabIndex: -1,
48
53
  getOwnerProps,
49
54
  ...globalAttributes,
50
- children: /* @__PURE__ */ jsx(
55
+ children: /* @__PURE__ */ jsxs(
51
56
  StyledList,
52
57
  {
53
58
  style: {
@@ -56,24 +61,27 @@ const List = (props) => {
56
61
  },
57
62
  role: "list",
58
63
  getOwnerProps,
59
- children: virtualItems.map((virtualItem) => {
60
- const { index, start } = virtualItem;
61
- return /* @__PURE__ */ jsx(
62
- StyledListItem,
63
- {
64
- innerRef: measureRef,
65
- "data-index": index,
66
- style: {
67
- transform: `translateY(${start}px)`
64
+ children: [
65
+ hasExtraContent ? /* @__PURE__ */ jsx(StyledExtraContent, { getOwnerProps, children: extraContent }) : null,
66
+ virtualItems.map((virtualItem) => {
67
+ const { index, start } = virtualItem;
68
+ return /* @__PURE__ */ jsx(
69
+ StyledListItem,
70
+ {
71
+ innerRef: measureRef,
72
+ "data-index": index,
73
+ style: {
74
+ transform: `translateY(${start}px)`
75
+ },
76
+ role: "listitem",
77
+ getOwnerProps,
78
+ getOwnerPropsArguments: () => ({ index: getId(index) }),
79
+ children: /* @__PURE__ */ jsx(ItemRenderer, { extraItemProps, index })
68
80
  },
69
- role: "listitem",
70
- getOwnerProps,
71
- getOwnerPropsArguments: () => ({ index: getId(index) }),
72
- children: /* @__PURE__ */ jsx(ItemRenderer, { extraItemProps, index })
73
- },
74
- getId(index)
75
- );
76
- })
81
+ getId(index)
82
+ );
83
+ })
84
+ ]
77
85
  }
78
86
  )
79
87
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/List.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useCallback } from 'react';\nimport { styled } from '@elliemae/ds-system';\nimport { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport { useFastList } from '../hooks/useFastList.js';\nimport type { DSFastListT } from '../react-desc-prop-types.js';\nimport { DSFastListName, DSFastListSlots } from '../constants/index.js';\n\nconst StyledList = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.WRAPPER_LIST,\n})`\n width: 100%;\n position: relative;\n`;\n\nconst StyledListItem = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.ITEM,\n})`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n`;\n\nconst StyledListContainer = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.CONTAINER,\n})`\n overflow: auto;\n width: 100%;\n height: 100%;\n padding-bottom: 0;\n`;\n\nexport const List = <T extends object>(props: DSFastListT.Props<T>) => {\n const { parentRef, getVirtualItems, totalSize, instanceUid, measureElement } = useFastList(props);\n const { ItemRenderer, extraItemProps, getId } = props;\n\n const virtualItems = getVirtualItems();\n const measureRef: React.LegacyRef<HTMLDivElement> = React.useCallback(\n (node: HTMLDivElement) => measureElement(node),\n [measureElement],\n );\n\n const getOwnerProps = useCallback(() => props, [props]);\n const globalAttributes = useGetGlobalAttributes(props);\n\n return (\n <StyledListContainer\n innerRef={parentRef}\n // firefox needs this tabIndex to prevent scrolling\n tabIndex={-1}\n key={instanceUid}\n getOwnerProps={getOwnerProps}\n {...globalAttributes}\n >\n <StyledList\n style={{\n // we add up 0.5 to prevent the scrollbar from appearing in some cases\n height: `${totalSize + 0.5}px`,\n }}\n role=\"list\"\n getOwnerProps={getOwnerProps}\n >\n {virtualItems.map((virtualItem) => {\n const { index, start } = virtualItem;\n return (\n <StyledListItem\n innerRef={measureRef}\n data-index={index}\n style={{\n transform: `translateY(${start}px)`,\n }}\n role=\"listitem\"\n key={getId(index)}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={() => ({ index: getId(index) })}\n >\n <ItemRenderer extraItemProps={extraItemProps} index={index} />\n </StyledListItem>\n );\n })}\n </StyledList>\n </StyledListContainer>\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC+ET;AA/Ed,OAAOA,UAAS,mBAAmB;AACnC,SAAS,cAAc;AACvB,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAE5B,SAAS,gBAAgB,uBAAuB;AAEhD,MAAM,aAAa,OAAO,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAKD,MAAM,iBAAiB,OAAO,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOD,MAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOM,MAAM,OAAO,CAAmB,UAAgC;AACrE,QAAM,EAAE,WAAW,iBAAiB,WAAW,aAAa,eAAe,IAAI,YAAY,KAAK;AAChG,QAAM,EAAE,cAAc,gBAAgB,MAAM,IAAI;AAEhD,QAAM,eAAe,gBAAgB;AACrC,QAAM,aAA8CA,OAAM;AAAA,IACxD,CAAC,SAAyB,eAAe,IAAI;AAAA,IAC7C,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,gBAAgB,YAAY,MAAM,OAAO,CAAC,KAAK,CAAC;AACtD,QAAM,mBAAmB,uBAAuB,KAAK;AAErD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MAEV,UAAU;AAAA,MAEV;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA;AAAA,YAEL,QAAQ,GAAG,YAAY,GAAG;AAAA,UAC5B;AAAA,UACA,MAAK;AAAA,UACL;AAAA,UAEC,uBAAa,IAAI,CAAC,gBAAgB;AACjC,kBAAM,EAAE,OAAO,MAAM,IAAI;AACzB,mBACE;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU;AAAA,gBACV,cAAY;AAAA,gBACZ,OAAO;AAAA,kBACL,WAAW,cAAc,KAAK;AAAA,gBAChC;AAAA,gBACA,MAAK;AAAA,gBAEL;AAAA,gBACA,wBAAwB,OAAO,EAAE,OAAO,MAAM,KAAK,EAAE;AAAA,gBAErD,8BAAC,gBAAa,gBAAgC,OAAc;AAAA;AAAA,cAJvD,MAAM,KAAK;AAAA,YAKlB;AAAA,UAEJ,CAAC;AAAA;AAAA,MACH;AAAA;AAAA,IA9BK;AAAA,EA+BP;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useCallback } from 'react';\nimport { styled } from '@elliemae/ds-system';\nimport { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport { useFastList } from '../hooks/useFastList.js';\nimport type { DSFastListT } from '../react-desc-prop-types.js';\nimport { DSFastListName, DSFastListSlots } from '../constants/index.js';\n\nconst StyledList = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.WRAPPER_LIST,\n})`\n width: 100%;\n position: relative;\n`;\n\nconst StyledListItem = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.ITEM,\n})`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n`;\n\nconst StyledExtraContent = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.EXTRA_CONTENT,\n})``;\n\nconst StyledListContainer = styled('div', {\n name: DSFastListName,\n slot: DSFastListSlots.CONTAINER,\n})`\n overflow: auto;\n width: 100%;\n height: 100%;\n padding-bottom: 0;\n`;\n\nexport const List = <T extends object>(props: DSFastListT.Props<T>) => {\n const { containerRef, getVirtualItems, totalSize, instanceUid, measureElement } = useFastList(props);\n const { ItemRenderer, extraItemProps, getId, extraContent } = props;\n const hasExtraContent = extraContent !== null && extraContent !== undefined && typeof extraContent !== 'boolean';\n\n const virtualItems = getVirtualItems();\n const measureRef: React.LegacyRef<HTMLDivElement> = React.useCallback(\n (node: HTMLDivElement) => measureElement(node),\n [measureElement],\n );\n\n const getOwnerProps = useCallback(() => props, [props]);\n const globalAttributes = useGetGlobalAttributes(props);\n\n return (\n <StyledListContainer\n innerRef={containerRef}\n // firefox needs this tabIndex to prevent scrolling\n tabIndex={-1}\n key={instanceUid}\n getOwnerProps={getOwnerProps}\n {...globalAttributes}\n >\n <StyledList\n style={{\n // we add up 0.5 to prevent the scrollbar from appearing in some cases\n height: `${totalSize + 0.5}px`,\n }}\n role=\"list\"\n getOwnerProps={getOwnerProps}\n >\n {hasExtraContent ? <StyledExtraContent getOwnerProps={getOwnerProps}>{extraContent}</StyledExtraContent> : null}\n {virtualItems.map((virtualItem) => {\n const { index, start } = virtualItem;\n return (\n <StyledListItem\n innerRef={measureRef}\n data-index={index}\n style={{\n transform: `translateY(${start}px)`,\n }}\n role=\"listitem\"\n key={getId(index)}\n getOwnerProps={getOwnerProps}\n getOwnerPropsArguments={() => ({ index: getId(index) })}\n >\n <ItemRenderer extraItemProps={extraItemProps} index={index} />\n </StyledListItem>\n );\n })}\n </StyledList>\n </StyledListContainer>\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC+DjB,SAQqB,KARrB;AA/DN,OAAOA,UAAS,mBAAmB;AACnC,SAAS,cAAc;AACvB,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAE5B,SAAS,gBAAgB,uBAAuB;AAEhD,MAAM,aAAa,OAAO,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAKD,MAAM,iBAAiB,OAAO,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOD,MAAM,qBAAqB,OAAO,OAAO;AAAA,EACvC,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAED,MAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,MAAM;AAAA,EACN,MAAM,gBAAgB;AACxB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOM,MAAM,OAAO,CAAmB,UAAgC;AACrE,QAAM,EAAE,cAAc,iBAAiB,WAAW,aAAa,eAAe,IAAI,YAAY,KAAK;AACnG,QAAM,EAAE,cAAc,gBAAgB,OAAO,aAAa,IAAI;AAC9D,QAAM,kBAAkB,iBAAiB,QAAQ,iBAAiB,UAAa,OAAO,iBAAiB;AAEvG,QAAM,eAAe,gBAAgB;AACrC,QAAM,aAA8CA,OAAM;AAAA,IACxD,CAAC,SAAyB,eAAe,IAAI;AAAA,IAC7C,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,gBAAgB,YAAY,MAAM,OAAO,CAAC,KAAK,CAAC;AACtD,QAAM,mBAAmB,uBAAuB,KAAK;AAErD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MAEV,UAAU;AAAA,MAEV;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA;AAAA,YAEL,QAAQ,GAAG,YAAY,GAAG;AAAA,UAC5B;AAAA,UACA,MAAK;AAAA,UACL;AAAA,UAEC;AAAA,8BAAkB,oBAAC,sBAAmB,eAA+B,wBAAa,IAAwB;AAAA,YAC1G,aAAa,IAAI,CAAC,gBAAgB;AACjC,oBAAM,EAAE,OAAO,MAAM,IAAI;AACzB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBACC,UAAU;AAAA,kBACV,cAAY;AAAA,kBACZ,OAAO;AAAA,oBACL,WAAW,cAAc,KAAK;AAAA,kBAChC;AAAA,kBACA,MAAK;AAAA,kBAEL;AAAA,kBACA,wBAAwB,OAAO,EAAE,OAAO,MAAM,KAAK,EAAE;AAAA,kBAErD,8BAAC,gBAAa,gBAAgC,OAAc;AAAA;AAAA,gBAJvD,MAAM,KAAK;AAAA,cAKlB;AAAA,YAEJ,CAAC;AAAA;AAAA;AAAA,MACH;AAAA;AAAA,IA/BK;AAAA,EAgCP;AAEJ;",
6
6
  "names": ["React"]
7
7
  }
@@ -2,7 +2,10 @@ import * as React from "react";
2
2
  import { PropTypes, getPropsPerSlotPropTypes, globalAttributesPropTypes } from "@elliemae/ds-props-helpers";
3
3
  import { DSFastListName, DSFastListSlots } from "./constants/index.js";
4
4
  const defaultProps = {
5
- estimateSize: () => 36
5
+ estimateSize: () => 36,
6
+ paddingStart: 0,
7
+ paddingEnd: 0,
8
+ remountOnCountChange: true
6
9
  };
7
10
  const DSFastListPropTypes = {
8
11
  ...getPropsPerSlotPropTypes(DSFastListName, DSFastListSlots),
@@ -11,22 +14,47 @@ const DSFastListPropTypes = {
11
14
  current: PropTypes.oneOfType([
12
15
  PropTypes.oneOf([null]),
13
16
  PropTypes.shape({
14
- scrollTo: PropTypes.func.description("Scroll to a index inside the list").signature(`((index: number, { align: 'start' | 'center' | 'end' | 'auto' }) => void)`),
17
+ scrollTo: PropTypes.func.description("Scroll to a index inside the list").signature(
18
+ `((index: number, options?: { align?: 'start' | 'center' | 'end' | 'auto'; behavior?: 'auto' | 'smooth' }) => void)`
19
+ ),
15
20
  measure: PropTypes.func.description(
16
21
  "Clears the cached size of every item, falling back to the estimated size until each item is measured again (on its next real layout change or remount) \u2014 does not force an immediate DOM remeasurement"
17
22
  ).signature(`(() => void)`),
18
23
  getVisibleItems: PropTypes.func.description("Returns the indices of the items currently visible in the viewport (no overscan buffer)").signature(`(() => number[])`),
19
- getMountedItems: PropTypes.func.description("Returns the indices of all items currently mounted in the DOM, including the overscan buffer").signature(`(() => number[])`)
24
+ getMountedItems: PropTypes.func.description("Returns the indices of all items currently mounted in the DOM, including the overscan buffer").signature(`(() => number[])`),
25
+ getOffsetForIndex: PropTypes.func.description(
26
+ "Returns the scroll offset that brings the item at the given index into view with the given alignment, or undefined when there is no measurement for it yet (for example, an empty list). It reads the current measurements, where items not rendered yet still have the estimated size, and it does not scroll"
27
+ ).signature(`((index: number, align?: 'start' | 'center' | 'end' | 'auto') => number | undefined)`),
28
+ scrollToOffset: PropTypes.func.description(
29
+ "Scrolls the list to the given offset once. Unlike scrollTo, it does not verify and retry the position on the following frames, so it never competes with the user scrolling at the same time"
30
+ ).signature(
31
+ `((offset: number, options?: { align?: 'start' | 'center' | 'end' | 'auto'; behavior?: 'auto' | 'smooth' }) => void)`
32
+ )
20
33
  })
21
34
  ])
22
- }).description(`mutable reference where methods will be stored`),
35
+ }).description(
36
+ "Mutable reference where the methods are stored. They are assigned during render only when `actionRef.current` is already an object, so pass a ref initialized with one (for example `useRef({})`), not `useRef(null)`"
37
+ ),
23
38
  ItemRenderer: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired.description(
24
39
  "Render function for each item"
25
40
  ),
26
41
  count: PropTypes.number.isRequired.description("Number of items to render"),
27
42
  extraItemProps: PropTypes.object.description("Extra props to pass to each item"),
28
43
  getId: PropTypes.func.isRequired.description("Function to get the key for each item"),
29
- estimateSize: PropTypes.func.description("Function to estimate the size of each item")
44
+ estimateSize: PropTypes.func.description("Function to estimate the size of each item"),
45
+ innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).description(
46
+ "Ref (object or callback) that receives the scroll container element of the list"
47
+ ),
48
+ paddingStart: PropTypes.number.description("Space in pixels reserved before the first item inside the scrolling area").defaultValue(0),
49
+ paddingEnd: PropTypes.number.description(
50
+ "Space in pixels reserved after the last item inside the scrolling area; negative values are passed through"
51
+ ).defaultValue(0),
52
+ remountOnCountChange: PropTypes.bool.description(
53
+ "When true the scroll container element is recreated every time count changes; set it to false to keep the same element and scroll position while the number of items changes"
54
+ ).defaultValue(true),
55
+ extraContent: PropTypes.node.description(
56
+ 'Content rendered inside the list wrapper before the items, within the extra content slot; it should be positioned out of the normal flow because the wrapper height is fixed. The wrapper has role="list" by default, so the content must carry role="listitem" itself (for example a container around a button), unless the wrapper role is overridden through the wrapper-list slot, in which case it must fit that role instead'
57
+ )
30
58
  };
31
59
  export {
32
60
  DSFastListPropTypes,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/react-desc-prop-types.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { GlobalAttributesT } from '@elliemae/ds-props-helpers';\nimport { PropTypes, getPropsPerSlotPropTypes, globalAttributesPropTypes } from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport type React from 'react';\nimport { DSFastListName, DSFastListSlots } from './constants/index.js';\n\nexport declare namespace DSFastListT {\n type ScrollAlignment = 'start' | 'center' | 'end' | 'auto';\n export type ScrollToOptions = {\n align: ScrollAlignment;\n };\n\n export type ActionRef = {\n scrollTo?: (index: number, options?: ScrollToOptions | undefined) => void;\n measure?: () => void;\n getVisibleItems?: () => number[];\n getMountedItems?: () => number[];\n };\n\n export type SlotFunctionArguments = {\n dsFastlistContainer: () => object;\n dsFastlistWrapperList: () => object;\n dsFastlistItem: () => object;\n };\n\n export interface OptionalProps<ExtraItemPropsT> extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSFastListName,\n typeof DSFastListSlots\n > {\n actionRef?: React.MutableRefObject<ActionRef>;\n extraItemProps?: ExtraItemPropsT;\n }\n\n export interface RequiredProps<ExtraItemPropsT> {\n ItemRenderer: React.ComponentType<{ index: number; extraItemProps?: ExtraItemPropsT }>;\n count: number;\n getId: (index: number) => string | number;\n }\n\n export interface DefaultProps {\n estimateSize: () => number;\n }\n\n // 'children' is excluded on top of `keyof D | keyof R`: DSFastList is the render-prop variant\n // (see FastList.tsx's own comment) and never reads props.children \u2014 without this exclusion,\n // GlobalAttributesT<HTMLElement> (which includes children via React's DOMAttributes) would let\n // the public type silently accept children that are dropped at runtime.\n type PropsT<D, R, O> = Partial<D> & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;\n type InternalPropsT<D, R, O> = D & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;\n\n export type Props<ExtraItemPropsT> = PropsT<\n DefaultProps,\n RequiredProps<ExtraItemPropsT>,\n OptionalProps<ExtraItemPropsT>\n >;\n export type InternalProps<ExtraItemPropsT> = InternalPropsT<\n DefaultProps,\n RequiredProps<ExtraItemPropsT>,\n OptionalProps<ExtraItemPropsT>\n >;\n}\n\nexport const defaultProps = {\n estimateSize: () => 36,\n};\n\nexport const DSFastListPropTypes = {\n ...getPropsPerSlotPropTypes(DSFastListName, DSFastListSlots),\n ...globalAttributesPropTypes,\n actionRef: PropTypes.shape({\n current: PropTypes.oneOfType([\n PropTypes.oneOf([null]),\n PropTypes.shape({\n scrollTo: PropTypes.func\n .description('Scroll to a index inside the list')\n .signature(`((index: number, { align: 'start' | 'center' | 'end' | 'auto' }) => void)`),\n measure: PropTypes.func\n .description(\n 'Clears the cached size of every item, falling back to the estimated size until each item is measured again (on its next real layout change or remount) \u2014 does not force an immediate DOM remeasurement',\n )\n .signature(`(() => void)`),\n getVisibleItems: PropTypes.func\n .description('Returns the indices of the items currently visible in the viewport (no overscan buffer)')\n .signature(`(() => number[])`),\n getMountedItems: PropTypes.func\n .description('Returns the indices of all items currently mounted in the DOM, including the overscan buffer')\n .signature(`(() => number[])`),\n }),\n ]),\n }).description(`mutable reference where methods will be stored`),\n ItemRenderer: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired.description(\n 'Render function for each item',\n ),\n count: PropTypes.number.isRequired.description('Number of items to render'),\n extraItemProps: PropTypes.object.description('Extra props to pass to each item'),\n getId: PropTypes.func.isRequired.description('Function to get the key for each item'),\n estimateSize: PropTypes.func.description('Function to estimate the size of each item'),\n} as React.WeakValidationMap<unknown>;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,WAAW,0BAA0B,iCAAiC;AAG/E,SAAS,gBAAgB,uBAAuB;AA0DzC,MAAM,eAAe;AAAA,EAC1B,cAAc,MAAM;AACtB;AAEO,MAAM,sBAAsB;AAAA,EACjC,GAAG,yBAAyB,gBAAgB,eAAe;AAAA,EAC3D,GAAG;AAAA,EACH,WAAW,UAAU,MAAM;AAAA,IACzB,SAAS,UAAU,UAAU;AAAA,MAC3B,UAAU,MAAM,CAAC,IAAI,CAAC;AAAA,MACtB,UAAU,MAAM;AAAA,QACd,UAAU,UAAU,KACjB,YAAY,mCAAmC,EAC/C,UAAU,2EAA2E;AAAA,QACxF,SAAS,UAAU,KAChB;AAAA,UACC;AAAA,QACF,EACC,UAAU,cAAc;AAAA,QAC3B,iBAAiB,UAAU,KACxB,YAAY,yFAAyF,EACrG,UAAU,kBAAkB;AAAA,QAC/B,iBAAiB,UAAU,KACxB,YAAY,8FAA8F,EAC1G,UAAU,kBAAkB;AAAA,MACjC,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC,EAAE,YAAY,gDAAgD;AAAA,EAC/D,cAAc,UAAU,UAAU,CAAC,UAAU,QAAQ,UAAU,IAAI,CAAC,EAAE,WAAW;AAAA,IAC/E;AAAA,EACF;AAAA,EACA,OAAO,UAAU,OAAO,WAAW,YAAY,2BAA2B;AAAA,EAC1E,gBAAgB,UAAU,OAAO,YAAY,kCAAkC;AAAA,EAC/E,OAAO,UAAU,KAAK,WAAW,YAAY,uCAAuC;AAAA,EACpF,cAAc,UAAU,KAAK,YAAY,4CAA4C;AACvF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { GlobalAttributesT } from '@elliemae/ds-props-helpers';\nimport { PropTypes, getPropsPerSlotPropTypes, globalAttributesPropTypes } from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport type React from 'react';\nimport { DSFastListName, DSFastListSlots } from './constants/index.js';\n\nexport declare namespace DSFastListT {\n type ScrollAlignment = 'start' | 'center' | 'end' | 'auto';\n /** Kept with its published shape (`align` required) so code that reads it keeps compiling. */\n export type ScrollToOptions = {\n align: ScrollAlignment;\n };\n\n /** What the scroll actions accept: `align` is optional and `behavior` can request a smooth scroll. */\n export type ScrollActionOptions = {\n align?: ScrollAlignment;\n behavior?: 'auto' | 'smooth';\n };\n\n /**\n * `scrollTo` and `scrollToOffset` use method syntax on purpose: their parameters are compared bivariantly, so an\n * `actionRef` typed with the published `(index, options?: ScrollToOptions) => void` stays assignable.\n */\n export type ActionRef = {\n scrollTo?(index: number, options?: ScrollActionOptions): void;\n measure?: () => void;\n getVisibleItems?: () => number[];\n getMountedItems?: () => number[];\n getOffsetForIndex?: (index: number, align?: ScrollAlignment) => number | undefined;\n scrollToOffset?(offset: number, options?: ScrollActionOptions): void;\n };\n\n export type SlotFunctionArguments = {\n dsFastlistContainer: () => object;\n dsFastlistWrapperList: () => object;\n dsFastlistItem: () => object;\n dsFastlistExtraContent: () => object;\n };\n\n export interface OptionalProps<ExtraItemPropsT> extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSFastListName,\n typeof DSFastListSlots\n > {\n actionRef?: React.MutableRefObject<ActionRef>;\n extraItemProps?: ExtraItemPropsT;\n innerRef?: React.MutableRefObject<HTMLDivElement | null> | React.RefCallback<HTMLDivElement>;\n extraContent?: React.ReactNode;\n }\n\n export interface RequiredProps<ExtraItemPropsT> {\n ItemRenderer: React.ComponentType<{ index: number; extraItemProps?: ExtraItemPropsT }>;\n count: number;\n getId: (index: number) => string | number;\n }\n\n export interface DefaultProps {\n estimateSize: () => number;\n paddingStart: number;\n paddingEnd: number;\n remountOnCountChange: boolean;\n }\n\n // 'children' is excluded on top of `keyof D | keyof R`: DSFastList is the render-prop variant\n // (see FastList.tsx's own comment) and never reads props.children \u2014 without this exclusion,\n // GlobalAttributesT<HTMLElement> (which includes children via React's DOMAttributes) would let\n // the public type silently accept children that are dropped at runtime.\n type PropsT<D, R, O> = Partial<D> & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;\n type InternalPropsT<D, R, O> = D & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;\n\n export type Props<ExtraItemPropsT> = PropsT<\n DefaultProps,\n RequiredProps<ExtraItemPropsT>,\n OptionalProps<ExtraItemPropsT>\n >;\n export type InternalProps<ExtraItemPropsT> = InternalPropsT<\n DefaultProps,\n RequiredProps<ExtraItemPropsT>,\n OptionalProps<ExtraItemPropsT>\n >;\n}\n\nexport const defaultProps = {\n estimateSize: () => 36,\n paddingStart: 0,\n paddingEnd: 0,\n remountOnCountChange: true,\n};\n\nexport const DSFastListPropTypes = {\n ...getPropsPerSlotPropTypes(DSFastListName, DSFastListSlots),\n ...globalAttributesPropTypes,\n actionRef: PropTypes.shape({\n current: PropTypes.oneOfType([\n PropTypes.oneOf([null]),\n PropTypes.shape({\n scrollTo: PropTypes.func\n .description('Scroll to a index inside the list')\n .signature(\n `((index: number, options?: { align?: 'start' | 'center' | 'end' | 'auto'; behavior?: 'auto' | 'smooth' }) => void)`,\n ),\n measure: PropTypes.func\n .description(\n 'Clears the cached size of every item, falling back to the estimated size until each item is measured again (on its next real layout change or remount) \u2014 does not force an immediate DOM remeasurement',\n )\n .signature(`(() => void)`),\n getVisibleItems: PropTypes.func\n .description('Returns the indices of the items currently visible in the viewport (no overscan buffer)')\n .signature(`(() => number[])`),\n getMountedItems: PropTypes.func\n .description('Returns the indices of all items currently mounted in the DOM, including the overscan buffer')\n .signature(`(() => number[])`),\n getOffsetForIndex: PropTypes.func\n .description(\n 'Returns the scroll offset that brings the item at the given index into view with the given alignment, or undefined when there is no measurement for it yet (for example, an empty list). It reads the current measurements, where items not rendered yet still have the estimated size, and it does not scroll',\n )\n .signature(`((index: number, align?: 'start' | 'center' | 'end' | 'auto') => number | undefined)`),\n scrollToOffset: PropTypes.func\n .description(\n 'Scrolls the list to the given offset once. Unlike scrollTo, it does not verify and retry the position on the following frames, so it never competes with the user scrolling at the same time',\n )\n .signature(\n `((offset: number, options?: { align?: 'start' | 'center' | 'end' | 'auto'; behavior?: 'auto' | 'smooth' }) => void)`,\n ),\n }),\n ]),\n }).description(\n 'Mutable reference where the methods are stored. They are assigned during render only when `actionRef.current` is already an object, so pass a ref initialized with one (for example `useRef({})`), not `useRef(null)`',\n ),\n ItemRenderer: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired.description(\n 'Render function for each item',\n ),\n count: PropTypes.number.isRequired.description('Number of items to render'),\n extraItemProps: PropTypes.object.description('Extra props to pass to each item'),\n getId: PropTypes.func.isRequired.description('Function to get the key for each item'),\n estimateSize: PropTypes.func.description('Function to estimate the size of each item'),\n innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).description(\n 'Ref (object or callback) that receives the scroll container element of the list',\n ),\n paddingStart: PropTypes.number\n .description('Space in pixels reserved before the first item inside the scrolling area')\n .defaultValue(0),\n paddingEnd: PropTypes.number\n .description(\n 'Space in pixels reserved after the last item inside the scrolling area; negative values are passed through',\n )\n .defaultValue(0),\n remountOnCountChange: PropTypes.bool\n .description(\n 'When true the scroll container element is recreated every time count changes; set it to false to keep the same element and scroll position while the number of items changes',\n )\n .defaultValue(true),\n extraContent: PropTypes.node.description(\n 'Content rendered inside the list wrapper before the items, within the extra content slot; it should be positioned out of the normal flow because the wrapper height is fixed. The wrapper has role=\"list\" by default, so the content must carry role=\"listitem\" itself (for example a container around a button), unless the wrapper role is overridden through the wrapper-list slot, in which case it must fit that role instead',\n ),\n} as React.WeakValidationMap<unknown>;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,WAAW,0BAA0B,iCAAiC;AAG/E,SAAS,gBAAgB,uBAAuB;AA6EzC,MAAM,eAAe;AAAA,EAC1B,cAAc,MAAM;AAAA,EACpB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,sBAAsB;AACxB;AAEO,MAAM,sBAAsB;AAAA,EACjC,GAAG,yBAAyB,gBAAgB,eAAe;AAAA,EAC3D,GAAG;AAAA,EACH,WAAW,UAAU,MAAM;AAAA,IACzB,SAAS,UAAU,UAAU;AAAA,MAC3B,UAAU,MAAM,CAAC,IAAI,CAAC;AAAA,MACtB,UAAU,MAAM;AAAA,QACd,UAAU,UAAU,KACjB,YAAY,mCAAmC,EAC/C;AAAA,UACC;AAAA,QACF;AAAA,QACF,SAAS,UAAU,KAChB;AAAA,UACC;AAAA,QACF,EACC,UAAU,cAAc;AAAA,QAC3B,iBAAiB,UAAU,KACxB,YAAY,yFAAyF,EACrG,UAAU,kBAAkB;AAAA,QAC/B,iBAAiB,UAAU,KACxB,YAAY,8FAA8F,EAC1G,UAAU,kBAAkB;AAAA,QAC/B,mBAAmB,UAAU,KAC1B;AAAA,UACC;AAAA,QACF,EACC,UAAU,sFAAsF;AAAA,QACnG,gBAAgB,UAAU,KACvB;AAAA,UACC;AAAA,QACF,EACC;AAAA,UACC;AAAA,QACF;AAAA,MACJ,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC,EAAE;AAAA,IACD;AAAA,EACF;AAAA,EACA,cAAc,UAAU,UAAU,CAAC,UAAU,QAAQ,UAAU,IAAI,CAAC,EAAE,WAAW;AAAA,IAC/E;AAAA,EACF;AAAA,EACA,OAAO,UAAU,OAAO,WAAW,YAAY,2BAA2B;AAAA,EAC1E,gBAAgB,UAAU,OAAO,YAAY,kCAAkC;AAAA,EAC/E,OAAO,UAAU,KAAK,WAAW,YAAY,uCAAuC;AAAA,EACpF,cAAc,UAAU,KAAK,YAAY,4CAA4C;AAAA,EACrF,UAAU,UAAU,UAAU,CAAC,UAAU,MAAM,UAAU,MAAM,CAAC,EAAE;AAAA,IAChE;AAAA,EACF;AAAA,EACA,cAAc,UAAU,OACrB,YAAY,0EAA0E,EACtF,aAAa,CAAC;AAAA,EACjB,YAAY,UAAU,OACnB;AAAA,IACC;AAAA,EACF,EACC,aAAa,CAAC;AAAA,EACjB,sBAAsB,UAAU,KAC7B;AAAA,IACC;AAAA,EACF,EACC,aAAa,IAAI;AAAA,EACpB,cAAc,UAAU,KAAK;AAAA,IAC3B;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -2,12 +2,14 @@ import * as React from "react";
2
2
  const SlotPropsAsObject = {
3
3
  dsFastlistContainer: { "aria-label": "just a typescript test" },
4
4
  dsFastlistWrapperList: { "aria-label": "just a typescript test" },
5
- dsFastlistItem: { "aria-label": "just a typescript test" }
5
+ dsFastlistItem: { "aria-label": "just a typescript test" },
6
+ dsFastlistExtraContent: { "aria-label": "just a typescript test" }
6
7
  };
7
8
  const SlotPropsAsFunctions = {
8
9
  dsFastlistContainer: () => ({ "aria-label": "just a typescript test" }),
9
10
  dsFastlistWrapperList: () => ({ "aria-label": "just a typescript test" }),
10
- dsFastlistItem: () => ({ "aria-label": "just a typescript test" })
11
+ dsFastlistItem: () => ({ "aria-label": "just a typescript test" }),
12
+ dsFastlistExtraContent: () => ({ "aria-label": "just a typescript test" })
11
13
  };
12
14
  const EnsureAllSlotsExistInSlotFunctionArguments = SlotPropsAsFunctions;
13
15
  //# sourceMappingURL=slot-props.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/typescript-testing/slot-props.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\n\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport type { DSFastListName, DSFastListSlots } from '../constants/index.js';\nimport type { DSFastListT } from '../react-desc-prop-types.js';\n\nconst SlotPropsAsObject: Partial<DSFastListT.OptionalProps<object>> = {\n dsFastlistContainer: { 'aria-label': 'just a typescript test' },\n dsFastlistWrapperList: { 'aria-label': 'just a typescript test' },\n dsFastlistItem: { 'aria-label': 'just a typescript test' },\n};\n\nconst SlotPropsAsFunctions: DSFastListT.SlotFunctionArguments = {\n dsFastlistContainer: () => ({ 'aria-label': 'just a typescript test' }),\n dsFastlistWrapperList: () => ({ 'aria-label': 'just a typescript test' }),\n dsFastlistItem: () => ({ 'aria-label': 'just a typescript test' }),\n};\n\n// Exhaustiveness check \u2014 fails compilation if a slot is missing from SlotFunctionArguments\nconst EnsureAllSlotsExistInSlotFunctionArguments: Required<\n TypescriptHelpersT.PropsForSlots<typeof DSFastListName, typeof DSFastListSlots>\n> = SlotPropsAsFunctions;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACMvB,MAAM,oBAAgE;AAAA,EACpE,qBAAqB,EAAE,cAAc,yBAAyB;AAAA,EAC9D,uBAAuB,EAAE,cAAc,yBAAyB;AAAA,EAChE,gBAAgB,EAAE,cAAc,yBAAyB;AAC3D;AAEA,MAAM,uBAA0D;AAAA,EAC9D,qBAAqB,OAAO,EAAE,cAAc,yBAAyB;AAAA,EACrE,uBAAuB,OAAO,EAAE,cAAc,yBAAyB;AAAA,EACvE,gBAAgB,OAAO,EAAE,cAAc,yBAAyB;AAClE;AAGA,MAAM,6CAEF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\n\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport type { DSFastListName, DSFastListSlots } from '../constants/index.js';\nimport type { DSFastListT } from '../react-desc-prop-types.js';\n\nconst SlotPropsAsObject: Partial<DSFastListT.OptionalProps<object>> = {\n dsFastlistContainer: { 'aria-label': 'just a typescript test' },\n dsFastlistWrapperList: { 'aria-label': 'just a typescript test' },\n dsFastlistItem: { 'aria-label': 'just a typescript test' },\n dsFastlistExtraContent: { 'aria-label': 'just a typescript test' },\n};\n\nconst SlotPropsAsFunctions: DSFastListT.SlotFunctionArguments = {\n dsFastlistContainer: () => ({ 'aria-label': 'just a typescript test' }),\n dsFastlistWrapperList: () => ({ 'aria-label': 'just a typescript test' }),\n dsFastlistItem: () => ({ 'aria-label': 'just a typescript test' }),\n dsFastlistExtraContent: () => ({ 'aria-label': 'just a typescript test' }),\n};\n\n// Exhaustiveness check \u2014 fails compilation if a slot is missing from SlotFunctionArguments\nconst EnsureAllSlotsExistInSlotFunctionArguments: Required<\n TypescriptHelpersT.PropsForSlots<typeof DSFastListName, typeof DSFastListSlots>\n> = SlotPropsAsFunctions;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACMvB,MAAM,oBAAgE;AAAA,EACpE,qBAAqB,EAAE,cAAc,yBAAyB;AAAA,EAC9D,uBAAuB,EAAE,cAAc,yBAAyB;AAAA,EAChE,gBAAgB,EAAE,cAAc,yBAAyB;AAAA,EACzD,wBAAwB,EAAE,cAAc,yBAAyB;AACnE;AAEA,MAAM,uBAA0D;AAAA,EAC9D,qBAAqB,OAAO,EAAE,cAAc,yBAAyB;AAAA,EACrE,uBAAuB,OAAO,EAAE,cAAc,yBAAyB;AAAA,EACvE,gBAAgB,OAAO,EAAE,cAAc,yBAAyB;AAAA,EAChE,wBAAwB,OAAO,EAAE,cAAc,yBAAyB;AAC1E;AAGA,MAAM,6CAEF;",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,9 @@ const data = [1, 2, 3];
6
6
  const extraProps = { data };
7
7
  const MockItemRenderer = ({ index }) => /* @__PURE__ */ jsx("div", {});
8
8
  const actionRef = createRef();
9
+ const innerRefObject = createRef();
10
+ const innerRefCallback = (node) => {
11
+ };
9
12
  const testRequiredProps = {
10
13
  ItemRenderer: MockItemRenderer,
11
14
  count: 0,
@@ -13,7 +16,9 @@ const testRequiredProps = {
13
16
  };
14
17
  const testOptionalProps = {
15
18
  actionRef,
16
- extraItemProps: { data }
19
+ extraItemProps: { data },
20
+ innerRef: innerRefObject,
21
+ extraContent: /* @__PURE__ */ jsx("button", { type: "button", children: "Load more" })
17
22
  };
18
23
  const testPartialDefaults = {};
19
24
  const testProps = {
@@ -27,7 +32,10 @@ const testPropsAsSyntax = {
27
32
  ...testPartialDefaults
28
33
  };
29
34
  const testCompleteDefaults = {
30
- estimateSize: () => 36
35
+ estimateSize: () => 36,
36
+ paddingStart: 0,
37
+ paddingEnd: 0,
38
+ remountOnCountChange: true
31
39
  };
32
40
  const testInternalProps = {
33
41
  ...testRequiredProps,
@@ -68,14 +76,51 @@ const testGlobalAttributes = {
68
76
  id: "custom-id",
69
77
  "aria-label": "custom list"
70
78
  };
79
+ const testContainerIntegration = {
80
+ ...testRequiredProps,
81
+ innerRef: innerRefCallback,
82
+ paddingStart: 24,
83
+ paddingEnd: -5,
84
+ remountOnCountChange: false,
85
+ extraContent: null
86
+ };
87
+ const testContainerIntegrationAsSyntax = {
88
+ ...testRequiredProps,
89
+ innerRef: innerRefObject,
90
+ paddingStart: 24,
91
+ paddingEnd: 40,
92
+ remountOnCountChange: true,
93
+ extraContent: /* @__PURE__ */ jsx("span", { children: "extra" })
94
+ };
95
+ const testContainerIntegrationAsConst = {
96
+ ...testRequiredProps,
97
+ paddingStart: 0,
98
+ paddingEnd: 0,
99
+ remountOnCountChange: false
100
+ };
101
+ const publishedScrollToOptions = { align: "start" };
102
+ const publishedAlign = publishedScrollToOptions.align;
103
+ const scrollActionOptions = { behavior: "smooth" };
104
+ const handleScrollToWithActionOptions = () => actionRef.current.scrollTo?.(1, scrollActionOptions);
105
+ const handleScrollToWithPublishedOptions = () => actionRef.current.scrollTo?.(1, publishedScrollToOptions);
106
+ const handleScrollToAlign = () => actionRef.current.scrollTo?.(1, { align: "center" });
107
+ const handleScrollToBehavior = () => actionRef.current.scrollTo?.(1, { behavior: "smooth" });
108
+ const handleScrollToBoth = () => actionRef.current.scrollTo?.(1, { align: "end", behavior: "auto" });
71
109
  const handleMeasure = () => actionRef.current.measure?.();
72
110
  const handleGetVisibleItems = () => actionRef.current.getVisibleItems?.() ?? [];
73
111
  const handleGetMountedItems = () => actionRef.current.getMountedItems?.() ?? [];
112
+ const handleGetOffsetForIndex = () => actionRef.current.getOffsetForIndex?.(1);
113
+ const handleGetOffsetForIndexAligned = () => actionRef.current.getOffsetForIndex?.(1, "center");
114
+ const handleScrollToOffset = () => actionRef.current.scrollToOffset?.(100);
115
+ const handleScrollToOffsetWithOptions = () => actionRef.current.scrollToOffset?.(100, { behavior: "auto" });
74
116
  const ExampleUsageComponent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
75
117
  /* @__PURE__ */ jsx(DSFastList, { ...testExplicitDefinition }),
76
118
  /* @__PURE__ */ jsx(DSFastList, { ...testInferredTypeCompatibility }),
77
119
  /* @__PURE__ */ jsx(DSFastList, { ...testDefinitionAsConst }),
78
120
  /* @__PURE__ */ jsx(DSFastList, { ...testGlobalAttributes }),
121
+ /* @__PURE__ */ jsx(DSFastList, { ...testContainerIntegration }),
122
+ /* @__PURE__ */ jsx(DSFastList, { ...testContainerIntegrationAsSyntax }),
123
+ /* @__PURE__ */ jsx(DSFastList, { ...testContainerIntegrationAsConst }),
79
124
  /* @__PURE__ */ jsx(
80
125
  DSFastList,
81
126
  {
@@ -86,6 +131,20 @@ const ExampleUsageComponent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
86
131
  extraItemProps: { foo: "bar" }
87
132
  }
88
133
  ),
134
+ /* @__PURE__ */ jsx(
135
+ DSFastList,
136
+ {
137
+ ItemRenderer: MockItemRenderer,
138
+ count: 0,
139
+ getId: (index) => "",
140
+ innerRef: innerRefObject,
141
+ paddingStart: 24,
142
+ paddingEnd: -5,
143
+ remountOnCountChange: false,
144
+ extraContent: /* @__PURE__ */ jsx("button", { type: "button", children: "Load more" }),
145
+ dsFastlistExtraContent: { role: "listitem" }
146
+ }
147
+ ),
89
148
  /* @__PURE__ */ jsx(
90
149
  DSFastList,
91
150
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/typescript-testing/typescript-fast-list-valid.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { type MutableRefObject, createRef } from 'react';\nimport { DSFastList } from '../index.js';\nimport type { DSFastListT } from '../index.js';\n\nconst data = [1, 2, 3];\nconst extraProps = { data };\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSFastListT.Props<typeof extraProps>;\ntype ComponentPropsInternals = DSFastListT.InternalProps<typeof extraProps>;\ntype ComponentPropsDefaultProps = DSFastListT.DefaultProps;\ntype ComponentPropsOptionalProps = DSFastListT.OptionalProps<typeof extraProps>;\ntype ComponentPropsRequiredProps = DSFastListT.RequiredProps<typeof extraProps>;\n\nconst MockItemRenderer = ({ index }: { index: number }) => <div></div>;\n\n// Referencing DSFastListT.ActionRef directly (not a hand-written shape) so this file breaks if\n// the real ActionRef contract changes \u2014 a hand-written shape here would silently drift.\nconst actionRef = createRef() as MutableRefObject<DSFastListT.ActionRef>;\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n};\n\nconst testOptionalProps: ComponentPropsOptionalProps = {\n actionRef,\n extraItemProps: { data },\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testPartialDefaults,\n};\n\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n estimateSize: () => 36,\n};\n\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testCompleteDefaults,\n};\n\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { data },\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferredTypeCompatibility = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { data },\n} as ComponentPropsForApp;\n\nconst testDefinitionAsConst = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { foo: 'bar' },\n} as const;\n\n// Global HTML/ARIA attributes (className, id, aria-*, data-*) work at runtime via\n// useGetGlobalAttributes in List.tsx \u2014 PropsT/InternalPropsT intersect with\n// Omit<GlobalAttributesT<HTMLElement>, ...> specifically so this compiles. Regression here means\n// the type/runtime contract has drifted apart again.\nconst testGlobalAttributes: ComponentPropsForApp = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n className: 'custom-class',\n id: 'custom-id',\n 'aria-label': 'custom list',\n};\n// actionRef method usages \u2014 measure() and getVisibleItems() (PUI-17898)\nconst handleMeasure = () => actionRef.current.measure?.();\nconst handleGetVisibleItems: () => number[] = () => actionRef.current.getVisibleItems?.() ?? [];\nconst handleGetMountedItems: () => number[] = () => actionRef.current.getMountedItems?.() ?? [];\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSFastList {...testExplicitDefinition} />\n <DSFastList {...testInferredTypeCompatibility} />\n <DSFastList {...testDefinitionAsConst} />\n <DSFastList {...testGlobalAttributes} />\n {/* works with inline values */}\n <DSFastList\n ItemRenderer={MockItemRenderer}\n count={0}\n getId={(index: number) => ''}\n actionRef={actionRef}\n extraItemProps={{ foo: 'bar' }}\n />\n {/* Inline props test \u2014 global HTML/ARIA attributes */}\n <DSFastList\n className=\"custom-class\"\n id=\"custom-id\"\n aria-label=\"custom list\"\n data-testid=\"custom-testid\"\n ItemRenderer={MockItemRenderer}\n count={0}\n getId={(index: number) => ''}\n />\n </>\n);\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACcoC,SA8FzD,UA9FyD,KA8FzD,YA9FyD;AAb3D,SAAgC,iBAAiB;AACjD,SAAS,kBAAkB;AAG3B,MAAM,OAAO,CAAC,GAAG,GAAG,CAAC;AACrB,MAAM,aAAa,EAAE,KAAK;AAQ1B,MAAM,mBAAmB,CAAC,EAAE,MAAM,MAAyB,oBAAC,SAAI;AAIhE,MAAM,YAAY,UAAU;AAE5B,MAAM,oBAAiD;AAAA,EACrD,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,UAAkB;AAC5B;AAEA,MAAM,oBAAiD;AAAA,EACrD;AAAA,EACA,gBAAgB,EAAE,KAAK;AACzB;AAIA,MAAM,sBAA2D,CAAC;AAElE,MAAM,YAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,uBAA6D;AAAA,EACjE,cAAc,MAAM;AACtB;AAEA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,UAAkB;AAAA,EAC1B;AAAA,EACA,gBAAgB,EAAE,KAAK;AACzB;AAGA,MAAM,gCAAgC;AAAA,EACpC,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,UAAkB;AAAA,EAC1B;AAAA,EACA,gBAAgB,EAAE,KAAK;AACzB;AAEA,MAAM,wBAAwB;AAAA,EAC5B,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,UAAkB;AAAA,EAC1B;AAAA,EACA,gBAAgB,EAAE,KAAK,MAAM;AAC/B;AAMA,MAAM,uBAA6C;AAAA,EACjD,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,UAAkB;AAAA,EAC1B,WAAW;AAAA,EACX,IAAI;AAAA,EACJ,cAAc;AAChB;AAEA,MAAM,gBAAgB,MAAM,UAAU,QAAQ,UAAU;AACxD,MAAM,wBAAwC,MAAM,UAAU,QAAQ,kBAAkB,KAAK,CAAC;AAC9F,MAAM,wBAAwC,MAAM,UAAU,QAAQ,kBAAkB,KAAK,CAAC;AAE9F,MAAM,wBAAwB,MAC5B,iCAEE;AAAA,sBAAC,cAAY,GAAG,wBAAwB;AAAA,EACxC,oBAAC,cAAY,GAAG,+BAA+B;AAAA,EAC/C,oBAAC,cAAY,GAAG,uBAAuB;AAAA,EACvC,oBAAC,cAAY,GAAG,sBAAsB;AAAA,EAEtC;AAAA,IAAC;AAAA;AAAA,MACC,cAAc;AAAA,MACd,OAAO;AAAA,MACP,OAAO,CAAC,UAAkB;AAAA,MAC1B;AAAA,MACA,gBAAgB,EAAE,KAAK,MAAM;AAAA;AAAA,EAC/B;AAAA,EAEA;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,IAAG;AAAA,MACH,cAAW;AAAA,MACX,eAAY;AAAA,MACZ,cAAc;AAAA,MACd,OAAO;AAAA,MACP,OAAO,CAAC,UAAkB;AAAA;AAAA,EAC5B;AAAA,GACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { type MutableRefObject, createRef } from 'react';\nimport { DSFastList } from '../index.js';\nimport type { DSFastListT } from '../index.js';\n\nconst data = [1, 2, 3];\nconst extraProps = { data };\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSFastListT.Props<typeof extraProps>;\ntype ComponentPropsInternals = DSFastListT.InternalProps<typeof extraProps>;\ntype ComponentPropsDefaultProps = DSFastListT.DefaultProps;\ntype ComponentPropsOptionalProps = DSFastListT.OptionalProps<typeof extraProps>;\ntype ComponentPropsRequiredProps = DSFastListT.RequiredProps<typeof extraProps>;\n\nconst MockItemRenderer = ({ index }: { index: number }) => <div></div>;\n\n// Referencing DSFastListT.ActionRef directly (not a hand-written shape) so this file breaks if\n// the real ActionRef contract changes \u2014 a hand-written shape here would silently drift.\nconst actionRef = createRef() as MutableRefObject<DSFastListT.ActionRef>;\nconst innerRefObject = createRef() as MutableRefObject<HTMLDivElement | null>;\nconst innerRefCallback = (node: HTMLDivElement | null) => {};\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n};\n\nconst testOptionalProps: ComponentPropsOptionalProps = {\n actionRef,\n extraItemProps: { data },\n innerRef: innerRefObject,\n extraContent: <button type=\"button\">Load more</button>,\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testPartialDefaults,\n};\n\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n estimateSize: () => 36,\n paddingStart: 0,\n paddingEnd: 0,\n remountOnCountChange: true,\n};\n\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testCompleteDefaults,\n};\n\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testOptionalProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { data },\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferredTypeCompatibility = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { data },\n} as ComponentPropsForApp;\n\nconst testDefinitionAsConst = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n actionRef,\n extraItemProps: { foo: 'bar' },\n} as const;\n\n// Global HTML/ARIA attributes (className, id, aria-*, data-*) work at runtime via\n// useGetGlobalAttributes in List.tsx \u2014 PropsT/InternalPropsT intersect with\n// Omit<GlobalAttributesT<HTMLElement>, ...> specifically so this compiles. Regression here means\n// the type/runtime contract has drifted apart again.\nconst testGlobalAttributes: ComponentPropsForApp = {\n ItemRenderer: MockItemRenderer,\n count: 0,\n getId: (index: number) => '',\n className: 'custom-class',\n id: 'custom-id',\n 'aria-label': 'custom list',\n};\n// container-integration props, all assignment styles\nconst testContainerIntegration: ComponentPropsForApp = {\n ...testRequiredProps,\n innerRef: innerRefCallback,\n paddingStart: 24,\n paddingEnd: -5,\n remountOnCountChange: false,\n extraContent: null,\n};\n\nconst testContainerIntegrationAsSyntax = {\n ...testRequiredProps,\n innerRef: innerRefObject,\n paddingStart: 24,\n paddingEnd: 40,\n remountOnCountChange: true,\n extraContent: <span>extra</span>,\n} as ComponentPropsForApp;\n\nconst testContainerIntegrationAsConst = {\n ...testRequiredProps,\n paddingStart: 0,\n paddingEnd: 0,\n remountOnCountChange: false,\n} as const;\n\n// scrollTo accepts the virtualizer's full scroll options\n// ScrollToOptions keeps its published shape: `align` is required, so reading it needs no undefined check\nconst publishedScrollToOptions: DSFastListT.ScrollToOptions = { align: 'start' };\nconst publishedAlign: 'start' | 'center' | 'end' | 'auto' = publishedScrollToOptions.align;\nconst scrollActionOptions: DSFastListT.ScrollActionOptions = { behavior: 'smooth' };\nconst handleScrollToWithActionOptions = () => actionRef.current.scrollTo?.(1, scrollActionOptions);\nconst handleScrollToWithPublishedOptions = () => actionRef.current.scrollTo?.(1, publishedScrollToOptions);\nconst handleScrollToAlign = () => actionRef.current.scrollTo?.(1, { align: 'center' });\nconst handleScrollToBehavior = () => actionRef.current.scrollTo?.(1, { behavior: 'smooth' });\nconst handleScrollToBoth = () => actionRef.current.scrollTo?.(1, { align: 'end', behavior: 'auto' });\n\n// actionRef method usages \u2014 measure() and getVisibleItems() (PUI-17898)\nconst handleMeasure = () => actionRef.current.measure?.();\nconst handleGetVisibleItems: () => number[] = () => actionRef.current.getVisibleItems?.() ?? [];\nconst handleGetMountedItems: () => number[] = () => actionRef.current.getMountedItems?.() ?? [];\n\n// single-shot scrolling primitives \u2014 getOffsetForIndex() + scrollToOffset()\nconst handleGetOffsetForIndex: () => number | undefined = () => actionRef.current.getOffsetForIndex?.(1);\nconst handleGetOffsetForIndexAligned: () => number | undefined = () =>\n actionRef.current.getOffsetForIndex?.(1, 'center');\nconst handleScrollToOffset = () => actionRef.current.scrollToOffset?.(100);\nconst handleScrollToOffsetWithOptions = () => actionRef.current.scrollToOffset?.(100, { behavior: 'auto' });\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSFastList {...testExplicitDefinition} />\n <DSFastList {...testInferredTypeCompatibility} />\n <DSFastList {...testDefinitionAsConst} />\n <DSFastList {...testGlobalAttributes} />\n <DSFastList {...testContainerIntegration} />\n <DSFastList {...testContainerIntegrationAsSyntax} />\n <DSFastList {...testContainerIntegrationAsConst} />\n {/* works with inline values */}\n <DSFastList\n ItemRenderer={MockItemRenderer}\n count={0}\n getId={(index: number) => ''}\n actionRef={actionRef}\n extraItemProps={{ foo: 'bar' }}\n />\n {/* Inline props test \u2014 container-integration props */}\n <DSFastList\n ItemRenderer={MockItemRenderer}\n count={0}\n getId={(index: number) => ''}\n innerRef={innerRefObject}\n paddingStart={24}\n paddingEnd={-5}\n remountOnCountChange={false}\n extraContent={<button type=\"button\">Load more</button>}\n dsFastlistExtraContent={{ role: 'listitem' }}\n />\n {/* Inline props test \u2014 global HTML/ARIA attributes */}\n <DSFastList\n className=\"custom-class\"\n id=\"custom-id\"\n aria-label=\"custom list\"\n data-testid=\"custom-testid\"\n ItemRenderer={MockItemRenderer}\n count={0}\n getId={(index: number) => ''}\n />\n </>\n);\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,9 +3,11 @@ export declare const DSFastListSlots: {
3
3
  readonly CONTAINER: "container";
4
4
  readonly WRAPPER_LIST: "wrapper-list";
5
5
  readonly ITEM: "item";
6
+ readonly EXTRA_CONTENT: "extra-content";
6
7
  };
7
8
  export declare const DSFastListDataTestIds: {
8
9
  readonly CONTAINER: "ds-fastlist-container";
9
10
  readonly WRAPPER_LIST: "ds-fastlist-wrapper-list";
10
11
  readonly ITEM: "ds-fastlist-item";
12
+ readonly EXTRA_CONTENT: "ds-fastlist-extra-content";
11
13
  };
@@ -3,7 +3,7 @@ import { type Virtualizer } from '@tanstack/react-virtual';
3
3
  import { type DSFastListT } from '../react-desc-prop-types.js';
4
4
  export type FastListCTX = {
5
5
  instanceUid: string;
6
- parentRef: React.MutableRefObject<HTMLDivElement | null>;
6
+ containerRef: React.MutableRefObject<HTMLDivElement | null> | React.RefCallback<HTMLDivElement>;
7
7
  getVirtualItems: Virtualizer<HTMLDivElement, HTMLElement>['getVirtualItems'];
8
8
  totalSize: ReturnType<Virtualizer<HTMLDivElement, HTMLElement>['getTotalSize']>;
9
9
  measureElement: Virtualizer<HTMLDivElement, HTMLElement>['measureElement'];
@@ -4,23 +4,38 @@ import type React from 'react';
4
4
  import { DSFastListName, DSFastListSlots } from './constants/index.js';
5
5
  export declare namespace DSFastListT {
6
6
  type ScrollAlignment = 'start' | 'center' | 'end' | 'auto';
7
+ /** Kept with its published shape (`align` required) so code that reads it keeps compiling. */
7
8
  type ScrollToOptions = {
8
9
  align: ScrollAlignment;
9
10
  };
11
+ /** What the scroll actions accept: `align` is optional and `behavior` can request a smooth scroll. */
12
+ type ScrollActionOptions = {
13
+ align?: ScrollAlignment;
14
+ behavior?: 'auto' | 'smooth';
15
+ };
16
+ /**
17
+ * `scrollTo` and `scrollToOffset` use method syntax on purpose: their parameters are compared bivariantly, so an
18
+ * `actionRef` typed with the published `(index, options?: ScrollToOptions) => void` stays assignable.
19
+ */
10
20
  type ActionRef = {
11
- scrollTo?: (index: number, options?: ScrollToOptions | undefined) => void;
21
+ scrollTo?(index: number, options?: ScrollActionOptions): void;
12
22
  measure?: () => void;
13
23
  getVisibleItems?: () => number[];
14
24
  getMountedItems?: () => number[];
25
+ getOffsetForIndex?: (index: number, align?: ScrollAlignment) => number | undefined;
26
+ scrollToOffset?(offset: number, options?: ScrollActionOptions): void;
15
27
  };
16
28
  type SlotFunctionArguments = {
17
29
  dsFastlistContainer: () => object;
18
30
  dsFastlistWrapperList: () => object;
19
31
  dsFastlistItem: () => object;
32
+ dsFastlistExtraContent: () => object;
20
33
  };
21
34
  interface OptionalProps<ExtraItemPropsT> extends TypescriptHelpersT.PropsForGlobalOnSlots<typeof DSFastListName, typeof DSFastListSlots> {
22
35
  actionRef?: React.MutableRefObject<ActionRef>;
23
36
  extraItemProps?: ExtraItemPropsT;
37
+ innerRef?: React.MutableRefObject<HTMLDivElement | null> | React.RefCallback<HTMLDivElement>;
38
+ extraContent?: React.ReactNode;
24
39
  }
25
40
  interface RequiredProps<ExtraItemPropsT> {
26
41
  ItemRenderer: React.ComponentType<{
@@ -32,6 +47,9 @@ export declare namespace DSFastListT {
32
47
  }
33
48
  interface DefaultProps {
34
49
  estimateSize: () => number;
50
+ paddingStart: number;
51
+ paddingEnd: number;
52
+ remountOnCountChange: boolean;
35
53
  }
36
54
  type PropsT<D, R, O> = Partial<D> & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;
37
55
  type InternalPropsT<D, R, O> = D & R & O & Omit<GlobalAttributesT<HTMLElement>, keyof D | keyof R | 'children'>;
@@ -40,5 +58,8 @@ export declare namespace DSFastListT {
40
58
  }
41
59
  export declare const defaultProps: {
42
60
  estimateSize: () => number;
61
+ paddingStart: number;
62
+ paddingEnd: number;
63
+ remountOnCountChange: boolean;
43
64
  };
44
65
  export declare const DSFastListPropTypes: React.WeakValidationMap<unknown>;