@arrai-innovations/reactive-helpers 10.4.2 → 11.0.1

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,7 @@
1
1
  import { loadingCombine } from "../utils/loadingCombine.js";
2
2
  import { useCancellableIntent } from "./cancellableIntent.js";
3
- import { listInstanceStateKeys, useListInstance } from "./listInstance.js";
3
+ import { useListInstance } from "./listInstance.js";
4
+ import { listInstanceStateKeys } from "./listKeys.js";
4
5
  import inspect from "browser-util-inspect";
5
6
  import cloneDeep from "lodash-es/cloneDeep.js";
6
7
  import isEmpty from "lodash-es/isEmpty.js";
@@ -14,17 +15,6 @@ export class ListSubscriptionError extends Error {
14
15
  }
15
16
  }
16
17
 
17
- export const listSubscriptionStateKeys = [
18
- "subscriptionLoading",
19
- "subscriptionErrored",
20
- "subscriptionError",
21
- "intendToList",
22
- "intendToSubscribe",
23
- "subscribed",
24
- ];
25
-
26
- export const listSubscriptionFunctions = ["subscribe", "unsubscribe", "clearError"];
27
-
28
18
  /**
29
19
  * The configuration options used to create a list subscription.
30
20
  * @typedef {object} ListSubscriptionOptions
@@ -190,7 +180,7 @@ export function useListSubscription({ listInstance, props, functions, keepOldPag
190
180
  listInstance.deleteListObject(id);
191
181
  } catch (err) {
192
182
  if (err.name === "ListError" && err.code === "missing-object") {
193
- console.warn(`deleteFromSubscription: delete for id not in objects (${id}).`);
183
+ console.warn(`deleteFromSubscription: delete for id not in objects (${inspect(id)}).`);
194
184
  return;
195
185
  }
196
186
  throw err;
package/use/search.js CHANGED
@@ -1,105 +1,195 @@
1
1
  import { assignReactiveObject } from "../utils/assignReactiveObject.js";
2
+ import asyncThrottle from "@jcoreio/async-throttle";
2
3
  import FlexSearch from "flexsearch";
3
- import fromPairs from "lodash-es/fromPairs.js";
4
- import throttle from "lodash-es/throttle.js";
5
- import { effectScope, reactive, toRef, watch } from "vue";
4
+ import cloneDeep from "lodash-es/cloneDeep.js";
5
+ import isEqual from "lodash-es/isEqual.js";
6
+ import { effectScope, reactive, toRef, watch, computed } from "vue";
7
+ import { deepUnref } from "vue-deepunref";
6
8
 
7
- const indexOptions = {
8
- tokenize: "forward",
9
+ /* minimize new Set() allocations */
10
+ const unionReduce = (accumulator, currentValue) => {
11
+ for (const elem of currentValue) {
12
+ accumulator.add(elem);
13
+ }
14
+ return accumulator;
9
15
  };
10
16
 
11
- const searchOptions = {
12
- throttle: 500,
13
- limit: 1000,
14
- };
17
+ /**
18
+ * FlexSearch.Document search options
19
+ * @typedef {object} SearchOptions
20
+ * @property {number} limit - limit of results
21
+ */
15
22
 
16
- export function setDefaultIndexOptions(newDefaultIndexOptions = {}) {
17
- Object.assign(indexOptions, newDefaultIndexOptions);
18
- }
23
+ // eslint-disable-next-line jsdoc/require-property
24
+ /**
25
+ * FlexSearch.Document options
26
+ * @typedef {object} DocumentOptions
27
+ */
19
28
 
20
- export function setDefaultSearchOptions(newDefaultSearchOptions = {}) {
21
- Object.assign(searchOptions, newDefaultSearchOptions);
22
- }
29
+ /**
30
+ * @typedef {object} SearchState
31
+ * @property {string} search - the search string
32
+ * @property {object} results - the results, where the keys are the ids of the objects that match, and the values are true
33
+ * @property {boolean} searched - whether the search has been performed
34
+ * @property {boolean} searching - whether the search is currently running
35
+ */
23
36
 
