### Basic Grid Example Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/intro.md Creates a grid layout of letters using state-based rendering. This example demonstrates adjusting the dimensions for a grid. Ensure UltimateList components, data sources, dimensions, and renderers are imported. ```lua local letters = {} for offset = 0, 25 do table.insert(letters, string.char(string.byte("A") + offset)) end return React.createElement("Frame", { Size = UDim2.fromOffset(300, 300), }, { ScrollingFrame = React.createElement(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(letters), dimensions = UltimateList.Dimensions.consistentUDim2( UDim2.new(0.33, 0, 0, 72) ), renderer = UltimateList.Renderers.byState(function(value) return React.createElement("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSansBold, Text = value, TextColor3 = Color3.new(0, 0, 0), TextSize = 36, Size = UDim2.fromScale(1, 1), }) end), direction = "y", }), }) ``` -------------------------------- ### Basic List Example Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/intro.md Creates a simple vertical list of letters using state-based rendering. Ensure UltimateList components, data sources, dimensions, and renderers are imported. ```lua local letters = {} for offset = 0, 25 do table.insert(letters, string.char(string.byte("A") + offset)) end return React.createElement("Frame", { Size = UDim2.fromOffset(300, 300), }, { ScrollingFrame = React.createElement(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(letters), dimensions = UltimateList.Dimensions.consistentSize(48), renderer = UltimateList.Renderers.byState(function(value) return React.createElement("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSansBold, Text = value, TextColor3 = Color3.new(0, 0, 0), TextSize = 36, Size = UDim2.fromScale(1, 1), }) end), direction = "y", }), }) ``` -------------------------------- ### Player Name Renderer using byBinding Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/renderers.md Use `byBinding` when an item's data can be fully represented by properties. This example shows rendering a player's display name using a React binding, which is more performant for scrolling. ```lua renderer = UltimateList.Renderers.byBinding(function(playerBinding: React.Binding) return React.createElement("TextLabel", { Size = UDim2.fromScale(1, 1), Text = playerBinding:map(function(player: Player?) return if player then player.DisplayName else "" end), }) end) ``` -------------------------------- ### MutableDataSourceMethods Type Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Defines the methods for interacting with a mutable data source, including getting elements by index or range, and binding to change events. Extensive documentation is available in the mutable sources documentation. ```typescript type MutableDataSourceMethods = { -- Get a cursor to the nth element get: (startIndex: number) -> DataSourceCursor?, -- Get the total length of the data source length: () -> number, -- Is given a callback to run when the data source changes. -- Returns a destructor to disconnect the function. bindToChanged: (callback: () -> ()) -> () -> (), -- The following have default definitions, but can be specialized to be more efficient. -- Get the final element (defaults to get(length())) back: (() -> T?)?, -- Get the elements from startIndex to and including endIndex. -- Defaults to using the `after` in your cursors. getByRange: ((startIndex: number, endIndex: number) -> { T })?, } ``` -------------------------------- ### Simple String Renderer using byState Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/renderers.md Use `byState` for a simple list of strings. The callback receives the item directly and returns a React element. UltimateList manages mounting and unmounting based on visibility. ```lua -- ... renderer = UltimateList.Renderers.byState(function(item: string) return React.createElement("TextLabel", { -- UltimateList puts your item in a frame matching -- your specified size and position. Size = UDim2.fromScale(1, 1), Text = item, }) end) ``` -------------------------------- ### Calculate Item Positions and Sizes in Lua Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/supporting-different-items.mdx Iterate through your items, determine the height for each based on its type, and calculate its position and size. This prepares the data for the virtualized list. ```lua -- Assuming ITEMS is an array of Item... local itemsWithUDimRects: { ItemWithUDimRect } = {} local nextPosition = UDim2.new() for _, item in ITEMS do local height = if item.type == "category" then 32 else 24 table.insert(itemsWithUDimRects, { item = item, udimRect = { size = UDim2.new(1, 0, 0, height), position = nextPosition, }, }) nextPosition += UDim2.fromOffset(0, height) end ``` -------------------------------- ### Complex Component Renderer using byState Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/renderers.md Demonstrates using `byState` with a more complex React component that utilizes hooks and dynamic children. This approach is highly flexible for intricate UIs. ```lua -- Example of component that takes full advantage of state local function MyComplicatedComponent(props: { player: Player, }) local inventory = useInventory(props.player) local inventoryItems = {} for _, item in inventory do inventoryItems[item.key] = React.createElement(InventoryItem, { item = item, }) end return React.createElement(PlayerCard, { name = name, }, inventoryItems) end -- ... renderer = UltimateList.Renderers.byState(function(item: Player) return React.createElement(MyComplicatedComponent, { player = item, }) end) ``` -------------------------------- ### DataSources.utilities.createGetSimpleCursor Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a wrapper around a simple getter function to make it produce the expected `DataSourceCursor`. ```APIDOC ### `utilities.createGetSimpleCursor` ```ts DataSources.utilities.createGetSimpleCursor( get: (index: number) -> T, getLength: () -> number ): (startIndex: number) -> DataSourceCursor? ``` Creates a wrapper around a simple getter function to make it produce the expected `DataSourceCursor` of `get`. See also [the documentation in mutable sources](./core-concepts/data-sources#get-startindex-number---datasourcecursort). ``` -------------------------------- ### Mutable Source with Simple Cursor Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/data-sources.md Implements a mutable data source using the createGetSimpleCursor utility for efficient data retrieval without requiring immutable arrays. ```lua UltimateList.DataSources.mutableSource({ get = DataSources.utilities.createGetSimpleCursor( -- Getter function(index: number): T -- Note that we return `T` and not `T?`. -- UltimateList will never provide an index not in the range of 1 <= index <= length, -- and thus every element being requested is expected to exist. return myData[index] end, -- Get length function(): number return #number end ), -- Other required fields... }) ``` -------------------------------- ### Understanding Type Signatures Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/data-sources.md Explains how to read complex type signatures, breaking down function types and callbacks. ```typescript bindToChanged: () -> () bindToChanged: () -> () -> () bindToChanged: (callback: () -> ()) -> () -> () type Callback = () -> () // ... bindToChanged: (Callback) -> Callback ``` -------------------------------- ### Create a ScrollingFrame with Data Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Instantiates a ScrollingFrame for virtualized lists. Requires data source, dimensions, and renderer. Supports optional configuration for tags, native styling, key generation, and scroll callbacks. ```typescript ScrollingFrame( dataSource: DataSources.DataSource, dimensions: Dimensions.Dimensions, renderer: Renderers.Renderer, direction: "x" | "y" ) ``` -------------------------------- ### Configure ScrollingFrame with Getter Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/supporting-different-items.mdx Initialize the ScrollingFrame component, providing the prepared data source and a getter function for dimensions. The getter function returns the pre-calculated `udimRect` for each item. ```lua ScrollingFrame = e(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(itemsWithUDimRects), dimensions = UltimateList.Dimensions.getter(function(itemWithUDimRect: ItemWithUDimRect) return itemWithUDimRect.udimRect end), renderer = UltimateList.Renderers.byState(function(itemWithUDimRect: ItemWithUDimRect) -- soon... end), direction = "y", }), ``` -------------------------------- ### Consistent Two-Dimensional Size (Grid) Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/dimensions.md Employ `Dimensions.consistentUDim2(udim2)` for grid layouts where all cells have the same dimensions. Ensure the scale for the dominant axis (Y for vertical, X for horizontal) is not provided, as it's determined by content. ```lua dimensions = UltimateList.Dimensions.consistentUDim2(UDim2.new( 1/4, -- Horizontal scale: 1/4th of a row 0, -- Horizontal offset, in this case 0px. 0, -- Vertical scale: MUST be 0, since we are a vertical list. 100 -- Vertical offset: 100px )) ``` -------------------------------- ### Create a Scrolling Frame with UltimateList Source: https://github.com/kampfkarren/ultimate-list/blob/main/README.md This snippet demonstrates how to create a virtualized scrolling list using UltimateList's ScrollingFrame component. It configures the data source, item dimensions, and a renderer for list items. ```luau return React.createElement(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(letters), dimensions = UltimateList.Dimensions.consistentSize(48), renderer = UltimateList.Renderers.byState(function(value) return React.createElement("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSansBold, Text = value, TextColor3 = Color3.new(0, 0, 0), TextSize = 36, Size = UDim2.fromScale(1, 1), }) end), direction = "y", }) ``` -------------------------------- ### Renderers.byState Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a renderer that calls a callback for each item to generate a React node. Re-renders occur on scroll, and items are unmounted when not visible. ```APIDOC ## Renderers.byState ### Description Takes a callback that turns a direct value into a React node. When the user scrolls, we will trigger a re-render and call that callback again. When an item is no longer visible, it is unmounted--elements are not reused for different items. ### Method Signature ```ts Renderers.byState( callback: (T) -> React.Node, config: { freezeViewWhileScrolling: boolean?, }? ): Renderer ``` ### Parameters #### Callback Function - `callback` (function): A function that takes an item of type `T` and returns a React node. #### Configuration Object (`config`) - `freezeViewWhileScrolling` (boolean, optional): Defaults to `true`. If enabled, the overlay view moves only after rendering is complete, ensuring consistent appearance but potentially causing lag. If disabled, scrolling is smoother but may show empty space during rendering. ``` -------------------------------- ### Create Simple Cursor Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Wraps a simple getter function to produce the expected DataSourceCursor. Useful for integrating custom data retrieval logic. ```typescript DataSources.utilities.createGetSimpleCursor( get: (index: number) -> T, getLength: () -> number ): (startIndex: number) -> DataSourceCursor? ``` -------------------------------- ### Create Simple Cursor Utility Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/data-sources.md A utility function to create a DataSourceCursor from a simple getter function and a length function. Useful when the data structure only supports direct indexing. ```typescript DataSources.utilities.createGetSimpleCursor( get: (index: number) -> T, getLength: () -> number, ) ``` -------------------------------- ### ScrollingFrame Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a ScrollingFrame for a virtualized list. It requires a data source, dimensions, and a renderer, and can be configured for horizontal or vertical scrolling. ```APIDOC ## ScrollingFrame Creates a ScrollingFrame that will make a virtualized list based on your specifications. `T` is the type of the items we are representing. **Props** - `dataSource: DataSources.DataSource`: The [data source](./core-concepts/data-sources) we are creating a list for. - `dimensions: Dimensions.Dimensions`: The [dimensions](./core-concepts/dimensions) that will determine how big an item is, and where it is placed. - `renderer: Renderers.Renderer`: The [renderer](./core-concepts/renderers) that will determine what an item looks like. - `direction: "y" | "x"`: "y" for a vertical list, "x" for a horizontal list. **Optional props** - `tag: string`: A tag to apply onto the ScrollingFrame. Useful for using [the Roblox UI styling system](https://create.roblox.com/docs/ui/styling). - `native: { [any]: any }`: All fields here will be applied on top of the ScrollingFrame. See also [styling with native](./guides/styling#native-property). - `getKey: (value: T, index: number) -> string`: A function that will return a unique key for a given item. By default UltimateList will use the index, but you will want to specify this if your list is not append-only. - `scrollingFrameRef: React.Ref`: A ref to the underlying ScrollingFrame. Note that the actual contents are stored in a separate frame that you cannot access. - `onAbsoluteWindowSizeChanged: (newWindowSize: Vector2) -> ()`: A callback that will run when the [window size of the ScrollingFrame](https://create.roblox.com/docs/reference/engine/classes/ScrollingFrame#AbsoluteWindowSize) changes. - `onScrollAxisChanged: (newScrollAxis: number) -> ()`: A callback that will run when the ScrollingFrame changes CanvasPosition. The number provided is the position of the dominant axis--so in a vertical list, it represents `CanvasPosition.Y`. ``` -------------------------------- ### Binding-Based Renderer Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/intro.md Configures a renderer to use bindings for potentially better performance during scrolling. This is an alternative to `byState` and requires a function that accepts a binding and returns a Roact element. ```lua renderer = UltimateList.Renderers.byBinding(function(valueBinding) return React.createElement("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSansBold, Text = valueBinding:map(function(value: string?) return value or "" end), TextColor3 = Color3.new(0, 0, 0), TextSize = 36, Size = UDim2.fromScale(1, 1), }) end), ``` -------------------------------- ### Prepare Item with Dynamic Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/supporting-different-items.mdx Define a type to hold both the item data and its calculated dimensions (size and position). This is necessary for getter dimensions, which require pre-calculated layout information. ```typescript type ItemWithUDimRect = { item: Item, udimRect: UltimateList.UDimRect, } ``` -------------------------------- ### Renderers.byBinding Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a renderer that uses a callback with a React binding to generate a React node. Elements are reused and bindings updated directly on scroll, eliminating React re-renders. ```APIDOC ## Renderers.byBinding ### Description Takes a callback that provides a React node based on the provided binding. When the user scrolls, these elements will be re-used, and the binding will be updated directly. This means as the user scrolls, there will be zero React re-renders. The value you get will be nil if there is no item occupying that space. ### Method Signature ```ts Renderers.byBinding( callback: (React.Binding) -> React.Node ): Renderer ``` ### Parameters #### Callback Function - `callback` (function): A function that takes a `React.Binding` and returns a React node. The binding provides the item value, which can be nil if no item occupies the space. ``` -------------------------------- ### Dimensions.consistentUDim2 Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Dictates that all items are of the same size, represented as a UDim2. ```APIDOC ### `consistentUDim2` ```ts Dimenions.consistentUDim2( udim2: UDim2 ): Dimensions ``` Dictates that all items are of the same size, represented as a UDim2. The items will then be put one after another until they reach the end of the row/column, and wrap around. See also: [consistent, two-dimensonal size](./core-concepts/dimensions#consistent-two-dimensional-size). ``` -------------------------------- ### Conditionally Render Items Based on Type Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/supporting-different-items.mdx Implement the renderer function to check the `type` property of each item and return the appropriate UI element (e.g., a bold TextLabel for categories, a regular TextLabel for text items). ```lua renderer = UltimateList.Renderers.byState(function(itemWithUDimRect: ItemWithUDimRect) if itemWithUDimRect.item.type == "category" then return e("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSansBold, Text = itemWithUDimRect.item.name, TextColor3 = Color3.new(0, 0, 0), TextSize = 30, Size = UDim2.fromScale(1, 1), }) else return e("TextLabel", { BackgroundColor3 = Color3.new(1, 1, 1), Font = Enum.Font.BuilderSans, Text = itemWithUDimRect.item.text, TextColor3 = Color3.new(0, 0, 0), TextSize = 20, Size = UDim2.fromScale(1, 1), }) end end), ``` -------------------------------- ### Immutable Array Data Source Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/data-sources.md Provides a static array as a data source. The array must be immutable; updates require providing a new array instance. ```lua local letters = {} for offset = 0, 25 do table.insert(letters, string.char(string.byte("A") + offset)) end return React.createElement(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(letters), -- Rest omitted... }) ``` -------------------------------- ### Dimensions.consistentSize Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Dictates that all items are of the same size. ```APIDOC ### `consistentSize` ```ts Dimensions.consistentSize( size: number ): Dimensions ``` Dictates that all items are of the same size. In a vertical list, this means they are all the same height. In a horizontal list, this means that they are all the same width. See also: [consistent, one-dimensonal size](./core-concepts/dimensions#consistent-one-dimensional-size). ``` -------------------------------- ### Create Spaced Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/dimensions.md Use `UltimateList.Dimensions.withSpacing` to define dimensions with even spacing between items. This is useful for lists where items need consistent gaps. This method works with `consistentSize` or `consistentUDim2`. ```lua dimenions = UltimateList.Dimensions.withSpacing( UltimateList.Dimensions.consistentSize(32), 8 ) ``` -------------------------------- ### Dynamic Size and Position Getter Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/dimensions.md Utilize `Dimensions.getter` to provide a function that calculates the size and position for each item dynamically. This is suitable for lists with variable item heights, such as those containing wrapped text or different item types. The getter function must be stateless. ```lua dimensions = UltimateList.Dimensions.getter(function(value, _index) return { size = UDim2.new(...), position = UDim2.new(...), } end) ``` ```lua dimensions = UltimateList.Dimensions.getter(function(value: Item) return { size = UDim2.new(1, 0, 0, value.height), position = UDim2.fromOffset(0, value.yOffset), } end) ``` -------------------------------- ### Mutable Data Source Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a data source from an abstract mutable structure. Use this for dynamic data that changes over time. ```typescript DataSources.mutableSource( methods: MutableDataSourceMethods ): DataSource ``` -------------------------------- ### DataSources.array Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Represents a data source based on an immutable array. ```APIDOC ### `array` ```ts DataSources.array( array: { T } ): DataSource ``` Represents a data source based on an immutable array. See also [the array data source](./core-concepts/data-sources#arrays). ``` -------------------------------- ### byState Renderer Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Defines a renderer that maps items to React nodes. Each item is unmounted when it becomes invisible. Use this when rendering expensive components or when item identity is crucial. ```typescript Renderers.byState( callback: (T) -> React.Node, config: { freezeViewWhileScrolling: boolean?, }? ): Renderer ``` -------------------------------- ### Dimensions.withSpacing Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Adds spacing in between each element when given a consistent set of dimensions. ```APIDOC ### `withSpacing` ```ts Dimensions.withSpacing( inner: Dimensions, spacing: number ) ``` Given a consistent set of dimensions, will adding spacing in between each element. See also: [spaced dimensions](./core-concepts/dimensions#spaced-dimensions). ``` -------------------------------- ### Dimensions.getter Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Specifies that the size and position of an item is determined by a callback function. ```APIDOC ### `getter` ```ts Dimensions.getter( callback: (value: T, index: number) -> UDimRect ): Dimensions ``` Specifies that the size and position of an item is not the same for all of them, and instead uses the callback provided to know what the size and position are. See also: [dynamically determined size and position](./core-concepts/dimensions#dynamically-determined-size-and-position). ``` -------------------------------- ### Consistent One-Dimensional Size Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/dimensions.md Use `UltimateList.Dimensions.consistentSize(size)` when all elements in the list share the same height (for vertical lists) or width (for horizontal lists). The non-dominant axis will automatically be set to 100% of the window. ```lua dimensions = UltimateList.Dimensions.consistentSize(32) ``` -------------------------------- ### Array Data Source Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Creates a data source from an immutable array. Use this when your list data does not change. ```typescript DataSources.array( array: { T } ): DataSource ``` -------------------------------- ### DataSources.mutableSource Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Represents a data source based on an abstract mutable structure. ```APIDOC ### `mutableSource` ```ts DataSources.mutableSource( methods: MutableDataSourceMethods ): DataSource ``` Represents a data source based on an abstract mutable structure. See also [mutable sources](./core-concepts/data-sources#mutable-sources), which includes a full breakdown on what methods are accepted. ``` -------------------------------- ### Apply Native Styles to ScrollingFrame Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/styling.md Use the `native` property to forward styles directly to the ScrollingFrame when style sheets are insufficient or when needing to hook into events. Note that certain properties like Size and CanvasSize are managed by UltimateList and should not be set directly. ```lua return React.createElement(UltimateList.Components.ScrollingFrame, { native = { BackgroundTransparency = 1, }, -- etc }) ``` -------------------------------- ### Getter Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Specifies item size and position using a callback function. Use this for lists with dynamically sized and positioned items. ```typescript Dimensions.getter( callback: (value: T, index: number) -> UDimRect ): Dimensions ``` -------------------------------- ### Style ScrollingFrame Container Size Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/styling.md Set the size of the ScrollingFrame by styling its parent container. This is useful for defining fixed dimensions like 300x300 pixels. ```lua return React.createElement("Frame", { Size = UDim2.fromOffset(300, 300), }, { ScrollingFrame = React.createElement(UltimateList.Components.ScrollingFrame, { -- etc }) }) ``` -------------------------------- ### byBinding Renderer Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Defines a renderer that uses React bindings for efficient updates. Elements are reused and bindings are updated directly, minimizing React re-renders during scrolling. Use this for performance-critical lists. ```typescript Renderers.byBinding( callback: (React.Binding) -> React.Node ): Renderer ``` -------------------------------- ### Dimensions with Spacing Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Adds spacing between elements when using a consistent set of dimensions. Ensures visual separation between list items. ```typescript Dimensions.withSpacing( inner: Dimensions, spacing: number ) ``` -------------------------------- ### DataSourceCursor Type Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Represents a position within a data source, providing methods to navigate before and after the current value. Used for mutable data sources. ```typescript type DataSourceCursor = { before: () -> DataSourceCursor?, value: T, after: () -> DataSourceCursor?, } ``` -------------------------------- ### Consistent Size Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Defines dimensions for a list where all items have the same size. Suitable for uniform lists in vertical or horizontal orientations. ```typescript Dimensions.consistentSize( size: number ): Dimensions ``` -------------------------------- ### Dynamic Immutable Array Data Source Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/core-concepts/data-sources.md Dynamically updates an immutable array using React's useState and useEffect. New array instances are created for each update to maintain immutability. ```lua local letters: { string }, setLetters = React.useState({} :: { string }) React.useEffect(function() local thread = task.spawn(function() for offset = 0, 25 do -- Update the `letters` state, but never mutating the array. setLetters(function(newLetters) newLetters = table.clone(newLetters) table.insert(newLetters, string.char(string.byte("A") + offset)) return newLetters end) task.wait(0.5) end end) return function() task.cancel(thread) end end, {}) return React.createElement(UltimateList.Components.ScrollingFrame, { dataSource = UltimateList.DataSources.array(letters), -- Rest omitted... }) ``` -------------------------------- ### Consistent UDim2 Dimensions Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Defines dimensions where all items share the same UDim2 size. Items wrap around rows/columns. ```typescript Dimenions.consistentUDim2( udim2: UDim2 ): Dimensions ``` -------------------------------- ### Define Tagged Union for Mixed Item Types Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/guides/supporting-different-items.mdx Create a TypeScript type that represents different kinds of items within the list. This allows a single data structure to hold various item formats. ```typescript type Item = { type: "category", name: string, } | { type: "text", text: string, } ``` -------------------------------- ### UDimRect Type Source: https://github.com/kampfkarren/ultimate-list/blob/main/docs/docs/api-reference.md Represents a rectangular dimension with size and position, both defined using UDim2. This type is used for dimension getters. ```typescript type UDimRect = { size: UDim2, position: UDim2, } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.