Skip to content

Commit

Permalink
Examples. Table. Use table metadata instead of React contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
porotkin committed Jan 23, 2025
1 parent 99ef455 commit 9993fc2
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ package wrappers.example.list
import react.FC
import react.dom.html.ReactHTML.div
import wrappers.example.table.UserTable
import wrappers.example.table.selection.TableSelectionModule

val UserList = FC {
div {
CreateUserButton()

TableSelectionModule {
UserTable()
}
UserTable()
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package wrappers.example.table.selection

import react.FC
import react.Key
import react.PropsWithValue

internal val SelectionCell: FC<PropsWithValue<SelectedKeys>> = FC { props ->
internal external interface SelectionCellProps : PropsWithValue<Set<Key>> {
var metadata: TableMetadata
}

internal val SelectionCell: FC<SelectionCellProps> = FC { props ->
val keys = props.value
val metadata = props.metadata

val changeHandler = useSelectionChangeHandler(keys)
val checked = useIsChecked(keys, metadata)
val changeHandler = useSelectionChangeHandler(keys, metadata)

SelectionCheckbox {
value = keys
value = checked
onChange = changeHandler
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package wrappers.example.table.selection

import preact.signals.core.ReadonlySignal
import preact.signals.react.runtime.useSignals
import react.FC
import react.PropsWithValue
Expand All @@ -8,14 +9,14 @@ import react.dom.html.ReactHTML.input
import web.html.HTMLInputElement
import web.html.InputType.Companion.checkbox

internal external interface SelectionCheckboxProps : PropsWithValue<SelectedKeys> {
internal external interface SelectionCheckboxProps : PropsWithValue<ReadonlySignal<Boolean>> {
var onChange: (event: ChangeEvent<HTMLInputElement>) -> Unit
}

internal val SelectionCheckbox: FC<SelectionCheckboxProps> = FC { props ->
useSignals() // for preact signals to re-render the component on change without Babel plugin

val isChecked = useIsChecked(props.value)
val isChecked = props.value

input {
type = checkbox
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package wrappers.example.table.selection

import preact.signals.core.Signal
import tanstack.table.core.RowData
import tanstack.table.core.Table
import tanstack.table.core.TableMeta
import tanstack.table.core.TableOptionsResolved
import wrappers.example.entities.User

internal external interface TableMetadata : TableMeta<User> {
var selection: Signal<SelectedKeys>
}

internal fun <T : RowData> Table<T>.getMeta(): TableMetadata =
options.unsafeCast<TableOptionsResolved<T>>()
.meta.unsafeCast<TableMetadata>()

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal fun <T : Any> createSelectionColumn(): ColumnDef<T, String> =

SelectionCell.create {
value = keys
metadata = context.table.getMeta()
}
}
)
Expand All @@ -29,6 +30,7 @@ internal fun <T : Any> createSelectionColumn(): ColumnDef<T, String> =

SelectionCell.create {
value = keys
metadata = context.table.getMeta()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package wrappers.example.table.selection
import preact.signals.core.ReadonlySignal
import preact.signals.react.useComputed

internal fun useIsChecked(keys: SelectedKeys): ReadonlySignal<Boolean> {
val selection = useSelectedKeys()

return useComputed {
selection.value.containsAll(keys)
}
internal fun useIsChecked(
keys: SelectedKeys,
metadata: TableMetadata,
): ReadonlySignal<Boolean> = useComputed {
metadata.selection.value.containsAll(keys)
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import react.dom.events.ChangeEvent
import react.useCallback
import web.html.HTMLInputElement

internal fun useSelectionChangeHandler(keys: SelectedKeys): (ChangeEvent<HTMLInputElement>) -> Unit {
val selectionHandler = useSelectionHandler()
internal fun useSelectionChangeHandler(
keys: SelectedKeys,
metadata: TableMetadata,
): (ChangeEvent<HTMLInputElement>) -> Unit {
val selectionHandler = useSelectionHandler(metadata)

return useCallback(keys) { event ->
selectionHandler(keys.associateWith { event.target.checked })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package wrappers.example.table.selection

import preact.signals.core.Signal
import react.RequiredContext
import react.createRequiredContext
import react.useRequired
import react.use.useConstant
import wrappers.example.entities.Key

typealias SelectionHandler = (Map<Key, Boolean>) -> Unit

internal val SelectionHandlerContext: RequiredContext<SelectionHandler> =
createRequiredContext()
internal fun useSelectionHandler(
metadata: TableMetadata,
): SelectionHandler =
useConstant { createSelectionHandler(metadata.selection) }

internal fun useSelectionHandler(): SelectionHandler =
useRequired(SelectionHandlerContext)

internal fun SelectionHandler(
private fun createSelectionHandler(
selection: Signal<SelectedKeys>,
): SelectionHandler = { keys ->
val (add, remove) = keys.entries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package wrappers.example.table

import js.array.ReadonlyArray
import js.objects.jso
import preact.signals.react.useSignal
import tanstack.react.table.useReactTable
import tanstack.table.core.ColumnDef
import tanstack.table.core.StringOrTemplateHeader
import tanstack.table.core.Table
import tanstack.table.core.getCoreRowModel
import wrappers.example.entities.User
import wrappers.example.hooks.useUsers
import wrappers.example.table.selection.EMPTY_SELECTION
import wrappers.example.table.selection.TableMetadata
import wrappers.example.table.selection.createSelectionColumn

private val COLUMNS: ReadonlyArray<ColumnDef<User, String>> = arrayOf(
Expand All @@ -26,13 +29,18 @@ private val COLUMNS: ReadonlyArray<ColumnDef<User, String>> = arrayOf(
)

fun useUsersTable(): Table<User> {
val selection = useSignal(EMPTY_SELECTION)

val users = useUsers()

return useReactTable(
options = jso {
data = users
columns = COLUMNS
getCoreRowModel = getCoreRowModel()
meta = jso<TableMetadata> {
this.selection = selection
}
}
)
}

0 comments on commit 9993fc2

Please sign in to comment.