24
- export function useSearch(
25
- customIndexOptions = {}, // custom index options are not reactive.
26
- customSearchOptions = {} // custom search options are reactive.
27
- ) {
28
- let searchIndex = new FlexSearch.Index({
29
- ...indexOptions,
30
- ...customIndexOptions,
31
- });
32
- const mySearchOptions = {
33
- ...searchOptions,
34
- ...customSearchOptions,
35
- };
37
+ /**
38
+ * @typedef {object} SearchInstance
39
+ * @property {SearchState} state - the state
40
+ * @property {function} addIndex - add an index
41
+ * @property {function} updateIndex - update an index
42
+ * @property {function} removeIndex - remove an index
43
+ * @property {function} clearIndex - clear the index
44
+ * @property {object} effectScope - a Vue effect scope
45
+ */
46
+
47
+ const defaultDocumentOptions = {
48
+ tokenize: "forward",
49
+ document: {
50
+ id: "id",
51
+ index: ["name"],
52
+ },
53
+ };
54
+
55
+ /**
56
+ * A reactive object for passing document options or search options to useSearch
57
+ * @typedef {object} SearchProps
58
+ * @property {DocumentOptions} customDocumentOptions - FlexSearch.Document options
59
+ * @property {SearchOptions} customSearchOptions - search options
60
+ */
61
+
62
+ /**
63
+ * A reactive wrapper around FlexSearch.Index
64
+ * @param {object} options - options
65
+ * @param {SearchProps} options.props - props
66
+ * @param {number} [options.throttle] - throttle wait time
67
+ * @returns {SearchInstance} - the instance
68
+ */
69
+ export function useSearch({ props, throttle = 500 }) {
70
+ let searchIndex;
71
+ const events = new EventTarget();
36
72
  const state = reactive({
37
73
  search: "",
38
74
  results: {},
39
75
  searched: false,
40
76
  searching: false,
77
+ customDocumentOptions: toRef(props, "customDocumentOptions"),
78
+ customSearchOptions: toRef(props, "customSearchOptions"),
79
+ called: 0,
80
+ pending: 0,
81
+ running: computed(() => state.searching || state.pending > state.called),
41
82
  });
42
- const addIndex = (id, indexValue) => {
43
- // numeric ids consume less memory in flexsearch.
44
- const numericId = +id;
45
- const numericIfPossible = isNaN(numericId) ? id : numericId;
46
- searchIndex.add(numericIfPossible, indexValue);
83
+ const es = effectScope();
84
+ const addIndex = async (indexValue) => {
85
+ ++state.pending;
86
+ const unrefedIndexValue = deepUnref(indexValue);
87
+ try {
88
+ await searchIndex.addAsync(unrefedIndexValue);
89
+ } catch (e) {
90
+ ++state.called;
91
+ throw e;
92
+ }
47
93
  throttledDoSearch();
48
94
  };
49
- const updateIndex = (id, indexValue) => {
50
- // numeric ids consume less memory in flexsearch.
51
- const numericId = +id;
52
- const numericIfPossible = isNaN(numericId) ? id : numericId;
53
- searchIndex.update(numericIfPossible, indexValue);
95
+ const updateIndex = async (indexValue) => {
96
+ ++state.pending;
97
+ try {
98
+ await searchIndex.updateAsync(deepUnref(indexValue));
99
+ } catch (e) {
100
+ ++state.called;
101
+ throw e;
102
+ }
54
103
  throttledDoSearch();
55
104
  };
56
- const removeIndex = (id) => {
57
- // numeric ids consume less memory in flexsearch.
58
- const numericId = +id;
59
- const numericIfPossible = isNaN(numericId) ? id : numericId;
60
- searchIndex.remove(numericIfPossible);
105
+ const removeIndex = async (id) => {
106
+ ++state.pending;
107
+ try {
108
+ await searchIndex.removeAsync(id);
109
+ } catch (e) {
110
+ ++state.called;
111
+ throw e;
112
+ }
61
113
  throttledDoSearch();
62
114
  };
115
+
116
+ let previousCustomDocumentOptions = null;
117
+
118
+ const customDocumentOptionsWatchHandler = () => {
119
+ const unrefCustomDocumentOptions = deepUnref(state.customDocumentOptions);
120
+ if (!isEqual(previousCustomDocumentOptions, unrefCustomDocumentOptions)) {
121
+ clearIndex();
122
+ }
123
+ };
124
+
125
+ const makeIndex = () => {
126
+ const unrefCustomDocumentOptions = deepUnref(state.customDocumentOptions) || cloneDeep(defaultDocumentOptions);
127
+ previousCustomDocumentOptions = unrefCustomDocumentOptions;
128
+ searchIndex = new FlexSearch.Document(unrefCustomDocumentOptions);
129
+ };
130
+
63
131
  const clearIndex = () => {
64
- searchIndex = new FlexSearch.Index(indexOptions);
132
+ makeIndex();
65
133
  assignReactiveObject(state.results, {});
66
- state.searched = false;
134
+ events.dispatchEvent(new Event("newIndex"));
67
135
  };
68
136
 
69
137
  async function doSearch() {
70
- if (!state.search) {
138
+ if (
139
+ !state.search ||
140
+ (state.customDocumentOptions?.minlength && state.search.length < state.customDocumentOptions.minlength)
141
+ ) {
71
142
  assignReactiveObject(state.results, {});
72
143
  state.searched = false;
73
- return;
144
+ // if there was nothing to do the first time, changing from undefined to false will still let
145
+ // users know that we are done.
146
+ } else {
147
+ const results = searchIndex.search(state.search, {
148
+ limit: state.customSearchOptions?.limit || 1000,
149
+ });
150
+ const resultsSet = results.map((r) => r.result).reduce(unionReduce, new Set());
151
+ if (!state.searched) {
152
+ state.searched = true;
153
+ }
154
+ assignReactiveObject(state.results, Object.fromEntries(Array.from(resultsSet).map((e) => [e, true])) || {});
155
+ }
156
+ if (state.pending - state.called <= 0) {
157
+ state.searching = false;
74
158
  }
75
- state.searching = true;
76
- const results = await searchIndex.searchAsync(state.search, {
77
- limit: mySearchOptions.limit,
78
- });
79
- state.searched = true;
80
- assignReactiveObject(state.results, fromPairs(results.map((e) => [e, true])) || {});
81
- state.searching = false;
82
159
  }
83
160
 
84
- const throttledDoSearch = throttle(doSearch, mySearchOptions.throttle);
85
-
86
- const es = effectScope();
161
+ const _throttledDoSearch = asyncThrottle(doSearch, throttle);
162
+ const throttledDoSearch = () => {
163
+ ++state.called;
164
+ if (!state.searching) {
165
+ state.searching = true;
166
+ }
167
+ return _throttledDoSearch();
168
+ };
87
169
 
88
170
  es.run(() => {
171
+ watch(toRef(state, "customDocumentOptions"), customDocumentOptionsWatchHandler, {
172
+ deep: true,
173
+ });
174
+ makeIndex();
89
175
  watch(
90
176
  toRef(state, "search"),
91
- function () {
92
- if (!indexOptions.minlength || state.search.length >= indexOptions.minlength) {
93
- throttledDoSearch();
94
- } else {
95
- assignReactiveObject(state.results, {});
96
- state.searched = false;
97
- }
177
+ () => {
178
+ ++state.pending;
179
+ throttledDoSearch();
98
180
  },
99
181
  {
100
182
  immediate: true,
101
183
  }
102
184
  );
103
185
  });
104
- return { state, addIndex, updateIndex, removeIndex, clearIndex, effectScope: es };
186
+ return {
187
+ state,
188
+ addIndex,
189
+ updateIndex,
190
+ removeIndex,
191
+ clearIndex,
192
+ events,
193
+ effectScope: es,
194
+ };
105
195
  }
@@ -22,7 +22,7 @@ export function useWatchesRunning({ triggerRefs, watchSentinelRefs }) {
22
22
  }
23
23
  );
24
24
  state.running = computed(() => {
25
- const values = watchSentinelRefs.map((ref) => ref.value);
25
+ const values = watchSentinelRefs.map((ref) => unref(ref));
26
26
  return loadingCombine(values);
27
27
  });
28
28
  });
@@ -83,12 +83,12 @@ function validateTargetAndSource(target, source) {
83
83
  * @returns {boolean} True if any keys were replaced, false otherwise.
84
84
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
85
85
  */
86
- function reactiveReplaceKeys(target, source, keys, exclude = []) {
86
+ function reactiveReplaceKeys(target, source, keys, exclude) {
87
87
  const targetIsReactive = isReactive(target);
88
88
  const sourceIsReactive = isReactive(source);
89
89
  let didAnything = false;
90
90
  for (const key of keys) {
91
- if (!exclude.includes(key)) {
91
+ if (!exclude?.includes(key)) {
92
92
  if (targetIsReactive && sourceIsReactive) {
93
93
  const targetPropRaw = unref(toRef(target, key));
94
94
  // if they are object like we can see if the values are the same
@@ -122,7 +122,7 @@ function reactiveReplaceKeys(target, source, keys, exclude = []) {
122
122
  * @returns {boolean} True if any keys were added, false otherwise.
123
123
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
124
124
  */
125
- export function addReactiveObject(target, source, exclude = [], addedKeys = null) {
125
+ export function addReactiveObject(target, source, exclude, addedKeys = null) {
126
126
  if (!addedKeys) {
127
127
  if (target === source) {
128
128
  return false;
@@ -144,7 +144,7 @@ export function addReactiveObject(target, source, exclude = [], addedKeys = null
144
144
  * @returns {boolean} True if any keys were updated, false otherwise.
145
145
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
146
146
  */
147
- export function updateReactiveObject(target, source, exclude = [], sameKeys = null) {
147
+ export function updateReactiveObject(target, source, exclude, sameKeys = null) {
148
148
  if (!sameKeys) {
149
149
  if (target === source) {
150
150
  return false;
@@ -167,7 +167,7 @@ export function updateReactiveObject(target, source, exclude = [], sameKeys = nu
167
167
  * keys will be calculated.
168
168
  * @returns {boolean} True if any keys were added or updated, false otherwise.
169
169
  */
170
- export function addOrUpdateReactiveObject(target, source, exclude = [], addedKeys = null, sameKeys = null) {
170
+ export function addOrUpdateReactiveObject(target, source, exclude, addedKeys = null, sameKeys = null) {
171
171
  if (!addedKeys && !sameKeys) {
172
172
  if (target === source) {
173
173
  return false;
@@ -191,7 +191,7 @@ export function addOrUpdateReactiveObject(target, source, exclude = [], addedKey
191
191
  * @returns {boolean} True if any keys were removed, false otherwise.
192
192
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
193
193
  */
194
- export function trimReactiveObject(target, source, exclude = [], removedKeys = null) {
194
+ export function trimReactiveObject(target, source, exclude, removedKeys = null) {
195
195
  if (!removedKeys) {
196
196
  if (target === source) {
197
197
  return false;
@@ -204,14 +204,14 @@ export function trimReactiveObject(target, source, exclude = [], removedKeys = n
204
204
  if (targetIsArray) {
205
205
  // Remove indices in reverse (descending) order to keep them stable
206
206
  for (const removedKey of [...removedKeys].map((key) => parseInt(key, 10)).sort((a, b) => b - a)) {
207
- if (!exclude.includes(removedKey)) {
207
+ if (!exclude?.includes(removedKey)) {
208
208
  target.splice(removedKey, 1);
209
209
  didAnything = true;
210
210
  }
211
211
  }
212
212
  } else {
213
213
  for (const removedKey of removedKeys) {
214
- if (!exclude.includes(removedKey)) {
214
+ if (!exclude?.includes(removedKey)) {
215
215
  delete target[removedKey];
216
216
  didAnything = true;
217
217
  }
@@ -220,6 +220,44 @@ export function trimReactiveObject(target, source, exclude = [], removedKeys = n
220
220
  return didAnything;
221
221
  }
222
222
 
223
+ function checkIfReversed(target, source) {
224
+ if (target.length !== source.length || target.length === 0) {
225
+ return false;
226
+ }
227
+ let t = target.length - 1,
228
+ s = 0,
229
+ slen = source.length;
230
+ while (t >= 0 && s < slen) {
231
+ const targetValue = target[t];
232
+ const sourceValue = source[s];
233
+ if (targetValue === sourceValue) {
234
+ t--;
235
+ s++;
236
+ continue;
237
+ }
238
+ return false;
239
+ }
240
+ return true;
241
+ }
242
+
243
+ export function assignReactiveArray(target, source) {
244
+ if (target === source) {
245
+ return false;
246
+ }
247
+ ({ target, source } = validateTargetAndSource(target, source));
248
+ let didAnything = false;
249
+ if (checkIfReversed(target, source)) {
250
+ // reverse the target
251
+ target.reverse();
252
+ didAnything = true;
253
+ } else {
254
+ const { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
255
+ didAnything |= trimReactiveObject(target, source, null, removedKeys);
256
+ didAnything |= addOrUpdateReactiveObject(target, source, null, addedKeys, sameKeys);
257
+ }
258
+ return didAnything;
259
+ }
260
+
223
261
  /**
224
262
  * Change a target to match a source, where keys missing from the source are removed from the target,
225
263
  * keys present in the source are added to the target, and keys present in both are updated in the target.
@@ -230,7 +268,13 @@ export function trimReactiveObject(target, source, exclude = [], removedKeys = n
230
268
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
231
269
  * @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
232
270
  */
233
- export function assignReactiveObject(target, source, exclude = []) {
271
+ export function assignReactiveObject(target, source, exclude) {
272
+ if (Array.isArray(target) && Array.isArray(source)) {
273
+ if (exclude?.length) {
274
+ console.warn(`assignReactiveObject: exclude doesn't make sense for array assignment`);
275
+ }
276
+ return assignReactiveArray(target, source);
277
+ }
234
278
  if (target === source) {
235
279
  return false;
236
280
  }
@@ -277,7 +321,7 @@ function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn)
277
321
  for (const key of keysForRecurse) {
278
322
  // scope exclude for this next level, remove keys that don't start with the current path, trim keys that do to remove the current path
279
323
  const nextLevelExclude = exclude
280
- .filter((excludeKey) => !excludeKey.startsWith(path))
324
+ ?.filter((excludeKey) => !excludeKey.startsWith(path))
281
325
  .map((excludeKey) => excludeKey.replace(path, ""));
282
326
  const nextPath = isArray(source[key]) ? `${path}[${key}]` : `${path}.${key}`;
283
327
  fn(target[key], source[key], nextLevelExclude, nextPath);
@@ -298,7 +342,7 @@ function recursiveInner(target, source, exclude, addedKeys, sameKeys, path, fn)
298
342
  * @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
299
343
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
300
344
  */
301
- function assignReactiveObjectRecursive(target, source, exclude = [], path = "") {
345
+ function assignReactiveObjectRecursive(target, source, exclude, path = "") {
302
346
  let { addedKeys, sameKeys, removedKeys } = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
303
347
  let didAnything = false;
304
348
  didAnything |= trimReactiveObject(target, source, exclude, removedKeys);
@@ -316,7 +360,7 @@ function assignReactiveObjectRecursive(target, source, exclude = [], path = "")
316
360
  * @returns {boolean} True if any keys were added, updated, or removed, false otherwise.
317
361
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
318
362
  */
319
- export function assignReactiveObjectDeep(target, source, exclude = []) {
363
+ export function assignReactiveObjectDeep(target, source, exclude) {
320
364
  // exclude keys will need to be lodash get strings
321
365
  if (target === source) {
322
366
  return false;
@@ -337,7 +381,7 @@ export function assignReactiveObjectDeep(target, source, exclude = []) {
337
381
  * @param {string} [path] The current path, used to rescope exclude for the next level.
338
382
  * @returns {boolean} True if any keys were added or updated, false otherwise.
339
383
  */
340
- function addOrUpdateReactiveObjectRecursive(target, source, exclude = [], path = "") {
384
+ function addOrUpdateReactiveObjectRecursive(target, source, exclude, path = "") {
341
385
  let addedKeys,
342
386
  sameKeys = keyDiff(Object.keys(source) || [], Object.keys(target) || []);
343
387
  return recursiveInner(target, source, exclude, addedKeys, sameKeys, path, addOrUpdateReactiveObjectRecursive);
@@ -353,7 +397,7 @@ function addOrUpdateReactiveObjectRecursive(target, source, exclude = [], path =
353
397
  * @returns {boolean} True if any keys were added or updated, false otherwise.
354
398
  * @throws {AssignReactiveObjectError} If either target or source are not ultimately objects or arrays.
355
399
  */
356
- export function addOrUpdateReactiveObjectDeep(target, source, exclude = []) {
400
+ export function addOrUpdateReactiveObjectDeep(target, source, exclude) {
357
401
  // exclude keys will need to be lodash get strings
358
402
  if (target === source) {
359
403
  return false;
package/utils/index.js CHANGED
@@ -8,6 +8,7 @@ export * from "./getFakeId.js";
8
8
  export * from "./keyDiff.js";
9
9
  export * from "./lifecycleDebug.js";
10
10
  export * from "./loadingCombine.js";
11
+ export * from "./relatedCalculatedHelpers.js";
11
12
  export * from "./set.js";
12
13
  export * from "./transformWalk.js";
13
14
  export * from "./watches.js";
package/utils/keyDiff.js CHANGED
@@ -18,23 +18,29 @@ import { difference, intersection } from "./set.js";
18
18
  /**
19
19
  * Result object of keyDiff and keyDiffDeep
20
20
  * @typedef {object} KeyDiffResult
21
- * @property {string[]} [sameKeys] - if sameKeys option is true, return keys that are the same
22
- * @property {string[]} [removedKeys] - if removedKeys option is true, return keys that are removed
23
- * @property {string[]} [addedKeys] - if addedKeys option is true, return keys that are added
21
+ * @property {Set} [sameKeys] - if sameKeys option is true, return keys that are the same
22
+ * @property {Set} [removedKeys] - if removedKeys option is true, return keys that are removed
23
+ * @property {Set} [addedKeys] - if addedKeys option is true, return keys that are added
24
24
  */
25
25
 
26
26
  /**
27
27
  * Calculate the difference between two arrays of keys, in terms of what keys
28
28
  * are the same, what keys are removed, and what keys are added.
29
29
  * @function keyDiff
30
- * @param {string[]} newKeys - keys to consider as new
31
- * @param {string[]} oldKeys - keys to consider as old
30
+ * @param {string[]|Set} newKeys - keys to consider as new
31
+ * @param {string[]|Set} oldKeys - keys to consider as old
32
32
  * @param {KeyDiffOptions} [options] - which differences are returned
33
33
  * @returns {KeyDiffResult} - the differences
34
34
  */
35
35
  export function keyDiff(newKeys, oldKeys, { sameKeys = true, removedKeys = true, addedKeys = true } = {}) {
36
- const newKeysSet = new Set(newKeys);
37
- const oldKeysSet = new Set(oldKeys);
36
+ let newKeysSet = newKeys;
37
+ let oldKeysSet = oldKeys;
38
+ if (!(newKeys instanceof Set)) {
39
+ newKeysSet = new Set(newKeys);
40
+ }
41
+ if (!(oldKeys instanceof Set)) {
42
+ oldKeysSet = new Set(oldKeys);
43
+ }
38
44
  const returnValue = {};
39
45
  if (sameKeys) {
40
46
  returnValue.sameKeys = intersection(newKeysSet, oldKeysSet);
@@ -0,0 +1,17 @@
1
+ export const relatedItemRegex = /^relatedItem\./;
2
+ export const calculatedItemRegex = /^calculatedItem\./;
3
+
4
+ export const getObjectRelatedCalculatedByKey = (obj, relatedObj, calculatedObj, key) => {
5
+ let getObj = obj,
6
+ getKey = key.replace(relatedItemRegex, () => {
7
+ getObj = relatedObj;
8
+ return "";
9
+ });
10
+ if (getKey === key) {
11
+ getKey = key.replace(calculatedItemRegex, () => {
12
+ getObj = calculatedObj;
13
+ return "";
14
+ });
15
+ }
16
+ return [getObj, getKey];
17
+ };
package/utils/watches.js CHANGED
@@ -1,4 +1,4 @@
1
- import { watch } from "vue";
1
+ import { watch, toRef } from "vue";
2
2
 
3
3
  // If you want an immediate watch, but you can't use immediate because you want to stop the watch in the function.
4
4
  export class ImmediateStopWatch {
@@ -85,7 +85,7 @@ export function doAwaitTimeout(timeout) {
85
85
  }
86
86
 
87
87
  export class AwaitNot {
88
- constructor({ obj, prop, couldAlreadyBeFalse = false, timeout = 1000 }) {
88
+ constructor({ obj, prop, ref, couldAlreadyBeFalse = false, timeout = 1000 }) {
89
89
  if (timeout > 0) {
90
90
  this.timeout = new AwaitTimeout({ timeout });
91
91
  }
@@ -94,8 +94,11 @@ export class AwaitNot {
94
94
  this.reject = reject;
95
95
  });
96
96
  this.couldAlreadyBeFalse = couldAlreadyBeFalse;
97
- this.obj = obj;
98
- this.prop = prop;
97
+ if (ref) {
98
+ this.ref = ref;
99
+ } else {
100
+ this.ref = toRef(() => obj[prop]);
101
+ }
99
102
  this.trueISW = new ImmediateStopWatch();
100
103
  this.falseISW = new ImmediateStopWatch();
101
104
  // prebuild the exception for a more useful stack.
@@ -125,7 +128,7 @@ export class AwaitNot {
125
128
  });
126
129
  this.timeout.start();
127
130
  }
128
- if (this.obj[this.prop] === false && this.couldAlreadyBeFalse) {
131
+ if (this.ref.value === false && this.couldAlreadyBeFalse) {
129
132
  this.waitForTrue();
130
133
  } else {
131
134
  this.waitForFalse();
@@ -134,14 +137,14 @@ export class AwaitNot {
134
137
 
135
138
  waitForTrue() {
136
139
  this.trueISW.start(
137
- () => this.obj[this.prop],
140
+ this.ref,
138
141
  (newValue) => {
139
142
  if (newValue === true) {
140
143
  this.stopTrue();
141
144
  this.waitForFalse();
142
145
  }
143
146
  },
144
- [this.obj[this.prop]]
147
+ [this.ref.value]
145
148
  );
146
149
  }
147
150
 
@@ -154,7 +157,7 @@ export class AwaitNot {
154
157
 
155
158
  waitForFalse() {
156
159
  this.falseISW.start(
157
- () => this.obj[this.prop],
160
+ this.ref,
158
161
  (newValue) => {
159
162
  if (newValue === false) {
160
163
  this.stop();
@@ -164,7 +167,7 @@ export class AwaitNot {
164
167
  this.cleanPromise();
165
168
  }
166
169
  },
167
- [this.obj[this.prop]]
170
+ [this.ref.value]
168
171
  );
169
172
  }
170
173
 
@@ -193,8 +196,8 @@ export class AwaitNot {
193
196
  }
194
197
  }
195
198
 
196
- export function doAwaitNot({ obj, prop, couldAlreadyBeFalse = true, timeout = 1000 }) {
197
- const awaitNot = new AwaitNot({ obj, prop, couldAlreadyBeFalse, timeout });
199
+ export function doAwaitNot({ obj, prop, ref, couldAlreadyBeFalse = true, timeout = 1000 }) {
200
+ const awaitNot = new AwaitNot({ obj, prop, ref, couldAlreadyBeFalse, timeout });
198
201
  awaitNot.start();
199
202
  return awaitNot.promise;
200
203
  }