@contember/bindx-repeater 0.1.49 → 0.1.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AnyBrand, type EntityAccessor, type HasManyAccessor } from '@contember/bindx';
|
|
2
2
|
/**
|
|
3
|
-
* Hook that returns sorted items from a has-many ref
|
|
3
|
+
* Hook that returns sorted items from a has-many ref.
|
|
4
|
+
*
|
|
5
|
+
* Rendering never writes: an item that joins the list gets its order value from the
|
|
6
|
+
* connect event instead, so sparse values on existing rows are left as they are.
|
|
4
7
|
*
|
|
5
8
|
* @param hasMany - The has-many ref
|
|
6
9
|
* @param orderField - Optional field name for sorting
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSortedItems.d.ts","sourceRoot":"","sources":["../../src/hooks/useSortedItems.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"useSortedItems.d.ts","sourceRoot":"","sources":["../../src/hooks/useSortedItems.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,MAAM,kBAAkB,CAAA;AAIzB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,CAAC,SAAS,MAAM,EAChB,CAAC,GAAG,CAAC,EACL,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAE/D,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAC5D,UAAU,EAAE,MAAM,GAAG,SAAS,GAC5B,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CA4CtD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/bindx-repeater",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"description": "Repeater components for has-many list management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"react": ">=18.0.0"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@contember/bindx": "0.1.
|
|
19
|
-
"@contember/bindx-react": "0.1.
|
|
18
|
+
"@contember/bindx": "0.1.50",
|
|
19
|
+
"@contember/bindx-react": "0.1.50"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { useCallback, useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
FIELD_REF_META,
|
|
4
|
+
type AnyBrand,
|
|
5
|
+
type EntityAccessor,
|
|
6
|
+
type HasManyAccessor,
|
|
7
|
+
type HasManyConnectedEvent,
|
|
8
|
+
} from '@contember/bindx'
|
|
9
|
+
import { useOnFieldEvent, useSnapshotStore } from '@contember/bindx-react'
|
|
3
10
|
import { sortEntities } from '../utils/sortEntities.js'
|
|
4
|
-
import { repairEntitiesOrder } from '../utils/repairEntitiesOrder.js'
|
|
5
11
|
|
|
6
12
|
/**
|
|
7
|
-
* Hook that returns sorted items from a has-many ref
|
|
13
|
+
* Hook that returns sorted items from a has-many ref.
|
|
14
|
+
*
|
|
15
|
+
* Rendering never writes: an item that joins the list gets its order value from the
|
|
16
|
+
* connect event instead, so sparse values on existing rows are left as they are.
|
|
8
17
|
*
|
|
9
18
|
* @param hasMany - The has-many ref
|
|
10
19
|
* @param orderField - Optional field name for sorting
|
|
@@ -20,6 +29,7 @@ export function useSortedItems<
|
|
|
20
29
|
hasMany: HasManyAccessor<T, S, TBrand, TEntityName, TSchema>,
|
|
21
30
|
orderField: string | undefined,
|
|
22
31
|
): EntityAccessor<T, S, TBrand, TEntityName, TSchema>[] {
|
|
32
|
+
const store = useSnapshotStore()
|
|
23
33
|
const rawItems = hasMany?.items
|
|
24
34
|
const items = Array.isArray(rawItems) ? rawItems : []
|
|
25
35
|
|
|
@@ -28,12 +38,38 @@ export function useSortedItems<
|
|
|
28
38
|
[items, orderField],
|
|
29
39
|
)
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
const meta = hasMany?.[FIELD_REF_META]
|
|
42
|
+
const itemType = meta?.targetType
|
|
43
|
+
|
|
44
|
+
const assignOrderToNewItem = useCallback((event: HasManyConnectedEvent): void => {
|
|
45
|
+
if (orderField === undefined || itemType === undefined) return
|
|
46
|
+
|
|
47
|
+
const added = store.getEntitySnapshot<Record<string, unknown>>(itemType, event.itemId)
|
|
48
|
+
// An item already carrying an order keeps it — this only fills the gap.
|
|
49
|
+
if (added === undefined) return
|
|
50
|
+
const currentOrder = added.data[orderField]
|
|
51
|
+
if (currentOrder !== undefined && currentOrder !== null) return
|
|
52
|
+
|
|
53
|
+
// Read through the accessor so the live list is used, not the render snapshot:
|
|
54
|
+
// several items added in one tick must not all land on the same order.
|
|
55
|
+
let maxOrder = -1
|
|
56
|
+
for (const item of hasMany.items) {
|
|
57
|
+
const value = store.getEntitySnapshot<Record<string, unknown>>(itemType, item.id)?.data[orderField]
|
|
58
|
+
if (typeof value === 'number' && value > maxOrder) {
|
|
59
|
+
maxOrder = value
|
|
60
|
+
}
|
|
34
61
|
}
|
|
35
|
-
|
|
36
|
-
|
|
62
|
+
|
|
63
|
+
store.setFieldValue(itemType, event.itemId, [orderField], maxOrder + 1)
|
|
64
|
+
}, [store, hasMany, orderField, itemType])
|
|
65
|
+
|
|
66
|
+
useOnFieldEvent(
|
|
67
|
+
'hasMany:connected',
|
|
68
|
+
meta?.entityType ?? '',
|
|
69
|
+
meta?.entityId ?? '',
|
|
70
|
+
meta?.fieldName ?? '',
|
|
71
|
+
assignOrderToNewItem,
|
|
72
|
+
)
|
|
37
73
|
|
|
38
74
|
return sortedItems
|
|
39
75
|
}
|