tracked-instance 1.0.23 → 2.0.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/README.md +75 -20
- package/dist/index.mjs +21 -12
- package/dist/types/collection.d.ts +28 -3
- package/dist/types/index.d.ts +2 -2
- package/dist/types/tracked-instance.d.ts +18 -2
- package/dist/types/utils.d.ts +36 -0
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -70,6 +70,27 @@ useTrackedInstance(false)
|
|
|
70
70
|
useTrackedInstance([1,2,3])
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
### Custom equality with `equals` option
|
|
74
|
+
|
|
75
|
+
By default, values are compared with strict equality (`===`). You can override this with a custom `equals` function that is called for primitive leaf values.
|
|
76
|
+
|
|
77
|
+
A common use case is treating `null` and `""` as equivalent — for example, when a UI component (like Vuetify's text field with a clear button) sets a value to `null`, but the original data used `""`:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
const { data, isDirty } = useTrackedInstance(
|
|
81
|
+
{ comment: null },
|
|
82
|
+
{ equals: (a, b) => (a ?? '') === (b ?? '') }
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
data.value.comment = '' // treated as equal to null
|
|
86
|
+
console.log(isDirty.value) // false
|
|
87
|
+
|
|
88
|
+
data.value.comment = 'hello'
|
|
89
|
+
console.log(isDirty.value) // true
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The `equals` function receives the two values being compared and should return `true` if they are considered equal. It is only called for primitive values — object and array fields are always compared by recursing into their properties.
|
|
93
|
+
|
|
73
94
|
### Real-world example
|
|
74
95
|
[Try on playground](https://play.vuejs.org/#eNqNVc1u00AQfpXBl7RSapfCAVlJVGh7KEiloj36srEn8TbrtbU/aaMoz4DEjROvgYTEw/AC8AjM7tqpaarSm+d/vplv1uvobdPES4tRGo10rnhjQKOxzSSTvGpqZWBtNV4rli+wOJfaMJnjBmaqrmBggvqAt/pBJjOZ1yTBumCGDSEvmZxjceoFrk+5MqshKKQaQxA185YNjGG3yN46kwCGG4EpDAZDJ62QqRSkFcKLXF/aqeC6xCKFGRMavbpAw7jQKfgMAEkCuqytKGCKYBvqDOlzta3vvDaZ3Oy79sk5uACX3HAmwCGBW24ohYGKLRBmtaqgcFgy2SUJ7XJq5KVvomv8ukQ4ZWoBHySfl6aP4+jw8M0uDqPs4zCoIOampsBWASBZ5WqclIprUzclKrioBZMDh9l3qRHbJWgCBBK1A79kwqIOWQh5D37YnmZLPGmjxrC3D+NJKLpF64YS+zQURtGjJLCHeEOCwaoRNEOSAEYFX07a3VPv644HsNmMEmfzTqWCJHxNrTG1hONc8HwxziLPliya/Pr64/f3z/DJiaMkePlyFOOxHms7rbiJG4VLlIZCezgoQcA74rKxppvg8qCqCxTk6xH5rWVRZzWrBslk8I4aaMn0VJpY2mqKqsvm1ryTLLg8K12Xp8ePnXR5ifliWt/1Ez4jZUuuuCNV7Kj0X+Bt4jD7B75h+Pcp0oJrNhVYkO1Fu/LO2oIG+PPty0+4oi11JG0r3K/XCW673abLo0nYaOEPMx0lpPEWWvuE2NV7cjzDnNrxs8fJaBiFx+2gYk18o2tJz5/nd9YaiC7bM6MxPHjnnDGLSmManSaJlc1iHud1lez6dbdFFY2m25rx+YN6FNdwgepjYzjd3j91mRD17Xuv274KPsbt/BH9jSYauNYu3c2oJTWwtRmm5u6MnPns6sIvdmskaljH+yeMdHa1sK7H4PbOyoLa7vn5bs/9+LicX+uzO4NSd6Bco34a3j+L6J9z8gT0+3Zfxa+3U9z8BYQrOQM=)
|
|
75
96
|
```vue
|
|
@@ -156,7 +177,7 @@ console.log(isDirty.value) // true
|
|
|
156
177
|
Add new item:
|
|
157
178
|
```javascript
|
|
158
179
|
const addedItem = add({name: 'Taras'})
|
|
159
|
-
console.log(addedItem) // {instance: TrackedInstance<{name: 'Taras'}>, isRemoved: false, isNew: true, meta:
|
|
180
|
+
console.log(addedItem) // {instance: TrackedInstance<{name: 'Taras'}>, isRemoved: false, isNew: true, meta: undefined}
|
|
160
181
|
```
|
|
161
182
|
Add new item in specific position:
|
|
162
183
|
```javascript
|
|
@@ -259,27 +280,61 @@ console.log(items.value[0].meta.isValidName.value) // false
|
|
|
259
280
|
```
|
|
260
281
|
|
|
261
282
|
# Documentation
|
|
262
|
-
##
|
|
263
|
-
- **data** - tracked data
|
|
264
|
-
- **changeData** - includes only modified fields from data, considers nested objects and arrays
|
|
265
|
-
- **isDirty** - weather instance has some changes
|
|
266
|
-
- **loadData** - rewrite data and clear dirty state
|
|
267
|
-
- **reset** - rollback changes at the last point when the instance was not isDirty
|
|
283
|
+
## useTrackedInstance(initialData?, options?)
|
|
268
284
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
285
|
+
```typescript
|
|
286
|
+
useTrackedInstance<Data>(initialData?: Data, options?: TrackedInstanceOptions): TrackedInstance<Data>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Options
|
|
290
|
+
|
|
291
|
+
| Option | Type | Description |
|
|
292
|
+
|--------|------|-------------|
|
|
293
|
+
| `equals` | `(a: unknown, b: unknown) => boolean` | Custom equality function for primitive leaf values. Replaces default `===`. |
|
|
294
|
+
|
|
295
|
+
### TrackedInstance
|
|
296
|
+
|
|
297
|
+
- **data** — reactive reference to the current data. Mutate it directly to track changes.
|
|
298
|
+
- **changedData** — only the modified fields, deeply nested. `undefined` when nothing has changed.
|
|
299
|
+
- **isDirty** — `true` when any field differs from the original.
|
|
300
|
+
- **loadData(newData)** — replace data and clear dirty state (new baseline).
|
|
301
|
+
- **reset()** — revert all changes back to the last `loadData()` baseline.
|
|
302
|
+
|
|
303
|
+
## useCollection(createItemMeta?, options?)
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
useCollection<Item, Meta>(
|
|
307
|
+
createItemMeta?: (instance: TrackedInstance<Item>) => Meta,
|
|
308
|
+
options?: TrackedInstanceOptions,
|
|
309
|
+
): Collection<Item, Meta>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
The `options` object (including `equals`) is passed to every `TrackedInstance` created inside the collection — both from `loadData()` and `add()`.
|
|
313
|
+
|
|
314
|
+
```javascript
|
|
315
|
+
const { items, isDirty } = useCollection(
|
|
316
|
+
() => undefined,
|
|
317
|
+
{ equals: (a, b) => (a ?? '') === (b ?? '') }
|
|
318
|
+
)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Collection
|
|
322
|
+
|
|
323
|
+
- **items** — reactive array of `CollectionItem`.
|
|
324
|
+
- **isDirty** — `true` if any item is dirty, new, or soft-removed.
|
|
325
|
+
- **add(item, index?)** — add a new item (marked `isNew`). Appended to end by default.
|
|
326
|
+
- **remove(index, isHardRemove?)** — soft-remove by default (`isRemoved = true`). Pass `true` to hard-delete from array.
|
|
327
|
+
- **loadData(items)** — replace all items and clear dirty state.
|
|
328
|
+
- **reset()** — remove new items, restore soft-removed items, and reset all instance data.
|
|
329
|
+
|
|
330
|
+
### CollectionItem
|
|
276
331
|
|
|
277
332
|
```typescript
|
|
278
|
-
interface CollectionItem {
|
|
279
|
-
instance: TrackedInstance
|
|
280
|
-
isRemoved: Ref<boolean>
|
|
281
|
-
isNew: Ref<boolean>
|
|
282
|
-
meta:
|
|
283
|
-
remove: (isHardRemove?: boolean) => void
|
|
333
|
+
interface CollectionItem<Item, Meta = undefined> {
|
|
334
|
+
instance: TrackedInstance<Item> // the tracked instance for this item
|
|
335
|
+
isRemoved: Ref<boolean> // true after soft remove
|
|
336
|
+
isNew: Ref<boolean> // true for items added via add(), false for items loaded via loadData()
|
|
337
|
+
meta: Meta // custom metadata from createItemMeta(), undefined by default
|
|
338
|
+
remove: (isHardRemove?: boolean) => void // shortcut: removes self from collection
|
|
284
339
|
}
|
|
285
340
|
```
|
package/dist/index.mjs
CHANGED
|
@@ -1535,7 +1535,7 @@ var setOriginalDataValue = (originalData, path) => {
|
|
|
1535
1535
|
const lastItem = path.at(-1);
|
|
1536
1536
|
originalDataTarget[lastItem.property] = lastItem.target[lastItem.property];
|
|
1537
1537
|
};
|
|
1538
|
-
var snapshotValueToOriginalData = (originalData, path, value) => {
|
|
1538
|
+
var snapshotValueToOriginalData = (originalData, path, value, equals) => {
|
|
1539
1539
|
const pathAsString = path.map((i) => i.property);
|
|
1540
1540
|
const valueInOriginalData = get_default(originalData, pathAsString);
|
|
1541
1541
|
const markRemovedFieldsAsUndefined = (valueInOriginalData2, oldValue2) => {
|
|
@@ -1555,7 +1555,8 @@ var snapshotValueToOriginalData = (originalData, path, value) => {
|
|
|
1555
1555
|
snapshotValueToOriginalData(
|
|
1556
1556
|
originalData,
|
|
1557
1557
|
path.concat({ target: oldValue2 || value, property: key }),
|
|
1558
|
-
void 0
|
|
1558
|
+
void 0,
|
|
1559
|
+
equals
|
|
1559
1560
|
);
|
|
1560
1561
|
}
|
|
1561
1562
|
};
|
|
@@ -1564,7 +1565,7 @@ var snapshotValueToOriginalData = (originalData, path, value) => {
|
|
|
1564
1565
|
if (isObject2(value) && (isObject2(valueInOriginalData) || isObject2(oldValue))) {
|
|
1565
1566
|
markRemovedFieldsAsUndefined(valueInOriginalData, oldValue);
|
|
1566
1567
|
for (const key of Object.keys(value)) {
|
|
1567
|
-
snapshotValueToOriginalData(originalData, path.concat({ target: oldValue || value, property: key }), value[key]);
|
|
1568
|
+
snapshotValueToOriginalData(originalData, path.concat({ target: oldValue || value, property: key }), value[key], equals);
|
|
1568
1569
|
}
|
|
1569
1570
|
} else if (Array.isArray(value) && (valueInOriginalData instanceof ArrayInOriginalData || Array.isArray(oldValue))) {
|
|
1570
1571
|
markRemovedFieldsAsUndefined(valueInOriginalData, oldValue);
|
|
@@ -1572,20 +1573,24 @@ var snapshotValueToOriginalData = (originalData, path, value) => {
|
|
|
1572
1573
|
snapshotValueToOriginalData(
|
|
1573
1574
|
originalData,
|
|
1574
1575
|
path.concat({ target: oldValue || value, property: key.toString() }),
|
|
1575
|
-
value[key]
|
|
1576
|
+
value[key],
|
|
1577
|
+
equals
|
|
1576
1578
|
);
|
|
1577
1579
|
}
|
|
1578
1580
|
} else {
|
|
1581
|
+
const isEqual = equals ? equals(oldValue, value) : oldValue === value;
|
|
1582
|
+
const isEqualToOriginal = equals ? equals(valueInOriginalData, value) : valueInOriginalData === value;
|
|
1579
1583
|
if (!has_default(originalData, pathAsString)) {
|
|
1580
|
-
if (
|
|
1584
|
+
if (!isEqual) {
|
|
1581
1585
|
setOriginalDataValue(originalData, path);
|
|
1582
1586
|
}
|
|
1583
|
-
} else if (
|
|
1587
|
+
} else if (isEqualToOriginal) {
|
|
1584
1588
|
unset_default(originalData, pathAsString);
|
|
1585
1589
|
}
|
|
1586
1590
|
}
|
|
1587
1591
|
};
|
|
1588
|
-
function useTrackedInstance(initialData) {
|
|
1592
|
+
function useTrackedInstance(initialData, options) {
|
|
1593
|
+
const { equals } = options ?? {};
|
|
1589
1594
|
const _originalData = createNestedRef({}, (path) => ({
|
|
1590
1595
|
deleteProperty(target, property) {
|
|
1591
1596
|
const result = Reflect.deleteProperty(target, property);
|
|
@@ -1623,13 +1628,13 @@ function useTrackedInstance(initialData) {
|
|
|
1623
1628
|
triggerChangingArrayItems();
|
|
1624
1629
|
}
|
|
1625
1630
|
} else {
|
|
1626
|
-
snapshotValueToOriginalData(_originalData.value, path, value);
|
|
1631
|
+
snapshotValueToOriginalData(_originalData.value, path, value, equals);
|
|
1627
1632
|
}
|
|
1628
1633
|
return Reflect.set(target, property, cloneDeep(value), receiver);
|
|
1629
1634
|
},
|
|
1630
1635
|
deleteProperty(target, property) {
|
|
1631
1636
|
const path = parentThree.concat({ target, property });
|
|
1632
|
-
snapshotValueToOriginalData(_originalData.value, path, void 0);
|
|
1637
|
+
snapshotValueToOriginalData(_originalData.value, path, void 0, equals);
|
|
1633
1638
|
return Reflect.deleteProperty(target, property);
|
|
1634
1639
|
}
|
|
1635
1640
|
}));
|
|
@@ -1660,7 +1665,7 @@ function useTrackedInstance(initialData) {
|
|
|
1660
1665
|
_originalData.value = {};
|
|
1661
1666
|
};
|
|
1662
1667
|
const reset = () => {
|
|
1663
|
-
const updatedData =
|
|
1668
|
+
const updatedData = cloneDeep(_data.value);
|
|
1664
1669
|
for (const [path, value] of iterateObject(_originalData.value, { includeParent: true })) {
|
|
1665
1670
|
if (value instanceof ArrayInOriginalData) {
|
|
1666
1671
|
set_default(updatedData, path.concat("length"), value.length);
|
|
@@ -1686,7 +1691,11 @@ function useTrackedInstance(initialData) {
|
|
|
1686
1691
|
|
|
1687
1692
|
// src/collection.ts
|
|
1688
1693
|
import { computed as computed2, markRaw, ref } from "vue";
|
|
1689
|
-
var useCollection = (
|
|
1694
|
+
var useCollection = (options) => {
|
|
1695
|
+
const {
|
|
1696
|
+
createItemMeta = () => void 0,
|
|
1697
|
+
...instanceOptions
|
|
1698
|
+
} = options ?? {};
|
|
1690
1699
|
const items = ref([]);
|
|
1691
1700
|
const isDirty = computed2(
|
|
1692
1701
|
() => items.value.some(({
|
|
@@ -1696,7 +1705,7 @@ var useCollection = (createItemMeta = () => void 0) => {
|
|
|
1696
1705
|
}) => instance.isDirty.value || isNew.value || isRemoved.value)
|
|
1697
1706
|
);
|
|
1698
1707
|
const createItem = (item, isNew) => {
|
|
1699
|
-
const instance = useTrackedInstance(item);
|
|
1708
|
+
const instance = useTrackedInstance(item, instanceOptions);
|
|
1700
1709
|
const collectionItem = markRaw({
|
|
1701
1710
|
isRemoved: ref(false),
|
|
1702
1711
|
isNew: ref(isNew),
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { ComputedRef, Raw, Ref } from 'vue';
|
|
2
|
-
import { TrackedInstance } from './tracked-instance';
|
|
2
|
+
import { TrackedInstance, TrackedInstanceOptions } from './tracked-instance';
|
|
3
3
|
export type CollectionItem<Item, Meta = undefined> = Raw<{
|
|
4
4
|
instance: TrackedInstance<Item>;
|
|
5
|
+
/** Arbitrary metadata attached to this item, produced by CollectionOptions.createItemMeta. */
|
|
5
6
|
meta: Meta;
|
|
7
|
+
/** True when the item has been soft-deleted via remove(). */
|
|
6
8
|
isRemoved: Ref<boolean>;
|
|
9
|
+
/** True for items added via add() after the last loadData() call. */
|
|
7
10
|
isNew: Ref<boolean>;
|
|
11
|
+
/** Removes this item from the collection. Shortcut for calling collection.remove(index). */
|
|
8
12
|
remove: (isHardRemoved?: boolean) => void;
|
|
9
13
|
}>;
|
|
10
14
|
export interface Collection<Item, Meta = undefined> {
|
|
11
15
|
items: Ref<CollectionItem<Item, Meta>[]>;
|
|
16
|
+
/** True when any item is modified, newly added, or soft-deleted. */
|
|
12
17
|
isDirty: ComputedRef<boolean>;
|
|
13
|
-
|
|
18
|
+
/** Adds an item to the collection. Inserts at the end by default; pass `index` to insert elsewhere. */
|
|
19
|
+
add: (item: Item, index?: number) => CollectionItem<Item, Meta>;
|
|
20
|
+
/** Soft-deletes an item by index (sets isRemoved). Pass isHardRemove=true to splice immediately. */
|
|
14
21
|
remove: (index: number, isHardRemove?: boolean) => void;
|
|
22
|
+
/** Replaces all items and clears the dirty state. The loaded items become the new baseline. */
|
|
15
23
|
loadData: (items: Item[]) => void;
|
|
24
|
+
/** Reverts all changes: drops new items, restores removed items, resets modified fields. */
|
|
16
25
|
reset: () => void;
|
|
17
26
|
}
|
|
18
|
-
export
|
|
27
|
+
export interface CollectionOptions<Item, Meta = undefined> extends TrackedInstanceOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Factory called when a collection item is created (via loadData or add).
|
|
30
|
+
* Use it to attach arbitrary metadata to each item — UI flags, sub-forms, derived state —
|
|
31
|
+
* that lives alongside the tracked instance but is not part of the tracked data.
|
|
32
|
+
* Receives the newly created TrackedInstance so the meta can reference reactive instance fields.
|
|
33
|
+
*/
|
|
34
|
+
createItemMeta?: (instance: TrackedInstance<Item>) => Meta;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates a reactive collection of TrackedInstance items.
|
|
38
|
+
*
|
|
39
|
+
* Tracks additions, removals, and field-level modifications across all items.
|
|
40
|
+
* Each item is wrapped with markRaw to prevent Vue from making the collection item
|
|
41
|
+
* itself deeply reactive — only instance.data, isRemoved, and isNew carry reactivity.
|
|
42
|
+
*/
|
|
43
|
+
export declare const useCollection: <Item = any, Meta = undefined>(options?: CollectionOptions<Item, Meta>) => Collection<Item, Meta>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { TrackedInstance } from './tracked-instance';
|
|
2
|
-
export type { Collection, CollectionItem } from './collection';
|
|
1
|
+
export type { TrackedInstance, TrackedInstanceOptions } from './tracked-instance';
|
|
2
|
+
export type { Collection, CollectionItem, CollectionOptions } from './collection';
|
|
3
3
|
export { useTrackedInstance } from './tracked-instance';
|
|
4
4
|
export { useCollection } from './collection';
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
2
|
import { DeepPartial } from './utils';
|
|
3
3
|
export interface TrackedInstance<Data> {
|
|
4
|
+
/** Reactive reference to the current (possibly modified) data. */
|
|
4
5
|
data: Ref<Data>;
|
|
6
|
+
/** True when at least one field differs from the value at the last loadData() call. */
|
|
5
7
|
isDirty: Ref<boolean>;
|
|
8
|
+
/** Partial object containing only the fields that have changed since the last loadData(). */
|
|
6
9
|
changedData: Ref<DeepPartial<Data>>;
|
|
10
|
+
/** Replaces the current data and clears the dirty state. The new value becomes the new baseline. */
|
|
7
11
|
loadData: (newData: Data) => void;
|
|
12
|
+
/** Reverts all changes, restoring data to the state at the last loadData() call. */
|
|
8
13
|
reset: () => void;
|
|
9
14
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
15
|
+
export interface TrackedInstanceOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Custom equality function for comparing primitive values.
|
|
18
|
+
* When provided, replaces the default strict equality (===) check.
|
|
19
|
+
* Called only for primitive leaf values (strings, numbers, booleans, null, undefined).
|
|
20
|
+
*
|
|
21
|
+
* @example treat null and empty string as equal
|
|
22
|
+
* equals: (a, b) => (a ?? '') === (b ?? '')
|
|
23
|
+
*/
|
|
24
|
+
equals?: (a: unknown, b: unknown) => boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function useTrackedInstance<Data = any>(value?: undefined, options?: TrackedInstanceOptions): TrackedInstance<Data | undefined>;
|
|
27
|
+
export declare function useTrackedInstance<Data>(value: Data, options?: TrackedInstanceOptions): TrackedInstance<Data>;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1,16 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively makes all properties of T optional.
|
|
3
|
+
* Arrays use element-level DeepPartial rather than making the array itself optional,
|
|
4
|
+
* which allows sparse array diffs (e.g. only index 2 changed).
|
|
5
|
+
*/
|
|
1
6
|
export type DeepPartial<Value> = Value extends object ? Value extends Array<infer ArrayValue> ? Array<DeepPartial<ArrayValue>> : {
|
|
2
7
|
[Property in keyof Value]?: DeepPartial<Value[Property]>;
|
|
3
8
|
} : Value;
|
|
9
|
+
/**
|
|
10
|
+
* Represents one segment in the path from the root proxy to the currently accessed node.
|
|
11
|
+
* Accumulated as Proxy `get` traps are traversed, then passed to `set`/`deleteProperty`
|
|
12
|
+
* handlers so they can reconstruct the full property path for _originalData bookkeeping.
|
|
13
|
+
*/
|
|
4
14
|
export interface NestedProxyPathItem {
|
|
5
15
|
target: Record<string, any>;
|
|
6
16
|
property: string;
|
|
7
17
|
receiver?: Record<string, any>;
|
|
8
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns true only for plain objects — intentionally excludes Array, Date, File, Map,
|
|
21
|
+
* and Set so they are treated as atomic leaf values rather than being traversed.
|
|
22
|
+
*/
|
|
9
23
|
export declare const isObject: (value: unknown) => boolean;
|
|
10
24
|
export declare const isEmpty: (value: object) => boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Depth-first generator that walks an object tree, yielding [path, value] pairs.
|
|
27
|
+
*
|
|
28
|
+
* By default it descends into plain objects (via isObject). Supply `goDeepCondition`
|
|
29
|
+
* to override — e.g. to also descend into ArrayInOriginalData entries.
|
|
30
|
+
* When `includeParent` is true, intermediate nodes are yielded before their children,
|
|
31
|
+
* which is needed for reset() to handle ArrayInOriginalData length restoration.
|
|
32
|
+
*/
|
|
11
33
|
export declare const iterateObject: (source: Record<string, any>, params?: {
|
|
12
34
|
goDeepCondition?: (path: string[], value: any) => boolean;
|
|
13
35
|
includeParent?: boolean;
|
|
14
36
|
}) => Generator<[string[], any], void, any>;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a Vue customRef whose value is a deeply nested Proxy tree.
|
|
39
|
+
*
|
|
40
|
+
* Every nested object/array returned by a `get` is itself wrapped in a new Proxy,
|
|
41
|
+
* so mutations at any depth trigger Vue's reactivity system via the root `track`/`trigger`
|
|
42
|
+
* pair. The `handler` factory receives the full path from the root to the current node,
|
|
43
|
+
* allowing callers to intercept `set` and `deleteProperty` with complete path context.
|
|
44
|
+
*/
|
|
15
45
|
export declare const createNestedRef: <Source extends Record<string, any>>(source: Source, handler: <InnerSource extends Record<string, any>>(path: NestedProxyPathItem[]) => ProxyHandler<InnerSource>) => import("vue").Ref<Source, Source>;
|
|
46
|
+
/**
|
|
47
|
+
* Deep-clones a value while preserving special types:
|
|
48
|
+
* - Date → new Date instance with the same timestamp
|
|
49
|
+
* - File → same reference (Files are immutable browser objects and cannot be meaningfully cloned)
|
|
50
|
+
* All other types delegate to lodash cloneDeepWith for recursive cloning.
|
|
51
|
+
*/
|
|
16
52
|
export declare const cloneDeep: (inputValue: any) => any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tracked-instance",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Build large forms and track all changes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
},
|
|
11
11
|
"main": "./dist/index.mjs",
|
|
12
12
|
"types": "./dist/types/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"types": "./dist/types/index.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
13
19
|
"files": [
|
|
14
20
|
"dist"
|
|
15
21
|
],
|