{"id":15385327,"url":"https://github.com/doeixd/create-virtualized-list-solid","last_synced_at":"2025-04-15T18:30:38.392Z","repository":{"id":255441938,"uuid":"851692408","full_name":"doeixd/create-virtualized-list-solid","owner":"doeixd","description":"A helpful wrapper around @tanstack/solid-virtual that simplifies the creation of virtualized lists in Solid.js","archived":false,"fork":false,"pushed_at":"2024-09-05T12:32:39.000Z","size":647,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T00:33:31.488Z","etag":null,"topics":["solid-js","solidjs","tanstack-virtual","virtualized-list","virtualizedlist"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doeixd.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-03T14:53:10.000Z","updated_at":"2025-03-20T22:20:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"efe44291-41e1-4428-b582-84e8c974b648","html_url":"https://github.com/doeixd/create-virtualized-list-solid","commit_stats":{"total_commits":46,"total_committers":1,"mean_commits":46.0,"dds":0.0,"last_synced_commit":"005ef6176ab7b7fc3b7bcde7784e856ed22d8eba"},"previous_names":["doeixd/create-virtualized-list-solid"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doeixd%2Fcreate-virtualized-list-solid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doeixd%2Fcreate-virtualized-list-solid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doeixd%2Fcreate-virtualized-list-solid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doeixd%2Fcreate-virtualized-list-solid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doeixd","download_url":"https://codeload.github.com/doeixd/create-virtualized-list-solid/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249128873,"owners_count":21217233,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["solid-js","solidjs","tanstack-virtual","virtualized-list","virtualizedlist"],"created_at":"2024-10-01T14:44:27.888Z","updated_at":"2025-04-15T18:30:38.020Z","avatar_url":"https://github.com/doeixd.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Solid.js Virtualized List Wrapper\n\nA helpful wrapper around `@tanstack/solid-virtual` that simplifies the creation of virtualized lists in Solid.js apps while maintaining full access to the underlying virtualizer.\n\n## Features\n\n- Simplifies the setup of virtualized lists\n- Automatically generates `root` and `container` props\n- Provides extra information for each item (e.g., `isLast`, `isEven`)\n- Automatically determines the count based on your data\n- Maintains full access to all `@tanstack/solid-virtual` features\n- Includes a higher-level `VirtualizedList` component for simple use cases\n\n## Installation\n\n```bash\nnpm install @doeixd/create-virtualized-list-solid\n```\n\n## Basic Usage\n\n```jsx\nimport { createVirtualizedList } from '@doeixd/create-virtualized-list-solid';\nimport { For } from 'solid-js';\n\nconst MyList = () =\u003e {\n  const items = () =\u003e Array.from({ length: 10000 }, (_, i) =\u003e `Item ${i + 1}`);\n\n  const virtualList = createVirtualizedList({\n    data: items,\n  });\n\n  return (\n    \u003cdiv {...virtualList.root}\u003e\n      \u003cdiv {...virtualList.container}\u003e\n        \u003cFor each={virtualList.item}\u003e\n          {virtualList.items((item) =\u003e (\n            \u003cdiv {...item.props}\u003e\n              {item.data} \n              {item.virtualItem.isLast \u0026\u0026 ' (Last Item)'}\n              {item.virtualItem.isEven \u0026\u0026 ' (Even Index)'}\n            \u003c/div\u003e\n          ))}\n        \u003c/For\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n## VirtualizedList Component\n\nFor simple use cases we provide a `VirtualizedList` component\n\n```jsx\nimport { VirtualizedList } from '@doeixd/create-virtualized-list-solid';\n\nconst MyList = () =\u003e {\n  const items = Array.from({ length: 10000 }, (_, i) =\u003e `Item ${i + 1}`);\n\n  return (\n    \u003cVirtualizedList\n      data={items}\n      height={400}\n      width={300}\n      renderItem={({ item, virtualItem }) =\u003e (\n        \u003cdiv style={{ \n          padding: '10px',\n          background: virtualItem.isEven ? '#f0f0f0' : 'white'\n        }}\u003e\n          {item}\n          {virtualItem.isLast \u0026\u0026 ' (Last Item)'}\n        \u003c/div\u003e\n      )}\n    /\u003e\n  );\n};\n```\nThe `VirtualizedList` component simplifies the creation of virtualized lists even further, handling all the setup and providing a clean interface for rendering items.\n\n## Why is this hepful?\n\n### Root and Container Elements\n\nIn a virtualized list, two key elements are required:\n\n1. **Root Element**: This is the scrollable viewport. It determines the visible area of the list.\n2. **Container Element**: This is a tall element that provides the full scrollable height/width of the list.\n\nManually setting up these elements with the correct properties can be tedious and error-prone. Our wrapper generates the necessary props for both elements, ensuring:\n\n- Correct sizing and positioning\n- Proper event handling for virtualization\n- Consistent styling defaults\n\nBy using `{...vList.root}` and `{...vList.container}`, you automatically apply all necessary properties without having to manage them yourself.\n\n### The `list.items` Helper\n\nThe `list.items` helper is a function that wraps each item in your list, providing:\n\n- Correct positioning within the container\n- Access to the virtual item data\n- Additional useful properties like `isLast` and `isEven`\n\nThis helper simplifies the rendering of each item and provides a consistent interface for working with your list data.\n\n### Before and After Comparison\n\nHere's how the wrapper simplifies your code:\n\n#### Before (using @tanstack/solid-virtual directly):\n\n```jsx\nimport { createVirtualizer } from '@tanstack/solid-virtual';\nimport { createSignal, For } from 'solid-js';\n\nconst VirtualList = () =\u003e {\n  const [listItems] = createSignal(Array.from({ length: 10000 }, (_, i) =\u003e `Item ${i}`));\n  const [parentRef, setParentRef] = createSignal(null);\n\n  const virtualizer = createVirtualizer({\n    count: listItems().length,\n    getScrollElement: () =\u003e parentRef(),\n    estimateSize: () =\u003e 35,\n    overscan: 5,\n  });\n\n  return (\n    \u003cdiv \n      ref={setParentRef} \n      style={{\n        height: '400px', \n        overflow: 'auto'\n      }}\n    \u003e\n      \u003cdiv \n        style={{\n          height: `${virtualizer.getTotalSize()}px`,\n          width: '100%', \n          position: 'relative'\n        }}\n      \u003e\n        \u003cFor each={virtualizer.getVirtualItems()}\u003e\n          {(virtualRow) =\u003e (\n            \u003cdiv\n              style={{\n                position: 'absolute',\n                top: 0,\n                left: 0,\n                width: '100%',\n                height: `${virtualRow.size}px`,\n                transform: `translateY(${virtualRow.start}px)`,\n              }}\n            \u003e\n              {listItems()[virtualRow.index]}\n            \u003c/div\u003e\n          )}\n        \u003c/For\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n#### After (using our wrapper):\n\n```jsx\nimport { createVirtualizedList } from '@doeixd/solid-virtualized-list-wrapper';\nimport { For } from 'solid-js';\n\nconst VirtualList = () =\u003e {\n  const listItems = () =\u003e Array.from({ length: 10000 }, (_, i) =\u003e `Item ${i}`);\n\n  const vList = createVirtualizedList({\n    data: listItems,\n  });\n\n  return (\n    \u003cdiv {...vList.root}\u003e\n      \u003cdiv {...vList.container}\u003e\n        \u003cFor each={vList.item}\u003e\n          {vList.items((item) =\u003e (\n            \u003cdiv {...item.props}\u003e{item.data}\u003c/div\u003e\n          ))}\n        \u003c/For\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\nAs you can see, the wrapper:\n\n1. Eliminates the need to manually set up the virtualizer\n2. Automatically generates necessary props for root and container elements\n3. Provides a simpler interface for rendering items\n4. Handles positioning and styling of items internally\n5. Reduces boilerplate and potential for errors\n\nBy abstracting these details, the wrapper allows you to focus on your list content rather than the complexities of virtualization.\n\n## API\n\n### `createVirtualizedList(args)`\n\nCreates a virtualized list wrapper.\n\n#### Parameters\n\n`args`: An object that extends `VirtualizerOptions` from `@tanstack/solid-virtual` with additional properties:\n\n- `data`: Function returning an array of items to be rendered\n- `itemHeight`: (Optional) Fixed height for items\n- `width`: (Optional) Width of the list container\n- `height`: (Optional) Height of the list container\n- `rootProps`: (Optional) Additional props for the root element\n- `containerProps`: (Optional) Additional props for the container element\n- `itemProps`: (Optional) Additional props for each item element\n\nAll other `VirtualizerOptions` are also accepted and passed through to the underlying virtualizer.\n\n#### Returns\n\nAn object with the following properties:\n\n- `root`: Getter function for root element props\n- `container`: Getter function for container element props\n- `items`: Function to create item wrappers with extra info\n- `virtualizer`: The underlying `@tanstack/solid-virtual` instance\n- `id`: Unique identifier for the list\n- `count`: Getter function for total item count (automatically determined)\n- `item`: Getter function for virtual items (alias for `virtualizer.getVirtualItems()`)\n\n### `VirtualizedList\u003cT\u003e(props)`\n\nCreates a simple generic virtualized list component.\n\n#### Props\n\n- `data`: Array of items to be rendered\n- `renderItem`: Function to render each item\n- `height`: Height number of pixels for the list container\n- `width`: Width number of pixels for the list container\n- `className`: Optional CSS class for the list container\n- `style`: Optional inline styles for the list container\n\nAll other props from `VirtualizerOptions` are also accepted and passed through to the underlying virtualizer.\n\n\n\n## Advanced Usage\n\n### Accessing the virtualizer\nYou can access all features of `@tanstack/solid-virtual` through the `virtualizer` property:\n\n```jsx\nconst virtualList = createVirtualizedList({\n  data: items,\n  // ... other options\n})\n\n// Use any @tanstack/solid-virtual method\nvirtualList.virtualizer.scrollToIndex(50)\n```\n### Reactivity\n\n#### Item rendering\nIn the `virtualList.items` function we allow you to provide a boolean representing whether or not you'd like reactivity inside the callback function for item rendering, allowing you to balance performance and reactivity based on your specific needs.\n\n##### How it works\nYou can now specify whether each item should track changes and re-render, or use the default untracked behavior for maximum performance.\n```tsx\nimport { createVirtualizedList } from '@doeixd/create-virtualized-list-solid';\nimport { For } from 'solid-js';\n\nconst MyList = () =\u003e {\n  const items = () =\u003e Array.from({ length: 10000 }, (_, i) =\u003e `Item ${i + 1}`);\n\n  const virtualList = createVirtualizedList({\n    data: items,\n  });\n\n  return (\n    \u003cdiv {...virtualList.root}\u003e\n      \u003cdiv {...virtualList.container}\u003e\n        \u003cFor each={virtualList.item}\u003e\n          {virtualList.items((item) =\u003e (\n            \u003cdiv {...item.props}\u003e\n              {item.data} \n              {item.virtualItem.isLast \u0026\u0026 ' (Last Item)'}\n              {item.virtualItem.isEven \u0026\u0026 ' (Even Index)'}\n            \u003c/div\u003e\n          ), true)} {/* Set to true to enable change tracking */}\n        \u003c/For\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )\n}\n```\nBy setting the second parameter of `virtualList.items` to true, you enable change tracking for that item. This allows the item to react to changes in its data or properties, at the cost of some performance.\n\n##### When to use change tracking\nFor items that need to update frequently based on external state\nWhen implementing dynamic content that changes after initial render\nFor interactive elements within list items\n\n##### When to use untracked rendering (default)\nFor static content that doesn't change after initial render\nWhen optimizing for maximum performance with large lists\nFor simple, non-interactive list items\n\nThis hybrid approach allows you to fine-tune the balance between performance and reactivity in your virtualized lists.\n\n#### Virtualizer \nThe `createVirtualizedList` function is designed to be reactive to changes in its options and data. Here's how reactivity is handled for the virtualizer:\n\n1. **Options Reactivity**: \n   The virtualizer options are wrapped in a `createMemo`, which means they will automatically update if any reactive dependencies change. This includes changes to the `data` function, `count`, or any other option passed to `createVirtualizedList`.\n\n   ```jsx\n   const [itemHeight, setItemHeight] = createSignal(50);\n   const virtualList = createVirtualizedList({\n     data: items,\n     estimateSize: () =\u003e itemHeight()\n   });\n\n   // Later, updating itemHeight will cause the virtualizer to update\n   setItemHeight(75);\n   ```\n\n2. **Data Changes**:\n   If your `data` function is reactive (e.g., it's based on a signal or store), changes to the underlying data will automatically be reflected in the virtualizer.\n\n   ```jsx\n   const [items, setItems] = createSignal([...]);\n   const virtualList = createVirtualizedList({\n     data: items\n   });\n\n   // Later, updating items will cause the virtualizer to update\n   setItems([...newItems]);\n   ```\n\n3. **Manual Updates**:\n   In some cases, you might need to manually trigger an update of the virtualizer. You can do this by accessing the underlying virtualizer instance:\n\n   ```jsx\n   virtualList.virtualizer.measure();  // Force remeasure all items\n   virtualList.virtualizer.getVirtualItems();  // Force recalculation of virtual items\n   ```\n\n4. **Resize Handling**:\n   The virtualizer automatically handles window resize events. If you're using a custom container and its size changes, you might need to manually notify the virtualizer:\n\n   ```jsx\n   window.addEventListener('custom-resize', () =\u003e {\n     virtualList.virtualizer.measure();\n   });\n   ```\n\nBy leveraging Solid.js's fine-grained reactivity system, `createVirtualizedList` ensures that your virtualized lists stay up-to-date and performant, even as the underlying data or configuration changes. This reactive approach allows you to create dynamic, responsive lists without manually managing updates to the virtualizer.\n\n## TypeScript Support\n\nThis wrapper is written in TypeScript and provides type definitions:\n\n```tsx\ninterface MyItem {\n  id: number;\n  name: string;\n}\n\nconst virtualList = createVirtualizedList\u003cMyItem\u003e({\n  data: () =\u003e myItems,\n  // ... other options\n})\n```\n\n```tsx\ninterface MyItem {\n  id: number;\n  name: string;\n}\n\nconst MyList = () =\u003e {\n  const items: MyItem[] = [/* ... */];\n\n  return (\n    \u003cVirtualizedList\u003cMyItem\u003e\n      data={items}\n      height={400}\n      width={300}\n      renderItem={({ item }) =\u003e \u003cdiv\u003e{item.name}\u003c/div\u003e}\n      determineKey={(item) =\u003e item.id}\n    /\u003e\n  );\n};\n```\n\n## Requirements\n\n- Solid.js\n- @tanstack/solid-virtual\n\n\n## Contributing\nContributions are welcome! Feel free to open issues or submit pull requests.\n\n## License\n\nThis project is licensed under the MIT License.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoeixd%2Fcreate-virtualized-list-solid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoeixd%2Fcreate-virtualized-list-solid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoeixd%2Fcreate-virtualized-list-solid/lists"}