Skip to content

Commit 8db757e

Browse files
committed
feat(store): add useSortedRowIds composable
1 parent 3ba3754 commit 8db757e

File tree

6 files changed

+186
-29
lines changed

6 files changed

+186
-29
lines changed

packages/private/docs/api/store/composables.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,92 @@ store.setCell('pets', 'felix', 'color', 'black')
875875

876876
</div>
877877

878+
## useSortedRowIds {#use-sorted-row-ids}
879+
880+
The `useSortedRowIds` composable returns a **readonly** reference to the sorted (and optionally, paginated) [Ids](https://tinybase.org/api/common/type-aliases/identity/ids/) of every [Row](https://tinybase.org/api/store/type-aliases/store/row/) in a given [Table](https://tinybase.org/api/store/type-aliases/store/table/), and registers a listener so that any changes to that result will cause a re-render.
881+
882+
When first accessed, this composable will create a listener so that changes to the sorted [Row](https://tinybase.org/api/store/type-aliases/store/row/) [Ids](https://tinybase.org/api/common/type-aliases/identity/ids/) will cause a re-render. When the component containing this composable is unmounted, the listener will be automatically removed.
883+
884+
### Parameters
885+
886+
<div class="hide-default-store">
887+
888+
- `store` ([`Store`](https://tinybase.org/api/store/interfaces/store/store/)): The store to listen to.
889+
890+
</div>
891+
892+
- `tableId` ([`MaybeRefOrGetter`](https://vuejs.org/api/utility-types.html#maybereforgetter)`<string>`): The [Id](https://tinybase.org/api/common/type-aliases/identity/id/) of the [Table](https://tinybase.org/api/store/type-aliases/store/table/) in the [Store](https://tinybase.org/api/store/interfaces/store/store/).
893+
894+
- `cellId`<span class="blue">?</span> ([`MaybeRefOrGetter`](https://vuejs.org/api/utility-types.html#maybereforgetter)`<string | undefined>`): The [Id](https://tinybase.org/api/common/type-aliases/identity/id/) of the [Cell](https://tinybase.org/api/store/type-aliases/store/cell/) whose values are used for the sorting, or `undefined` to by sort the [Row](https://tinybase.org/api/store/type-aliases/store/row/) [Id](https://tinybase.org/api/common/type-aliases/identity/id/) itself.
895+
896+
- `descending`<span class="blue">?</span> ([`MaybeRefOrGetter`](https://vuejs.org/api/utility-types.html#maybereforgetter)`<boolean | undefined>`): Whether the sorting should be in descending order.
897+
898+
- `offset`<span class="blue">?</span> ([`MaybeRefOrGetter`](https://vuejs.org/api/utility-types.html#maybereforgetter)`<number | undefined>`): The number of [Row](https://tinybase.org/api/store/type-aliases/store/row/) [Ids](https://tinybase.org/api/common/type-aliases/identity/ids/) to skip for pagination purposes, if any.
899+
900+
- `limit`<span class="blue">?</span> ([`MaybeRefOrGetter`](https://vuejs.org/api/utility-types.html#maybereforgetter)`<number | undefined>`): The maximum number of [Row](https://tinybase.org/api/store/type-aliases/store/row/) [Ids](https://tinybase.org/api/common/type-aliases/identity/ids/) to return, or undefined for all.
901+
902+
### Returns
903+
904+
- `ComputedRef<`[`Ids`](https://tinybase.org/api/common/type-aliases/identity/ids/)`>`: A **readonly** reference to an array of the sorted Ids of every Row in the Table.
905+
906+
### Example
907+
908+
```ts
909+
// store
910+
export const store = createStore().setTables({
911+
pets: {
912+
fido: { species: 'dog' },
913+
felix: { species: 'cat' },
914+
},
915+
})
916+
```
917+
918+
<div class="hide-default-store">
919+
920+
```vue
921+
<script setup lang="ts">
922+
import { useSortedRowIds, injectStore } from 'vue-tinybase/custom-store'
923+
924+
import { Store1Key } from './store'
925+
926+
const store = injectStore(Store1Key)
927+
928+
const rowIds = useSortedRowIds('pets', 'species', false, 0, undefined, store)
929+
// UI will show: ["felix", "fido"]
930+
931+
store.setRow('pets', 'cujo', { species: 'wolf' })
932+
// UI will show: ["felix", "fido", "cujo"]
933+
</script>
934+
935+
<template>
936+
<div>{{ rowIds }}</div>
937+
</template>
938+
```
939+
940+
</div>
941+
942+
<div class="hide-custom-store">
943+
944+
```vue
945+
<script setup lang="ts">
946+
import { useSortedRowIds, injectStore } from 'vue-tinybase'
947+
948+
const store = injectStore()
949+
950+
const rowIds = useSortedRowIds('pets', 'species', false, 0, undefined)
951+
// UI will show: ["felix", "fido"]
952+
953+
store.setRow('pets', 'cujo', { species: 'wolf' })
954+
// UI will show: ["felix", "fido", "cujo"]
955+
</script>
956+
957+
<template>
958+
<div>{{ rowIds }}</div>
959+
</template>
960+
```
961+
962+
</div>
963+
878964
## useTable {#use-table}
879965

880966
The `useTable` composable returns a **readonly** reference to an object containing the data of a single [Table](https://tinybase.org/api/store/type-aliases/store/table/) in a [Store](https://tinybase.org/api/store/interfaces/store/store/), and registers a listener so that any changes to that result will cause a re-render.
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
export { useHasCell } from './useHasCell.js'
2-
export { useHasTableCell } from './useHasTableCell.js'
3-
export { useHasValues } from './useHasValues.js'
4-
export { useRowIds } from './useRowIds.js'
5-
export { useTableIds } from './useTableIds.js'
6-
export { useValueIds } from './useValueIds.js'
71
export { useCell } from './useCell.js'
8-
export { useHasRow } from './useHasRow.js'
9-
export { useHasTables } from './useHasTables.js'
10-
export { useRow } from './useRow.js'
11-
export { useTable } from './useTable.js'
12-
export { useTables } from './useTables.js'
13-
export { useValues } from './useValues.js'
142
export { useCellIds } from './useCellIds.js'
3+
export { useHasCell } from './useHasCell.js'
4+
export { useHasRow } from './useHasRow.js'
155
export { useHasTable } from './useHasTable.js'
6+
export { useHasTables } from './useHasTables.js'
7+
export { useHasTableCell } from './useHasTableCell.js'
168
export { useHasValue } from './useHasValue.js'
9+
export { useHasValues } from './useHasValues.js'
10+
export { useRow } from './useRow.js'
1711
export { useRowCount } from './useRowCount.js'
12+
export { useRowIds } from './useRowIds.js'
13+
export { useSortedRowIds } from './useSortedRowIds.js'
14+
export { useTable } from './useTable.js'
1815
export { useTableCellIds } from './useTableCellIds.js'
16+
export { useTableIds } from './useTableIds.js'
17+
export { useTables } from './useTables.js'
1918
export { useValue } from './useValue.js'
19+
export { useValueIds } from './useValueIds.js'
20+
export { useValues } from './useValues.js'
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { toRef } from '@vue/reactivity'
2+
3+
import { useReactiveComposable } from '../../../utils/useReactiveComposable.js'
4+
import { onSortedRowIdsChange } from '../events/onSortedRowIdsChange.js'
5+
6+
import type { AnyStore, ExtractTablesSchemaFromStore } from '../../../types.js'
7+
import type { MaybeRefOrGetter } from '@vue/reactivity'
8+
import type { Ids } from 'tinybase/with-schemas/common'
9+
import type { CellIdFromSchema, TableIdFromSchema } from 'tinybase/with-schemas/internal/store'
10+
11+
export function useSortedRowIds<
12+
Store extends AnyStore,
13+
TableId extends TableIdFromSchema<ExtractTablesSchemaFromStore<Store>>,
14+
>(
15+
store: Store,
16+
tableId: MaybeRefOrGetter<TableId>,
17+
cellId?: MaybeRefOrGetter<CellIdFromSchema<ExtractTablesSchemaFromStore<Store>, TableId> | undefined>,
18+
descending?: MaybeRefOrGetter<boolean | undefined>,
19+
offset?: MaybeRefOrGetter<number | undefined>,
20+
limit?: MaybeRefOrGetter<number | undefined>,
21+
) {
22+
const tableIdRef = toRef(tableId)
23+
const cellIdRef = toRef(cellId)
24+
const descendingRef = toRef(descending)
25+
const offsetRef = toRef(offset)
26+
const limitRef = toRef(limit)
27+
28+
return useReactiveComposable<Ids>({
29+
getData: () => store.getSortedRowIds(tableIdRef.value),
30+
listener: ({ loadData }) =>
31+
onSortedRowIdsChange(
32+
store,
33+
tableIdRef as any,
34+
cellIdRef,
35+
descendingRef,
36+
offsetRef,
37+
limitRef,
38+
(_store, _tableId, _cellId, _descending, _offset, _limit, sortedRowIds) => loadData(sortedRowIds),
39+
false,
40+
{
41+
immediate: false,
42+
},
43+
),
44+
})
45+
}

packages/public/vue-tinybase/src/custom-store/store/events/onSortedRowIdsChange.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export function onSortedRowIdsChange<
1212
Store extends AnyStore,
1313
TableId extends TableIdFromSchema<ExtractTablesSchemaFromStore<Store>>,
1414
CellIdOrUndefined extends CellIdFromSchema<ExtractTablesSchemaFromStore<Store>, TableId> | undefined,
15-
Descending extends boolean,
16-
Offset extends number,
15+
Descending extends boolean | undefined,
16+
Offset extends number | undefined,
1717
Limit extends number | undefined,
1818
>(
1919
store: Store,
@@ -22,7 +22,14 @@ export function onSortedRowIdsChange<
2222
descending: MaybeRefOrGetter<Descending>,
2323
offset: MaybeRefOrGetter<Offset>,
2424
limit: MaybeRefOrGetter<Limit>,
25-
listener: SortedRowIdsListener<ExtractSchemasFromStore<Store>, TableId, CellIdOrUndefined, Descending, Offset, Limit>,
25+
listener: SortedRowIdsListener<
26+
ExtractSchemasFromStore<Store>,
27+
TableId,
28+
CellIdOrUndefined,
29+
Descending extends undefined ? false : Descending,
30+
Offset extends undefined ? 0 : Offset,
31+
Limit
32+
>,
2633
mutator?: MaybeRefOrGetter<boolean>,
2734
options?: UseListenerOptions,
2835
) {
@@ -32,8 +39,8 @@ export function onSortedRowIdsChange<
3239
store.addSortedRowIdsListener(
3340
toValue(tableId),
3441
toValue(cellId),
35-
toValue(descending),
36-
toValue(offset),
42+
toValue(descending) ?? false,
43+
toValue(offset) ?? 0,
3744
toValue(limit),
3845
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
3946
listener as any,
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
export { useHasCell } from './useHasCell.js'
2-
export { useHasTableCell } from './useHasTableCell.js'
3-
export { useHasValues } from './useHasValues.js'
4-
export { useRowIds } from './useRowIds.js'
5-
export { useTableIds } from './useTableIds.js'
6-
export { useValueIds } from './useValueIds.js'
71
export { useCell } from './useCell.js'
8-
export { useHasRow } from './useHasRow.js'
9-
export { useHasTables } from './useHasTables.js'
10-
export { useRow } from './useRow.js'
11-
export { useTable } from './useTable.js'
12-
export { useTables } from './useTables.js'
13-
export { useValues } from './useValues.js'
142
export { useCellIds } from './useCellIds.js'
3+
export { useHasCell } from './useHasCell.js'
4+
export { useHasRow } from './useHasRow.js'
155
export { useHasTable } from './useHasTable.js'
6+
export { useHasTables } from './useHasTables.js'
7+
export { useHasTableCell } from './useHasTableCell.js'
168
export { useHasValue } from './useHasValue.js'
9+
export { useHasValues } from './useHasValues.js'
10+
export { useRow } from './useRow.js'
1711
export { useRowCount } from './useRowCount.js'
12+
export { useRowIds } from './useRowIds.js'
13+
export { useSortedRowIds } from './useSortedRowIds.js'
14+
export { useTable } from './useTable.js'
1815
export { useTableCellIds } from './useTableCellIds.js'
16+
export { useTableIds } from './useTableIds.js'
17+
export { useTables } from './useTables.js'
1918
export { useValue } from './useValue.js'
19+
export { useValueIds } from './useValueIds.js'
20+
export { useValues } from './useValues.js'
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { injectStore } from '../../context/injectStore.js'
2+
import { useSortedRowIds as useSortedRowIdsCS } from '../../custom-store/store/composables/useSortedRowIds.js'
3+
4+
import type { DefaultStore, DefaultStoreTablesSchema } from '../../types.js'
5+
import type { ComputedRef, MaybeRefOrGetter } from '@vue/reactivity'
6+
import type { Ids } from 'tinybase/with-schemas/common'
7+
import type { CellIdFromSchema, TableIdFromSchema } from 'tinybase/with-schemas/internal/store'
8+
9+
export function useSortedRowIds<TableId extends TableIdFromSchema<DefaultStoreTablesSchema>>(
10+
tableId: MaybeRefOrGetter<TableId>,
11+
cellId?: MaybeRefOrGetter<CellIdFromSchema<DefaultStoreTablesSchema, TableId> | undefined>,
12+
descending?: MaybeRefOrGetter<boolean | undefined>,
13+
offset?: MaybeRefOrGetter<number | undefined>,
14+
limit?: MaybeRefOrGetter<number | undefined>,
15+
): ComputedRef<Ids> {
16+
return useSortedRowIdsCS<DefaultStore, TableId>(injectStore(), tableId, cellId, descending, offset, limit)
17+
}

0 commit comments

Comments
 (0)