{"id":13659509,"url":"https://github.com/jordond/drag-select-compose","last_synced_at":"2025-10-04T13:03:26.881Z","repository":{"id":175674577,"uuid":"654306203","full_name":"jordond/drag-select-compose","owner":"jordond","description":"⚡ A Compose multiplatform library for adding Google Photos style drag-to-select multi-selection to a LazyGrid","archived":false,"fork":false,"pushed_at":"2025-04-09T19:28:02.000Z","size":13842,"stargazers_count":225,"open_issues_count":14,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T21:57:05.974Z","etag":null,"topics":["android","compose","compose-desktop","compose-ios","compose-multiplatform","drag-selection","drag-selection-library","google-photos","kotlin","kotlin-multiplatform","kotlin-multiplatform-library","kotlin-multiplatform-mobile"],"latest_commit_sha":null,"homepage":"https://demo.dragselectcompose.com","language":"Kotlin","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/jordond.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2023-06-15T20:52:11.000Z","updated_at":"2025-02-27T20:37:36.000Z","dependencies_parsed_at":"2023-10-05T02:47:33.083Z","dependency_job_id":"28f8ad48-2e68-477c-9b39-fe5546f0f8ea","html_url":"https://github.com/jordond/drag-select-compose","commit_stats":null,"previous_names":["jordond/drag-select-compose"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordond%2Fdrag-select-compose","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordond%2Fdrag-select-compose/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordond%2Fdrag-select-compose/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordond%2Fdrag-select-compose/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jordond","download_url":"https://codeload.github.com/jordond/drag-select-compose/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248119359,"owners_count":21050754,"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":["android","compose","compose-desktop","compose-ios","compose-multiplatform","drag-selection","drag-selection-library","google-photos","kotlin","kotlin-multiplatform","kotlin-multiplatform-library","kotlin-multiplatform-mobile"],"created_at":"2024-08-02T05:01:09.547Z","updated_at":"2025-10-04T13:03:26.875Z","avatar_url":"https://github.com/jordond.png","language":"Kotlin","funding_links":[],"categories":["Libraries","Uncategorized"],"sub_categories":["🍎 Compose UI","Uncategorized"],"readme":"# Drag Select Compose\n\n![Maven Central](https://img.shields.io/maven-central/v/com.dragselectcompose/dragselect)\n[![Kotlin](https://img.shields.io/badge/kotlin-v2.2.0-blue.svg?logo=kotlin)](http://kotlinlang.org)\n[![Build](https://github.com/jordond/drag-select-compose/actions/workflows/ci.yml/badge.svg)](https://github.com/jordond/drag-select-compose/actions/workflows/ci.yml)\n[![License](https://img.shields.io/github/license/jordond/drag-select-compose)](http://www.apache.org/licenses/LICENSE-2.0)\n\n[![Compose Multiplatform](https://img.shields.io/badge/Compose%20Multiplatform-v1.8.2-blue)](https://github.com/JetBrains/compose-multiplatform)\n![badge-android](http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat)\n![badge-ios](http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat)\n![badge-desktop](http://img.shields.io/badge/platform-desktop-DB413D.svg?style=flat)\n![badge-js-wasm](http://img.shields.io/badge/platform-js%2Fwasm-FDD835.svg?style=flat)\n\nThis is a Compose Multiplatform library that allows you to easily implement a \"Google Photos\"-style\nmulti-selection in your Compose apps.\n\nYou can run the demo at [demo.dragselectcompose.com](https://demo.dragselectcompose.com) and view the KDocs at [docs.dragselectcompose.com](https://docs.dragselectcompose.com)\n\n\u003cimg width=\"250px\" alt=\"demo\" src=\"art/drag-select-compose-demo.gif\" /\u003e\n\n## Table of Contents\n\n- [Platforms](#platforms)\n- [Inspiration](#inspiration)\n- [Setup](#setup)\n    - [Single Platform](#single-platform)\n    - [Multiplatform](#multiplatform)\n    - [Version Catalog](#version-catalog)\n- [Usage](#usage)\n- [Extensions](#extensions)\n- [Grid Wrapper](#wrapper)\n- [Demo](#demo)\n    - [Android](#android-demo)\n    - [Multiplatform](#multiplatform-demo)\n- [License](#license)\n\n## Platforms\n\nThis library is written for Compose Multiplatform, and can be used on the following platforms:\n\n- Android\n- iOS\n- JVM (Desktop)\n- JavaScript/wasm (Browser)\n\n## Inspiration\n\nThis library was inspired by\nthis [article](https://medium.com/androiddevelopers/create-a-photo-grid-with-multiselect-behavior-using-jetpack-compose-9a8d588a9b63)\nand\nthe [gist](https://gist.github.com/JolandaVerhoef/bcaf96360b92bba974e3796fe37247e2).\n\nAs well as the [drag-select-recyclerview](https://github.com/afollestad/drag-select-recyclerview)\nlibrary.\n\n## Setup\n\nYou can add this library to your project using Gradle.\n\n### Single Platform\n\nTo add to a single platform like Android, add the dependency to your app level `build.gradle.kts`\nfile:\n\n```kotlin\ndependencies {\n    // Includes the core functionality along with all of the optional modules\n    implementation(\"com.dragselectcompose:dragselect:3.1.0\")\n\n    // Or use the modules you want\n\n    // Core functionality\n    implementation(\"com.dragselectcompose:core:3.1.0\")\n\n    // Optional extensions for adding semantics and toggle Modifiers to Grid items\n    implementation(\"com.dragselectcompose:extensions:3.1.0\")\n\n    // Optional wrappers around LazyGrid that implement the selection UI for you\n    implementation(\"com.dragselectcompose:grid:3.1.0\")\n}\n```\n\n### Multiplatform\n\nTo add to a multiplatform project, add the dependency to the common source-set:\n\n```kotlin\nkotlin {\n    sourceSets {\n        commonMain {\n            dependencies {\n                // Includes the core functionality along with all of the optional modules\n                implementation(\"com.dragselectcompose:dragselect:3.1.0\")\n\n                // Or use the modules you want\n\n                // Core functionality\n                implementation(\"com.dragselectcompose:core:3.1.0\")\n\n                // Optional extensions for adding semantics and toggle Modifiers to Grid items\n                implementation(\"com.dragselectcompose:extensions:3.1.0\")\n\n                // Optional wrappers around LazyGrid that implement the selection UI for you\n                implementation(\"com.dragselectcompose:grid:3.1.0\")\n            }\n        }\n    }\n}\n```\n\nFor the supported platforms, see the badges at the top of the README.\n\n### Version catalog\n\n```toml\n[versions]\ndragselectcompose = \"3.1.0\"\n\n[libraries]\ndragselect = { module = \"com.dragselectcompose:dragselect\", version.ref = \"dragselectcompose\" }\ndragselect-core = { module = \"com.dragselectcompose:core\", version.ref = \"dragselectcompose\" }\ndragselect-extensions = { module = \"com.dragselectcompose:extensions\", version.ref = \"dragselectcompose\" }\ndragselect-grid = { module = \"com.dragselectcompose:grid\", version.ref = \"dragselectcompose\" }\n```\n\n## Usage\n\nThe `:core` artifact provides a `Modifier` extension for adding a drag-to-select functionality to\nyour `LazyGrid`:\n\n```kotlin\nfun \u003cItem\u003e Modifier.gridDragSelect(\n    items: List\u003cItem\u003e,\n    state: DragSelectState\u003cItem\u003e,\n    enableAutoScroll: Boolean = true,\n    autoScrollThreshold: Float? = null,\n    enableHaptics: Boolean = true,\n    hapticFeedback: HapticFeedback? = null,\n): Modifier\n```\n\nIt provides the following functionality:\n\n- Adds a long-press drag gesture to select items.\n- Maintains a list of selected items.\n- Expose a `inSelectionMode: Boolean` which you can use to display an unselected state.\n- If `enableAutoScroll` is `true` then the list will start to scroll when reaching the top or bottom\n  of the list.\n- Will trigger a \"long-press\" haptics if `enableHaptics` is `true`.\n\n**Note:** By default selected items will be compared using an equality check. If your item is not\na `data class` you must implement `equals` and `hashCode` for your item. Or you can pass a lambda\nto `rememberDragSelectState` to compare your items:\n\n```kotlin\nval dragSelectState = rememberDragSelectState\u003cFoo\u003e(compareSelector = { it.someProperty })\n```\n\nYou can then use `DragSelectState` to render your list of items:\n\n### Basic Example\n\n```kotlin\ndata class Model(\n    val id: Int,\n    val title: String,\n    val imageUrl: String,\n)\n\n@Composeable\nfun MyGrid(models: List\u003cModel\u003e) {\n    val dragSelectState = rememberDragSelectState\u003cModel\u003e()\n    LazyVerticalGrid(\n        columns = GridCells.Adaptive(minSize = 128.dp),\n        state = dragSelectState.lazyGridState,\n        verticalArrangement = Arrangement.spacedBy(3.dp),\n        horizontalArrangement = Arrangement.spacedBy(3.dp),\n        modifier = Modifier.gridDragSelect(\n            items = models,\n            state = dragSelectState,\n        ),\n    ) {\n        items(models, key = { it.id }) { model -\u003e\n            val isSelected by remember { derivedStateOf { dragSelectState.isSelected(model) } }\n            val inSelectionMode = dragSelectState.inSelectionMode\n\n            // Define your Model Composeable and use `isSelected` or `inSelectionMode`\n        }\n    }\n}\n```\n\nYou can see a full basic example\nin [`BasicDragSelectPhotoGrid`](demo/android/src/main/kotlin/com/dragselectcompose/demo/BasicDragSelectPhotoGrid.kt).\n\n## Extensions\n\nIncluded in the `:dragselectcompose` and `:extensions` artifact are a couple extensions on `Modifer`\nto easily add support for accessibility semantics and toggling selection while the Grid is in\nselection mode.\n\n- [`Modifier.dragSelectSemantics()`](extensions/src/commonMain/kotlin/com/dragselectcompose/extensions/Semantics.kt)\n    - Adds a long click semantics to the modifier for accessibility.\n- [`Modifier.dragSelectToggleable()`](extensions/src/commonMain/kotlin/com/dragselectcompose/extensions/Toggleable.kt)\n    - Allows you to toggle the item when the Grid is in Selection Mode.\n- [`Modifier.dragSelectToggleableItem()`](extensions/src/commonMain/kotlin/com/dragselectcompose/extensions/ToggleableItem.kt)\n    - Combines the above two extensions.\n\n```kotlin\n@Composeable\nfun MyGrid(models: List\u003cModel\u003e) {\n    val dragSelectState = rememberDragSelectState\u003cModel\u003e()\n    LazyVerticalGrid(\n        // ...\n    ) {\n        items(models, key = { it.id }) { model -\u003e\n            // Add semantics and toggleable modifiers\n            MyItemContent(\n                item = model,\n                modifier = Modifier.dragSelectToggleable(\n                    state = dragSelectState,\n                    item = model,\n                ),\n            )\n        }\n    }\n}\n```\n\nYou can see a full extensions example\nin [`ExtensionsDragSelectPhotoGrid`](demo/android/src/main/kotlin/com/dragselectcompose/demo/ExtensionsDragSelectPhotoGrid.kt).\n\n## Wrapper\n\nIncluded in the `:grid` artifact is a \"all-inclusive\" drag-select experience. It includes wrappers\naround `LazyHorizontalGrid` and `LazyVerticalGrid` that takes care of adding\nthe `Modifier.gridDragSelect`.\n\nWhen using `LazyDragSelectVerticalGrid` or `LazyDragSelectHorizontalGrid` the `content()` is scoped\nto a custom scope that provides a helper composable for handling the selection indicator, and\nanimating the padding.\n\nHere is a quick example:\n\n```kotlin\n@Composeable\nfun MyGrid(models: List\u003cModel\u003e) {\n    val dragSelectState = rememberDragSelectState\u003cModel\u003e()\n\n    LazyDragSelectVerticalGrid(\n        columns = GridCells.Adaptive(minSize = 128.dp),\n        items = models,\n        state = dragSelectState,\n    ) {\n        items(key = { it.id }) { model -\u003e\n            SelectableItem(item = model) {\n                // Your Composeable for your item\n            }\n        }\n    }\n}\n```\n\nNow your item will have an animated padding and clipped shape when selected. As well as displaying\nindicator icons when the grid is in selection mode, and the item is selected or not.\n\nSee the documentation for `LazyDragSelectVerticalGrid` and `SelectableItem` for all the options you\ncan customize.\n\nYou can see a full example\nin [`LazyDragSelectPhotoGrid`](demo/android/src/main/kotlin/com/dragselectcompose/demo/LazyDragSelectPhotoGrid.kt)\n\n## Demo\n\nTo run a demo for the library you can look inside of `/demo` to see a standard Android application,\nand a Compose Multiplatform application.\n\n### Android Demo\n\nA demo app is included in the `:demo:android` module, run it by following these steps:\n\n```shell\ngit clone git@github.com:jordond/drag-select-compose.git drag-select-compose\ncd drag-select-compose\n./gradlew assembleRelease\n```\n\nThen install the `demo/android/build/outputs/apk/release/demo-release.apk` file on your device.\n\n### Multiplatform Demo\n\nThe demo is inside of `:demo:kmm` module. In order to run it you should have the latest version of\nAndroid Studio installed.\n\nCheck out [the README](demo/README.md) for more information.\n\n## License\n\nSee [LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjordond%2Fdrag-select-compose","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjordond%2Fdrag-select-compose","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjordond%2Fdrag-select-compose/lists"}