@arrai-innovations/reactive-helpers 21.1.2 → 22.1.0
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.
- package/LICENSE +28 -0
- package/README.md +109 -21
- package/config/commonCrud.js +7 -10
- package/config/listCrud.js +33 -33
- package/config/objectCrud.js +64 -59
- package/package.json +103 -89
- package/types/config/listCrud.d.ts +83 -28
- package/types/config/objectCrud.d.ts +139 -49
- package/types/tests/benchmarks/fixtures.d.ts +60 -0
- package/types/tests/benchmarks/listLayers.bench.d.ts +1 -0
- package/types/tests/benchmarks/listPush.bench.d.ts +1 -0
- package/types/tests/benchmarks/listStream.bench.d.ts +1 -0
- package/types/tests/unit/use/lifecycleCleanup.spec.d.ts +1 -0
- package/types/tests/unit/use/listPerformance.spec.d.ts +1 -0
- package/types/tests/unit/utils/cancellablePromise.spec.d.ts +1 -0
- package/types/use/cancellableIntent.d.ts +36 -33
- package/types/use/combineClasses.d.ts +5 -2
- package/types/use/error.d.ts +39 -19
- package/types/use/list.d.ts +27 -26
- package/types/use/listCalculated.d.ts +38 -55
- package/types/use/listFilter.d.ts +25 -33
- package/types/use/listInstance.d.ts +94 -81
- package/types/use/listRelated.d.ts +37 -57
- package/types/use/listSearch.d.ts +54 -52
- package/types/use/listSort.d.ts +31 -40
- package/types/use/listSubscription.d.ts +33 -36
- package/types/use/loading.d.ts +20 -10
- package/types/use/loadingError.d.ts +12 -3
- package/types/use/object.d.ts +8 -5
- package/types/use/objectCalculated.d.ts +46 -39
- package/types/use/objectInstance.d.ts +70 -74
- package/types/use/objectRelated.d.ts +51 -41
- package/types/use/objectSubscription.d.ts +38 -48
- package/types/use/proxyError.d.ts +15 -6
- package/types/use/proxyLoading.d.ts +11 -5
- package/types/use/proxyLoadingError.d.ts +19 -7
- package/types/use/search.d.ts +33 -29
- package/types/utils/assignReactiveObject.d.ts +3 -0
- package/types/utils/cancellableFetch.d.ts +2 -3
- package/types/utils/cancellablePromise.d.ts +42 -8
- package/types/utils/classes.d.ts +7 -1
- package/types/utils/deepUnref.d.ts +1 -1
- package/types/utils/getFakePk.d.ts +2 -2
- package/types/utils/isReactiveTyped.d.ts +2 -0
- package/types/utils/keyDiff.d.ts +4 -6
- package/types/utils/relatedCalculatedHelpers.d.ts +2 -0
- package/types/utils/watches.d.ts +1 -1
- package/use/cancellableIntent.js +36 -9
- package/use/combineClasses.js +2 -2
- package/use/error.js +10 -14
- package/use/list.js +6 -18
- package/use/listCalculated.js +28 -38
- package/use/listFilter.js +12 -24
- package/use/listInstance.js +101 -60
- package/use/listRelated.js +18 -37
- package/use/listSearch.js +9 -18
- package/use/listSort.js +95 -64
- package/use/listSubscription.js +19 -25
- package/use/loading.js +5 -7
- package/use/loadingError.js +3 -3
- package/use/object.js +14 -27
- package/use/objectCalculated.js +21 -25
- package/use/objectInstance.js +55 -50
- package/use/objectRelated.js +19 -25
- package/use/objectSubscription.js +18 -30
- package/use/proxyError.js +10 -10
- package/use/proxyLoading.js +5 -5
- package/use/proxyLoadingError.js +13 -8
- package/use/search.js +5 -11
- package/utils/assignReactiveObject.js +3 -3
- package/utils/cancellableFetch.js +3 -3
- package/utils/cancellablePromise.js +25 -8
- package/utils/classes.js +2 -2
- package/utils/deepUnref.js +1 -5
- package/utils/getFakePk.js +2 -2
- package/utils/isReactiveTyped.js +2 -0
- package/utils/keyDiff.js +1 -3
- package/utils/relatedCalculatedHelpers.js +2 -0
package/use/listRelated.js
CHANGED
|
@@ -18,44 +18,37 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
|
|
|
18
18
|
|
|
19
19
|
// todo: pkKey is misnamed, it should be fkKey... this will be a major breaking change
|
|
20
20
|
/**
|
|
21
|
-
* The rule for defining relationships for objects in a list.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @property {string} pkKey - Specifies the foreign key used to link objects across lists. Planned to be renamed to
|
|
25
|
-
* 'fkKey' to better reflect its usage.
|
|
21
|
+
* @typedef {object} ListRelatedRule - The rule for defining relationships for objects in a list.
|
|
22
|
+
* @property {string} [pkKey] - Specifies the foreign key used to link objects across lists. Defaults to the rule's
|
|
23
|
+
* own key when omitted. Planned to be renamed to 'fkKey' to better reflect its usage.
|
|
26
24
|
* @property {string[]} [order] - Specifies the order in which related objects should be sorted, if applicable.
|
|
27
25
|
* @property {import('./listInstance.js').ObjectsByPk} objects - The objects that can be related based on the foreign key.
|
|
28
26
|
*/
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
|
-
* The rules for defining relationships among objects in a list.
|
|
32
|
-
*
|
|
33
29
|
* @typedef {{
|
|
34
30
|
* [rule: string]: ListRelatedRule,
|
|
35
|
-
* }} ListRelatedRules
|
|
31
|
+
* }} ListRelatedRules - The rules for defining relationships among objects in a list.
|
|
36
32
|
*/
|
|
37
33
|
|
|
38
34
|
/**
|
|
39
|
-
* Represents the internal state used by the list related composition function. It manages and computes the relationships
|
|
40
|
-
* between objects based on specified rules, providing real-time updates to related objects as the parent state changes.
|
|
41
|
-
*
|
|
42
|
-
* @typedef {object} ListRelatedRawState
|
|
35
|
+
* @typedef {object} ListRelatedRawState - Represents the internal state used by the list related composition function. It manages and computes the relationships between objects based on specified rules, providing real-time updates to related objects as the parent state changes.
|
|
43
36
|
* @property {{
|
|
44
37
|
* [pk: import('../config/commonCrud.js').Pk]: {
|
|
45
|
-
* [rule: string]:
|
|
38
|
+
* [rule: string]: any,
|
|
46
39
|
* },
|
|
47
|
-
* }} relatedObjects -
|
|
40
|
+
* }} relatedObjects - The related objects, by object pk and then rule name. Each entry is backed by a computed, but it is read through a reactive proxy that unwraps it, so reads yield the related object (or array of related objects) and never carry a `.value`.
|
|
48
41
|
* @property {ListRelatedRules} relatedObjectsRules - Defines the rules for establishing relationships, such as foreign key links and sorting orders.
|
|
49
42
|
* @property {{
|
|
50
43
|
* [pk: import('../config/commonCrud.js').Pk]: {
|
|
51
44
|
* [rule: string]: import('vue').ComputedRef<[object, string]>,
|
|
52
45
|
* },
|
|
53
|
-
* }} objAndKeyForPkAndRule - Maps each object pk and rule to a tuple consisting of the related object and its respective key, facilitating direct data manipulation.
|
|
46
|
+
* }} objAndKeyForPkAndRule - Maps each object pk and rule to a tuple consisting of the related object and its respective key, facilitating direct data manipulation. Reads through the reactive state unwrap the computed to the tuple itself, so `.value` is not used.
|
|
54
47
|
* @property {{
|
|
55
48
|
* [pk: import('../config/commonCrud.js').Pk]: {
|
|
56
|
-
* [rule: string]:
|
|
49
|
+
* [rule: string]: any,
|
|
57
50
|
* },
|
|
58
|
-
* }} fkForPkAndRule -
|
|
51
|
+
* }} fkForPkAndRule - The foreign key for each object pk and rule, crucial for navigating complex data relationships. Each entry is backed by a computed that the reactive proxy unwraps on read.
|
|
59
52
|
* @property {boolean} relatedObjectsParentStateObjectsWatchRunning - Flags whether the watch on parent state objects is currently active, ensuring updates trigger as needed.
|
|
60
53
|
* @property {boolean} relatedObjectsWatchRunning - Indicates if watches on the related objects themselves are active, managing updates efficiently.
|
|
61
54
|
* @property {boolean} relatedRunning - Signals whether any computations related to object relationships are currently in progress.
|
|
@@ -63,41 +56,31 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
|
|
|
63
56
|
*/
|
|
64
57
|
|
|
65
58
|
/**
|
|
66
|
-
* The raw state properties for a parent of a list related property.
|
|
67
|
-
*
|
|
68
59
|
* @typedef {(
|
|
69
60
|
* import('./listInstance.js').ListInstanceRawState &
|
|
70
61
|
* Partial<import('./listSubscription.js').ListSubscriptionRawState>
|
|
71
|
-
* )} ListRelatedParentRawState
|
|
62
|
+
* )} ListRelatedParentRawState - The raw state properties for a parent of a list related property.
|
|
72
63
|
*/
|
|
73
64
|
|
|
74
65
|
/**
|
|
75
|
-
* The type for a parentState object.
|
|
76
|
-
*
|
|
77
|
-
* @typedef {import('vue').UnwrapNestedRefs<ListRelatedParentRawState>} ListRelatedParentState
|
|
66
|
+
* @typedef {import('vue').UnwrapNestedRefs<ListRelatedParentRawState>} ListRelatedParentState - The type for a parentState object.
|
|
78
67
|
*/
|
|
79
68
|
|
|
80
69
|
/**
|
|
81
|
-
* The state for a list related property.
|
|
82
|
-
*
|
|
83
70
|
* @typedef {import('vue').UnwrapNestedRefs<
|
|
84
71
|
* ListRelatedParentRawState &
|
|
85
72
|
* ListRelatedRawState
|
|
86
|
-
* >} ListRelatedState
|
|
73
|
+
* >} ListRelatedState - The state for a list related property.
|
|
87
74
|
*/
|
|
88
75
|
|
|
89
76
|
/**
|
|
90
|
-
* The options for the list related composition function.
|
|
91
|
-
*
|
|
92
|
-
* @typedef {object} ListRelatedOptions
|
|
77
|
+
* @typedef {object} ListRelatedOptions - The options for the list related composition function.
|
|
93
78
|
* @property {ListRelatedParentState} parentState - The parent state object.
|
|
94
79
|
* @property {import('vue').Ref<ListRelatedRules>} relatedObjectsRules - The rules for the related objects.
|
|
95
80
|
*/
|
|
96
81
|
|
|
97
82
|
/**
|
|
98
|
-
* The properties for the list related composition function.
|
|
99
|
-
*
|
|
100
|
-
* @typedef {object} ListRelatedProperties
|
|
83
|
+
* @typedef {object} ListRelatedProperties - The properties for the list related composition function.
|
|
101
84
|
* @property {ListRelatedState} state - The state for the list related property.
|
|
102
85
|
* @property {ListRelatedParentState} parentState - The parent state object.
|
|
103
86
|
* @property {() => void} stop - Stops all effects of the list related property.
|
|
@@ -106,9 +89,7 @@ import { computed, effectScope, nextTick, onScopeDispose, reactive, ref, toRef,
|
|
|
106
89
|
// if we provided functions, we would add a typedef and mix them into ListRelated
|
|
107
90
|
|
|
108
91
|
/**
|
|
109
|
-
* An instance of `useListRelated`.
|
|
110
|
-
*
|
|
111
|
-
* @typedef {ListRelatedProperties} ListRelated
|
|
92
|
+
* @typedef {ListRelatedProperties} ListRelated - An instance of `useListRelated`.
|
|
112
93
|
*/
|
|
113
94
|
|
|
114
95
|
/**
|
|
@@ -348,7 +329,7 @@ export function useListRelated({ parentState, relatedObjectsRules }) {
|
|
|
348
329
|
|
|
349
330
|
es.run(() => {
|
|
350
331
|
watch(
|
|
351
|
-
() =>
|
|
332
|
+
() => parentState.objectsVersion,
|
|
352
333
|
() => {
|
|
353
334
|
state.relatedObjectsParentStateObjectsWatchRunning = true;
|
|
354
335
|
},
|
|
@@ -356,7 +337,7 @@ export function useListRelated({ parentState, relatedObjectsRules }) {
|
|
|
356
337
|
);
|
|
357
338
|
watch(() => Object.keys(parentState.objects), parentStateObjectsWatch, { immediate: true });
|
|
358
339
|
watch(
|
|
359
|
-
[() =>
|
|
340
|
+
[() => parentState.objectsVersion, () => Object.keys(state.relatedObjectsRules || {})],
|
|
360
341
|
() => {
|
|
361
342
|
state.relatedObjectsWatchRunning = true;
|
|
362
343
|
},
|
package/use/listSearch.js
CHANGED
|
@@ -21,9 +21,7 @@ import { refIfReactive } from "../utils/refIfReactive.js";
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Represents the raw reactive state used by the list search functionality.
|
|
25
|
-
*
|
|
26
|
-
* @typedef {object} ListSearchRawState
|
|
24
|
+
* @typedef {object} ListSearchRawState - Represents the raw reactive state used by the list search functionality.
|
|
27
25
|
* @property {import('./listInstance.js').ObjectsByPk} objects - Currently filtered objects based on the search.
|
|
28
26
|
* @property {import('./listInstance.js').ObjectsInOrder} objectsInOrder - The list of objects sorted according to the current search criteria.
|
|
29
27
|
* @property {import('./listInstance.js').ListOrder} order - The current sort order of object pks after search have been applied.
|
|
@@ -46,7 +44,7 @@ import { refIfReactive } from "../utils/refIfReactive.js";
|
|
|
46
44
|
* Partial<import('./listRelated.js').ListRelatedRawState> &
|
|
47
45
|
* Partial<import('./listCalculated.js').ListCalculatedRawState> &
|
|
48
46
|
* Partial<import('./listFilter.js').ListFilterRawState>
|
|
49
|
-
* )} ListSearchParentRawState
|
|
47
|
+
* )} ListSearchParentRawState - The raw, pre-unwrapped parent state consumed by the list search mixin, aggregating the upstream list composable states.
|
|
50
48
|
*/
|
|
51
49
|
|
|
52
50
|
/**
|
|
@@ -54,7 +52,7 @@ import { refIfReactive } from "../utils/refIfReactive.js";
|
|
|
54
52
|
*/
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
|
-
* @typedef {import('vue').ToRefs<ListSearchParentState>} ListSearchParentStateToRefs
|
|
55
|
+
* @typedef {import('vue').ToRefs<ListSearchParentState>} ListSearchParentStateToRefs - The parent list-search state converted to individual Vue refs.
|
|
58
56
|
*/
|
|
59
57
|
|
|
60
58
|
/**
|
|
@@ -86,9 +84,7 @@ import { refIfReactive } from "../utils/refIfReactive.js";
|
|
|
86
84
|
*/
|
|
87
85
|
|
|
88
86
|
/**
|
|
89
|
-
* The properties on a list search instance.
|
|
90
|
-
*
|
|
91
|
-
* @typedef {object} ListSearchProperties
|
|
87
|
+
* @typedef {object} ListSearchProperties - The properties on a list search instance.
|
|
92
88
|
* @property {ListSearchState} state - The state.
|
|
93
89
|
* @property {import('./search.js').SearchInstance} textSearchIndex - The text search index.
|
|
94
90
|
* @property {() => void} stop - Stops the effect scope and cleans up resources.
|
|
@@ -97,9 +93,7 @@ import { refIfReactive } from "../utils/refIfReactive.js";
|
|
|
97
93
|
// if we provided functions, we would add a typedef and mix them into ListSearch
|
|
98
94
|
|
|
99
95
|
/**
|
|
100
|
-
* The provided list search instance, containing properties and functions.
|
|
101
|
-
*
|
|
102
|
-
* @typedef {ListSearchProperties} ListSearch
|
|
96
|
+
* @typedef {ListSearchProperties} ListSearch - The provided list search instance, containing properties and functions.
|
|
103
97
|
*/
|
|
104
98
|
|
|
105
99
|
/**
|
|
@@ -123,14 +117,11 @@ export function useListSearches(listSearchArgs) {
|
|
|
123
117
|
}
|
|
124
118
|
|
|
125
119
|
/**
|
|
126
|
-
* FlexSearch.Document options, specifically for .index. Their documentation isn't very clear on this.
|
|
127
|
-
* Typically, it would be a list of dot-separated keys to index.
|
|
128
|
-
*
|
|
129
|
-
* @typedef {string | string[] | object[]} TextSearchRules
|
|
120
|
+
* @typedef {string | string[] | object[]} TextSearchRules - FlexSearch.Document options, specifically for .index. Their documentation isn't very clear on this. Typically, it would be a list of dot-separated keys to index.
|
|
130
121
|
*/
|
|
131
122
|
|
|
132
123
|
/**
|
|
133
|
-
* @typedef {object} ListSearchProps
|
|
124
|
+
* @typedef {object} ListSearchProps - The consumer-supplied props configuring a list's text search (rules, value, and FlexSearch options).
|
|
134
125
|
* @property {TextSearchRules} textSearchRules - Rules for what to search for. Keys are the keys to search for, values are functions that take the object and return The value to search for.
|
|
135
126
|
* @property {string} textSearchValue - The value to search for.
|
|
136
127
|
* @property {object} customDocumentOptions - FlexSearch.Document options.
|
|
@@ -139,7 +130,7 @@ export function useListSearches(listSearchArgs) {
|
|
|
139
130
|
*/
|
|
140
131
|
|
|
141
132
|
/**
|
|
142
|
-
* @typedef {object} ListSearchInstanceOptions
|
|
133
|
+
* @typedef {object} ListSearchInstanceOptions - The configuration options used to create a list search instance.
|
|
143
134
|
* @property {object} parentState - The list being filtered.
|
|
144
135
|
* @property {ListSearchProps} [props] - Reactive properties.
|
|
145
136
|
* @property {number} [throttle=500] - Throttle wait time.
|
|
@@ -271,7 +262,7 @@ export function useListSearch({ parentState, props, throttle = 500, showAllWhenE
|
|
|
271
262
|
addedKeys: addedObjectPks,
|
|
272
263
|
removedKeys: removedObjectPks,
|
|
273
264
|
sameKeys: sameObjectPks,
|
|
274
|
-
} = keyDiff(Object.keys(parentState.objects), Object.keys(
|
|
265
|
+
} = keyDiff(Object.keys(parentState.objects), Object.keys(objectEffectScopes));
|
|
275
266
|
const { addedKeys: addedTextSearchRules, removedKeys: removedTextSearchRules } = keyDiff(
|
|
276
267
|
state.textSearchRules,
|
|
277
268
|
previousTextSearchRules
|
package/use/listSort.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { keyDiff } from "../utils/keyDiff.js";
|
|
2
|
+
import { loadingCombine } from "../utils/loadingCombine.js";
|
|
3
|
+
import { proxyRunning } from "../utils/proxyRunning.js";
|
|
2
4
|
import get from "lodash-es/get.js";
|
|
3
5
|
import identity from "lodash-es/identity.js";
|
|
4
6
|
import throttle from "lodash-es/throttle.js";
|
|
5
|
-
import { computed, effectScope, reactive, ref, toRef, toRefs, unref, watch } from "vue";
|
|
7
|
+
import { computed, effectScope, onScopeDispose, reactive, ref, toRef, toRefs, unref, watch } from "vue";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Provides a Vue 3 composable for sorting lists based on dynamic and customizable rules. This module integrates
|
|
@@ -23,7 +25,7 @@ const defaultOptions = {
|
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Sets default configuration options for all list sorting operations within the application. This function allows
|
|
26
|
-
* global settings to be specified that affect the
|
|
28
|
+
* global settings to be specified that affect the behaviour of sorting operations unless overridden by specific
|
|
27
29
|
* instance configurations.
|
|
28
30
|
*
|
|
29
31
|
* @param {object} options - Configuration options to set as defaults for list sorting.
|
|
@@ -35,25 +37,19 @@ export function setListSortDefaultOptions({ sortThrottleWait }) {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
|
-
* Describes a rule for ordering elements in a list. Each rule can directly reference a property of the list items,
|
|
39
|
-
* or define a function to compute the value used for sorting. Rules can be configured to sort in ascending or descending
|
|
40
|
-
* order and can utilize locale-aware string comparison if necessary.
|
|
41
|
-
*
|
|
42
40
|
* @typedef {{
|
|
43
41
|
* key: string,
|
|
44
42
|
* keyFn?: (object: any, state: ListSortState) => any,
|
|
45
43
|
* desc?: boolean,
|
|
46
44
|
* localeCompare?: boolean
|
|
47
|
-
* }} OrderByRule
|
|
45
|
+
* }} OrderByRule - Describes a rule for ordering elements in a list. Each rule can directly reference a property of the list items, or define a function to compute the value used for sorting. Rules can be configured to sort in ascending or descending order and can utilize locale-aware string comparison if necessary.
|
|
48
46
|
*/
|
|
49
47
|
|
|
50
48
|
/**
|
|
51
|
-
* Represents the raw state used by the list sorting functionality. Includes all configurations and state necessary
|
|
52
|
-
* to manage sorting operations within a Vue application.
|
|
53
|
-
*
|
|
54
|
-
* @typedef {object} ListSortRawState
|
|
49
|
+
* @typedef {object} ListSortRawState - Represents the raw state used by the list sorting functionality. Includes all configurations and state necessary to manage sorting operations within a Vue application.
|
|
55
50
|
* @property {OrderByRule[]} orderByRules - Current sorting rules applied to the list.
|
|
56
51
|
* @property {boolean[]} orderByDesc - Flags indicating whether each sort criterion is in descending order.
|
|
52
|
+
* @property {import('vue').ComputedRef<boolean|undefined>} running - Whether the sort is settling a pending reorder, combined with the upstream running state so it propagates through the composed list state. True from when a new order is computed until the throttled reorder lands.
|
|
57
53
|
*/
|
|
58
54
|
|
|
59
55
|
/**
|
|
@@ -66,36 +62,29 @@ export function setListSortDefaultOptions({ sortThrottleWait }) {
|
|
|
66
62
|
* Partial<import('./listCalculated.js').ListCalculatedRawState> &
|
|
67
63
|
* Partial<import('./listFilter.js').ListFilterRawState> &
|
|
68
64
|
* Partial<import('./listSearch.js').ListSearchRawState>
|
|
69
|
-
* )} ListSortParentRawState
|
|
65
|
+
* )} ListSortParentRawState - The raw, pre-unwrapped parent state consumed by the list sort mixin, aggregating the upstream list composable states.
|
|
70
66
|
*/
|
|
71
67
|
|
|
72
68
|
/**
|
|
73
|
-
* @typedef {import('vue').UnwrapNestedRefs<ListSortParentRawState>} ListSortParentState
|
|
69
|
+
* @typedef {import('vue').UnwrapNestedRefs<ListSortParentRawState>} ListSortParentState - The unwrapped reactive parent state consumed by the list sort mixin.
|
|
74
70
|
*/
|
|
75
71
|
|
|
76
72
|
/**
|
|
77
|
-
* The reactive state used by the list sorting functionality. Includes all configurations and state necessary to manage
|
|
78
|
-
* sorting operations within a Vue application.
|
|
79
|
-
*
|
|
80
73
|
* @typedef {import('vue').UnwrapNestedRefs<
|
|
81
74
|
* ListSortParentRawState &
|
|
82
75
|
* ListSortRawState
|
|
83
|
-
* >} ListSortState
|
|
76
|
+
* >} ListSortState - The reactive state used by the list sorting functionality. Includes all configurations and state necessary to manage sorting operations within a Vue application.
|
|
84
77
|
*/
|
|
85
78
|
|
|
86
79
|
/**
|
|
87
|
-
* The configuration options for initializing a list sort instance.
|
|
88
|
-
*
|
|
89
|
-
* @typedef {object} ListSortOptions
|
|
80
|
+
* @typedef {object} ListSortOptions - The configuration options for initializing a list sort instance.
|
|
90
81
|
* @property {ListSortParentState} parentState - The parent state containing the list data and any associated state needed for sorting.
|
|
91
82
|
* @property {OrderByRule[]|import('vue').Ref<OrderByRule[]>} orderByRules - Rules defining how the list should be sorted, including key and direction.
|
|
92
83
|
* @property {number | symbol} sortThrottleWait - Optional throttle wait time to limit the frequency of sort operations, enhancing performance.
|
|
93
84
|
*/
|
|
94
85
|
|
|
95
86
|
/**
|
|
96
|
-
* The properties available on a list sort instance.
|
|
97
|
-
*
|
|
98
|
-
* @typedef {object} ListSortProperties
|
|
87
|
+
* @typedef {object} ListSortProperties - The properties available on a list sort instance.
|
|
99
88
|
* @property {ListSortState} state - The reactive state for the list sort.
|
|
100
89
|
* @property {ListSortParentState} parentState - The parent state.
|
|
101
90
|
* @property {() => void} stop - A function to stop the effect scope and clean up resources.
|
|
@@ -104,9 +93,7 @@ export function setListSortDefaultOptions({ sortThrottleWait }) {
|
|
|
104
93
|
// if we provided functions, we would add a typedef and mix them into ListSort
|
|
105
94
|
|
|
106
95
|
/**
|
|
107
|
-
* The list sort instance, including reactive state and utilities to manage list sorting operations.
|
|
108
|
-
*
|
|
109
|
-
* @typedef {ListSortProperties} ListSort
|
|
96
|
+
* @typedef {ListSortProperties} ListSort - The list sort instance, including reactive state and utilities to manage list sorting operations.
|
|
110
97
|
*/
|
|
111
98
|
|
|
112
99
|
/**
|
|
@@ -177,6 +164,13 @@ export function useListSort({ parentState, orderByRules, sortThrottleWait = defa
|
|
|
177
164
|
})();
|
|
178
165
|
const es = effectScope();
|
|
179
166
|
|
|
167
|
+
/** @type {import('vue').Ref<boolean|undefined>} */
|
|
168
|
+
const parentRunning = ref(undefined);
|
|
169
|
+
proxyRunning(parentState, "running", parentRunning);
|
|
170
|
+
// True from the moment a new order is pending until the (possibly throttled) reorder lands.
|
|
171
|
+
const sortWatchRunning = ref(true);
|
|
172
|
+
const running = computed(() => loadingCombine(sortWatchRunning.value, parentRunning.value));
|
|
173
|
+
|
|
180
174
|
const internalState = reactive({
|
|
181
175
|
orderByRules,
|
|
182
176
|
orderByDesc: computed(() =>
|
|
@@ -197,52 +191,59 @@ export function useListSort({ parentState, orderByRules, sortThrottleWait = defa
|
|
|
197
191
|
if (!obj) {
|
|
198
192
|
return [];
|
|
199
193
|
}
|
|
200
|
-
return
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
194
|
+
return (
|
|
195
|
+
internalState.orderByRules
|
|
196
|
+
?.filter((r) => r && r.key)
|
|
197
|
+
.map((r) => {
|
|
198
|
+
if (!r) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
if (r.keyFn) {
|
|
202
|
+
return r.keyFn(obj, parentState);
|
|
203
|
+
}
|
|
204
|
+
if (r.key.startsWith("relatedItem.")) {
|
|
205
|
+
return get(parentState.relatedObjects?.[pk], r.key.slice(12));
|
|
206
|
+
}
|
|
207
|
+
if (r.key.startsWith("calculatedItem.")) {
|
|
208
|
+
return get(parentState.calculatedObjects?.[pk], r.key.slice(15));
|
|
209
|
+
}
|
|
210
|
+
return get(obj, r.key);
|
|
211
|
+
}) ?? []
|
|
212
|
+
);
|
|
217
213
|
})
|
|
218
214
|
);
|
|
219
215
|
criteriaMap[pk] = { scope, crit };
|
|
220
216
|
return crit;
|
|
221
217
|
}
|
|
222
218
|
|
|
219
|
+
function syncCriteria(newKeys) {
|
|
220
|
+
const { addedKeys, removedKeys } = keyDiff(newKeys, Object.keys(criteriaMap));
|
|
221
|
+
for (const pk of removedKeys) {
|
|
222
|
+
criteriaMap[pk].scope.stop();
|
|
223
|
+
delete criteriaMap[pk];
|
|
224
|
+
}
|
|
225
|
+
for (const pk of addedKeys) {
|
|
226
|
+
ensureCriteria(pk);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
223
230
|
es.run(() => {
|
|
224
231
|
watch(
|
|
225
|
-
() =>
|
|
226
|
-
(
|
|
227
|
-
|
|
228
|
-
for (const pk of removedKeys) {
|
|
229
|
-
criteriaMap[pk].scope.stop();
|
|
230
|
-
delete criteriaMap[pk];
|
|
231
|
-
}
|
|
232
|
-
for (const pk of addedKeys) {
|
|
233
|
-
ensureCriteria(pk);
|
|
234
|
-
}
|
|
232
|
+
() => parentState.objectsVersion,
|
|
233
|
+
() => {
|
|
234
|
+
syncCriteria(Object.keys(parentState.objects));
|
|
235
235
|
},
|
|
236
236
|
{ immediate: true, flush: "sync" }
|
|
237
237
|
);
|
|
238
|
+
watch(() => Object.keys(parentState.objects), syncCriteria);
|
|
238
239
|
});
|
|
239
240
|
|
|
240
241
|
const rawOrder = computed(() => {
|
|
241
242
|
const arr = [...unref(toRef(parentState, "order"))];
|
|
242
243
|
const rulesArr = internalState.orderByRules?.filter(identity) || [];
|
|
243
244
|
return arr.sort((a, b) => {
|
|
244
|
-
const aCrit = criteriaMap[a]
|
|
245
|
-
const bCrit = criteriaMap[b]
|
|
245
|
+
const aCrit = criteriaMap[a]?.crit ?? [];
|
|
246
|
+
const bCrit = criteriaMap[b]?.crit ?? [];
|
|
246
247
|
for (let i = 0; i < rulesArr.length; i++) {
|
|
247
248
|
const rule = rulesArr[i];
|
|
248
249
|
let x = aCrit[i],
|
|
@@ -285,16 +286,45 @@ export function useListSort({ parentState, orderByRules, sortThrottleWait = defa
|
|
|
285
286
|
});
|
|
286
287
|
|
|
287
288
|
const order = ref([]);
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
289
|
+
const writeOrder = (v) => {
|
|
290
|
+
order.value = v;
|
|
291
|
+
// the pending reorder has landed; let running settle unless the parent is still running
|
|
292
|
+
sortWatchRunning.value = false;
|
|
293
|
+
};
|
|
294
|
+
// Held separately from assignOrder so the throttle's own cancel stays typed.
|
|
295
|
+
const throttledOrder = sortThrottleWaitNumber > 0 ? throttle(writeOrder, sortThrottleWaitNumber) : null;
|
|
296
|
+
const assignOrder = throttledOrder ?? writeOrder;
|
|
296
297
|
|
|
297
|
-
|
|
298
|
+
es.run(() => {
|
|
299
|
+
// Raise running synchronously the moment a new order is pending, so a throttled reorder keeps
|
|
300
|
+
// running true until it lands. This mirrors the related, calculated, and search layers, and
|
|
301
|
+
// lets the composed manager's state.running reflect the final reorder settling. Watch cheap
|
|
302
|
+
// signals rather than rawOrder itself: a sync watcher re-evaluates its source on every
|
|
303
|
+
// invalidation, and rawOrder performs the full sort, so watching it synchronously re-sorts
|
|
304
|
+
// the list once per reactive write while a page is being pushed. The batched objectsVersion
|
|
305
|
+
// covers structural changes and the rule reads cover rule changes; reorders triggered another
|
|
306
|
+
// way (a row edit, a parent subset change) raise running in the pre-flush watcher below.
|
|
307
|
+
watch(
|
|
308
|
+
() => [parentState.objectsVersion, internalState.orderByRules, internalState.orderByDesc],
|
|
309
|
+
() => {
|
|
310
|
+
sortWatchRunning.value = true;
|
|
311
|
+
},
|
|
312
|
+
{ flush: "sync" }
|
|
313
|
+
);
|
|
314
|
+
watch(
|
|
315
|
+
rawOrder,
|
|
316
|
+
(v) => {
|
|
317
|
+
sortWatchRunning.value = true;
|
|
318
|
+
assignOrder(v);
|
|
319
|
+
},
|
|
320
|
+
{ immediate: true }
|
|
321
|
+
);
|
|
322
|
+
// A throttled trailing reorder is a timer, not a reactive effect, so disposal would otherwise
|
|
323
|
+
// leave it pending and let it write order after the layer stopped.
|
|
324
|
+
if (throttledOrder) {
|
|
325
|
+
onScopeDispose(() => throttledOrder.cancel());
|
|
326
|
+
}
|
|
327
|
+
});
|
|
298
328
|
|
|
299
329
|
// 6) objectsInOrder just follows that
|
|
300
330
|
const objectsInOrder = computed(() => order.value.map((pk) => parentState.objects[pk]));
|
|
@@ -307,6 +337,7 @@ export function useListSort({ parentState, orderByRules, sortThrottleWait = defa
|
|
|
307
337
|
objects,
|
|
308
338
|
order,
|
|
309
339
|
objectsInOrder,
|
|
340
|
+
running,
|
|
310
341
|
}),
|
|
311
342
|
parentState,
|
|
312
343
|
stop: () => {
|
package/use/listSubscription.js
CHANGED
|
@@ -33,36 +33,30 @@ export class ListSubscriptionError extends Error {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* The raw state of a list subscription.
|
|
37
|
-
*
|
|
38
|
-
* @typedef {object} ListSubscriptionMyState
|
|
36
|
+
* @typedef {object} ListSubscriptionMyState - The raw state of a list subscription.
|
|
39
37
|
* @property {import('vue').Ref<boolean>|boolean} intendToList - If this is true, the list should be fetched, or re-fetched if arguments change.
|
|
40
38
|
* @property {import('vue').Ref<boolean>|boolean} intendToSubscribe - If this is true, the subscription should start or restart if arguments change.
|
|
41
39
|
* @property {import('vue').Ref<boolean>} subscribed - Whether the subscription is active.
|
|
42
40
|
*/
|
|
43
41
|
|
|
44
42
|
/**
|
|
45
|
-
* @typedef {import('vue').ToRefs<import('./listInstance.js').ListInstanceState>} ListInstanceStateRefs
|
|
43
|
+
* @typedef {import('vue').ToRefs<import('./listInstance.js').ListInstanceState>} ListInstanceStateRefs - The list instance's reactive state converted to individual Vue refs.
|
|
46
44
|
*/
|
|
47
45
|
|
|
48
46
|
/**
|
|
49
|
-
* The raw state of a list subscription, including the state from the list instance.
|
|
50
|
-
*
|
|
51
47
|
* @typedef {ListSubscriptionMyState & (
|
|
52
48
|
* Pick<import('./loadingError.js').LoadingErrorStatus, "loading" | "error" | "errored">
|
|
53
|
-
* ) & ListInstanceStateRefs} ListSubscriptionRawState
|
|
49
|
+
* ) & ListInstanceStateRefs} ListSubscriptionRawState - The raw state of a list subscription, including the state from the list instance.
|
|
54
50
|
*/
|
|
55
51
|
|
|
56
52
|
/**
|
|
57
|
-
* A reactive object that manages a list of objects, as returned by `useListInstance`.
|
|
58
|
-
*
|
|
59
|
-
* @typedef {import('vue').Reactive<ListSubscriptionRawState>} ListSubscriptionState
|
|
53
|
+
* @typedef {import('vue').Reactive<ListSubscriptionRawState>} ListSubscriptionState - A reactive object that manages a list of objects, as returned by `useListInstance`.
|
|
60
54
|
*/
|
|
61
55
|
|
|
62
56
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
57
|
+
* @typedef {Pick<import('./loadingError.js').LoadingErrorStatus, "clearError"> & {
|
|
58
|
+
* stop: () => void
|
|
59
|
+
* }} ListSubscriptionFunctions - The methods available on a list subscription.
|
|
66
60
|
*/
|
|
67
61
|
|
|
68
62
|
/**
|
|
@@ -70,13 +64,11 @@ export class ListSubscriptionError extends Error {
|
|
|
70
64
|
* state: ListSubscriptionState,
|
|
71
65
|
* listInstance: import('./listInstance.js').ListInstance,
|
|
72
66
|
* loadingError: import('./loadingError.js').LoadingErrorStatus,
|
|
73
|
-
* }} ListSubscriptionContext
|
|
67
|
+
* }} ListSubscriptionContext - The context (state, list instance, and loading/error status) bound to the shared list subscription functions.
|
|
74
68
|
*/
|
|
75
69
|
|
|
76
70
|
/**
|
|
77
|
-
* The properties of a list subscription.
|
|
78
|
-
*
|
|
79
|
-
* @typedef {object} ListSubscriptionProperties
|
|
71
|
+
* @typedef {object} ListSubscriptionProperties - The properties of a list subscription.
|
|
80
72
|
* @property {ListSubscriptionState} state - The reactive state of the list subscription.
|
|
81
73
|
* @property {import('./listInstance.js').ListInstance} listInstance - The list instance used by the subscription.
|
|
82
74
|
* @property {import('./cancellableIntent.js').CancellableIntent} listIntent - The `CancellableIntent` instance managing if the list should be (re)fetched.
|
|
@@ -84,21 +76,16 @@ export class ListSubscriptionError extends Error {
|
|
|
84
76
|
*/
|
|
85
77
|
|
|
86
78
|
/**
|
|
87
|
-
* An instance of a list subscription, returned by `useListSubscription`.
|
|
88
|
-
*
|
|
89
|
-
* @typedef {ListSubscriptionFunctions & ListSubscriptionProperties} ListSubscription
|
|
79
|
+
* @typedef {ListSubscriptionFunctions & ListSubscriptionProperties} ListSubscription - An instance of a list subscription, returned by `useListSubscription`.
|
|
90
80
|
*/
|
|
91
81
|
|
|
92
82
|
/**
|
|
93
|
-
* @typedef {object} ListSubscriptionOwnOptions
|
|
83
|
+
* @typedef {object} ListSubscriptionOwnOptions - The options specific to a list subscription, namely an optional pre-built list instance to reuse.
|
|
94
84
|
* @property {import("./listInstance.js").ListInstance} [listInstance] - A list instance to use instead of creating one.
|
|
95
85
|
*/
|
|
96
86
|
|
|
97
87
|
/**
|
|
98
|
-
* Defines the settings required to establish a list subscription, detailing how list instances should handle updates
|
|
99
|
-
* and subscriptions based on the given properties.
|
|
100
|
-
*
|
|
101
|
-
* @typedef {import("./listInstance.js").ListInstanceOptions & ListSubscriptionOwnOptions} ListSubscriptionOptions
|
|
88
|
+
* @typedef {import("./listInstance.js").ListInstanceOptions & ListSubscriptionOwnOptions} ListSubscriptionOptions - Defines the settings required to establish a list subscription, detailing how list instances should handle updates and subscriptions based on the given properties.
|
|
102
89
|
*/
|
|
103
90
|
|
|
104
91
|
/**
|
|
@@ -352,5 +339,12 @@ export function useListSubscription({ listInstance, props, handlers }) {
|
|
|
352
339
|
listIntent,
|
|
353
340
|
subscribeIntent,
|
|
354
341
|
clearError: proxyLoadingError.clearError,
|
|
342
|
+
// Stops both intents, mirroring useObjectSubscription, so a caller that owns this
|
|
343
|
+
// subscription's lifetime does not have to know its intent inventory. The wrapped
|
|
344
|
+
// instance keeps its state and still takes manual calls.
|
|
345
|
+
stop: () => {
|
|
346
|
+
listIntent.stop();
|
|
347
|
+
subscribeIntent.stop();
|
|
348
|
+
},
|
|
355
349
|
};
|
|
356
350
|
}
|
package/use/loading.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
import { readonly, ref } from "vue";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {import("vue").Ref<boolean|undefined>} LoadingRef
|
|
5
|
-
* @typedef {Readonly<LoadingRef>} LoadingReadonlyRef
|
|
4
|
+
* @typedef {import("vue").Ref<boolean|undefined>} LoadingRef - A Vue ref to the loading flag, which is a boolean or undefined.
|
|
5
|
+
* @typedef {Readonly<LoadingRef>} LoadingReadonlyRef - A readonly Vue ref to the loading flag, which is a boolean or undefined.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* @typedef {object} LoadingProperties
|
|
9
|
+
* @typedef {object} LoadingProperties - The reactive loading-state member (loading) contributed by the useLoading composable.
|
|
10
10
|
* @property {LoadingReadonlyRef} loading - Whether the component is loading.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @typedef {object} LoadingFunctions
|
|
14
|
+
* @typedef {object} LoadingFunctions - The loading-state actions (setLoading, clearLoading) contributed by the useLoading composable.
|
|
15
15
|
* @property {() => void} setLoading - Set the loading state to true.
|
|
16
16
|
* @property {() => void} clearLoading - Set the loading state to false.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The loading state API.
|
|
21
|
-
*
|
|
22
|
-
* @typedef {LoadingProperties & LoadingFunctions} LoadingStatus
|
|
20
|
+
* @typedef {LoadingProperties & LoadingFunctions} LoadingStatus - The loading state API.
|
|
23
21
|
*/
|
|
24
22
|
|
|
25
23
|
/**
|
package/use/loadingError.js
CHANGED
|
@@ -2,9 +2,9 @@ import { useLoading } from "./loading.js";
|
|
|
2
2
|
import { useError } from "./error.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @typedef {import('./loading.js').LoadingProperties & import('./error.js').ErrorProperties} LoadingErrorProperties
|
|
6
|
-
* @typedef {import('./loading.js').LoadingFunctions & import('./error.js').ErrorFunctions} LoadingErrorFunctions
|
|
7
|
-
* @typedef {LoadingErrorProperties & LoadingErrorFunctions} LoadingErrorStatus
|
|
5
|
+
* @typedef {import('./loading.js').LoadingProperties & import('./error.js').ErrorProperties} LoadingErrorProperties - The combined reactive loading and error state members contributed by the useLoadingError composable.
|
|
6
|
+
* @typedef {import('./loading.js').LoadingFunctions & import('./error.js').ErrorFunctions} LoadingErrorFunctions - The combined loading and error state actions contributed by the useLoadingError composable.
|
|
7
|
+
* @typedef {LoadingErrorProperties & LoadingErrorFunctions} LoadingErrorStatus - The combined loading and error state API (properties plus actions) returned by useLoadingError.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|