To get an updating list of currently visible items with a certain threshold LazyListState can be used.
LazyListState exposes the list of currently visible items List<LazyListItemInfo>. It's easy to calculate visibility percent using
offset and size properties, and thus apply a filter to the visible list for visibility >= threshold.
LazyListItemInfo has index property, which can be used for mapping LazyListItemInfo to the actual data item in the list passed to LazyColumn.
fun LazyListState.visibleItems(itemVisiblePercentThreshold: Float) =
    layoutInfo
        .visibleItemsInfo
        .filter {
            visibilityPercent(it) >= itemVisiblePercentThreshold
        }
fun LazyListState.visibilityPercent(info: LazyListItemInfo): Float {
    val cutTop = max(0, layoutInfo.viewportStartOffset - info.offset)
    val cutBottom = max(0, info.offset + info.size - layoutInfo.viewportEndOffset)
    return max(0f, 100f - (cutTop + cutBottom) * 100f / info.size)
}
Usage
val list = state.visibleItems(50f) // list of LazyListItemInfo
This list has to be mapped first to corresponding items in LazyColumn.
val visibleItems = state.visibleItems(50f)
            .map { listItems[it.index] }
@Composable
fun App() {
    val listItems = remember { generateFakeListItems().toMutableStateList() }
    val state = rememberLazyListState()
    LazyColumn(Modifier.fillMaxSize(), state = state) {
        items(listItems.size) {
            Item(listItems[it])
        }
    }
    val visibleItems by remember(state) {
      derivedStateOf {
        state.visibleItems(50f)
          .map { listItems[it.index] }
      }
    }
    LaunchedEffect(visibleItems) {
      Log.d(TAG, "App: $visibleItems")
    }
}
fun generateFakeListItems() = (0..100).map { "Item $it" }