@nemigo/svelte 2.10.0 → 2.10.2
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/dist/tree.d.ts +6 -0
- package/dist/tree.js +74 -21
- package/package.json +17 -1
package/dist/tree.d.ts
CHANGED
|
@@ -34,8 +34,14 @@ export declare abstract class SvelteTree<R extends TreeRecord, Item extends Tree
|
|
|
34
34
|
items: ISvelteState<Item[]>;
|
|
35
35
|
map: Map<string, Item>;
|
|
36
36
|
size: ISvelteState<number>;
|
|
37
|
+
root_parent_id: string | null;
|
|
38
|
+
constructor(root_parent_id?: string | null);
|
|
37
39
|
abstract toTreeItem(record: R): Item;
|
|
38
40
|
abstract sort(a: Item, b: Item): number;
|
|
41
|
+
/** true, если запись относится к нашему поддереву (корень или потомок) */
|
|
42
|
+
__inScope(record: R): boolean;
|
|
43
|
+
/** является ли этот parent_id "корнем" нашего поддерева */
|
|
44
|
+
__isRootParent(parent_id: string | null): boolean;
|
|
39
45
|
hooks: {
|
|
40
46
|
create: (record: R) => void;
|
|
41
47
|
update: (record: R, mods: any) => void;
|
package/dist/tree.js
CHANGED
|
@@ -5,8 +5,27 @@ export class SvelteTree extends Emitter {
|
|
|
5
5
|
items = createSvelteRawState([]);
|
|
6
6
|
map = new Map();
|
|
7
7
|
size = createSvelteRawState(0);
|
|
8
|
+
root_parent_id;
|
|
9
|
+
constructor(root_parent_id = null) {
|
|
10
|
+
super();
|
|
11
|
+
this.root_parent_id = root_parent_id;
|
|
12
|
+
}
|
|
13
|
+
/** true, если запись относится к нашему поддереву (корень или потомок) */
|
|
14
|
+
__inScope(record) {
|
|
15
|
+
// корневой уровень нашего поддерева
|
|
16
|
+
if (record.parent_id === this.root_parent_id)
|
|
17
|
+
return true;
|
|
18
|
+
// потомок — значит его родитель уже в map
|
|
19
|
+
return record.parent_id !== null && this.map.has(record.parent_id);
|
|
20
|
+
}
|
|
21
|
+
/** является ли этот parent_id "корнем" нашего поддерева */
|
|
22
|
+
__isRootParent(parent_id) {
|
|
23
|
+
return parent_id === this.root_parent_id;
|
|
24
|
+
}
|
|
8
25
|
hooks = {
|
|
9
26
|
create: (record) => {
|
|
27
|
+
if (!this.__inScope(record))
|
|
28
|
+
return;
|
|
10
29
|
const item = this.toTreeItem(record);
|
|
11
30
|
this.dispatch("before-create", item);
|
|
12
31
|
this.map.set(record.id, item);
|
|
@@ -18,14 +37,26 @@ export class SvelteTree extends Emitter {
|
|
|
18
37
|
},
|
|
19
38
|
update: (record, mods) => {
|
|
20
39
|
const item = this.map.get(record.id);
|
|
21
|
-
|
|
22
|
-
return;
|
|
23
|
-
const preview = { ...item.record.signal, ...mods };
|
|
24
|
-
if (isDataEqual(record, preview))
|
|
25
|
-
return;
|
|
40
|
+
const preview = { ...(item?.record.signal ?? record), ...mods };
|
|
26
41
|
const prev_parent_id = record.parent_id;
|
|
27
42
|
const mod_parent_id = mods.parent_id;
|
|
28
43
|
const isParentChange = mod_parent_id !== undefined && mod_parent_id !== prev_parent_id;
|
|
44
|
+
// --- элемент ещё не в поддереве ---
|
|
45
|
+
if (!item) {
|
|
46
|
+
// если после апдейта он попадает в наше поддерево — создаём
|
|
47
|
+
if (this.__inScope(preview)) {
|
|
48
|
+
this.hooks.create(preview);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// --- элемент уже в поддереве ---
|
|
53
|
+
// если апдейт выталкивает его из поддерева (смена parent_id на "чужой") — удаляем
|
|
54
|
+
if (isParentChange && !this.__inScope(preview)) {
|
|
55
|
+
this.hooks.delete(record.id);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (isDataEqual(record, preview))
|
|
59
|
+
return;
|
|
29
60
|
if (isParentChange) {
|
|
30
61
|
this.dispatch("before-parent-update", {
|
|
31
62
|
prev: prev_parent_id,
|
|
@@ -77,15 +108,15 @@ export class SvelteTree extends Emitter {
|
|
|
77
108
|
},
|
|
78
109
|
};
|
|
79
110
|
__sort(items) {
|
|
80
|
-
items.signal = items.signal.toSorted((a, b) => this.sort(a, b));
|
|
111
|
+
items.signal = items.signal.toSorted((a, b) => this.sort(a, b));
|
|
81
112
|
}
|
|
82
113
|
__push(items, item) {
|
|
83
114
|
items.signal.push(item);
|
|
84
|
-
this.__sort(items);
|
|
115
|
+
this.__sort(items);
|
|
85
116
|
}
|
|
86
117
|
__splice(items, idx) {
|
|
87
118
|
items.signal.splice(idx, 1);
|
|
88
|
-
items.signal = items.signal.slice();
|
|
119
|
+
items.signal = items.signal.slice();
|
|
89
120
|
}
|
|
90
121
|
__delete(items, item) {
|
|
91
122
|
const idx = items.signal.indexOf(item);
|
|
@@ -94,14 +125,14 @@ export class SvelteTree extends Emitter {
|
|
|
94
125
|
}
|
|
95
126
|
__parent(item, call) {
|
|
96
127
|
const parent_id = item.record.signal.parent_id;
|
|
97
|
-
if (parent_id) {
|
|
128
|
+
if (this.__isRootParent(parent_id)) {
|
|
129
|
+
call(this.items);
|
|
130
|
+
}
|
|
131
|
+
else if (parent_id) {
|
|
98
132
|
const parent = this.map.get(parent_id);
|
|
99
133
|
if (parent)
|
|
100
134
|
call(parent.child);
|
|
101
135
|
}
|
|
102
|
-
else {
|
|
103
|
-
call(this.items);
|
|
104
|
-
}
|
|
105
136
|
}
|
|
106
137
|
clear() {
|
|
107
138
|
this.items.signal = [];
|
|
@@ -109,20 +140,42 @@ export class SvelteTree extends Emitter {
|
|
|
109
140
|
this.size.signal = 0;
|
|
110
141
|
}
|
|
111
142
|
__build(records) {
|
|
112
|
-
//
|
|
143
|
+
// 1. индексируем все записи, чтобы корректно определять принадлежность к поддереву
|
|
144
|
+
const byId = new Map();
|
|
113
145
|
for (const r of records)
|
|
146
|
+
byId.set(r.id, r);
|
|
147
|
+
// определяем, входит ли запись в наше поддерево (поднимаемся до корня)
|
|
148
|
+
const inScope = (r) => {
|
|
149
|
+
let cur = r;
|
|
150
|
+
const seen = new Set();
|
|
151
|
+
while (cur) {
|
|
152
|
+
if (cur.parent_id === this.root_parent_id)
|
|
153
|
+
return true;
|
|
154
|
+
if (cur.parent_id === null)
|
|
155
|
+
return false;
|
|
156
|
+
if (seen.has(cur.id))
|
|
157
|
+
return false; // защита от циклов
|
|
158
|
+
seen.add(cur.id);
|
|
159
|
+
cur = byId.get(cur.parent_id);
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
};
|
|
163
|
+
const scoped = records.filter(inScope);
|
|
164
|
+
// 2. создаём элементы
|
|
165
|
+
for (const r of scoped)
|
|
114
166
|
this.map.set(r.id, this.toTreeItem(r));
|
|
115
|
-
//
|
|
116
|
-
for (const r of
|
|
167
|
+
// 3. строим дерево
|
|
168
|
+
for (const r of scoped) {
|
|
117
169
|
const item = this.map.get(r.id);
|
|
118
|
-
|
|
119
|
-
if (parent_id)
|
|
120
|
-
this.map.get(parent_id)?.child.signal.push(item);
|
|
121
|
-
else
|
|
170
|
+
if (this.__isRootParent(r.parent_id)) {
|
|
122
171
|
this.items.signal.push(item);
|
|
172
|
+
}
|
|
173
|
+
else if (r.parent_id) {
|
|
174
|
+
this.map.get(r.parent_id)?.child.signal.push(item);
|
|
175
|
+
}
|
|
123
176
|
}
|
|
124
|
-
//
|
|
125
|
-
for (const r of
|
|
177
|
+
// 4. сортируем
|
|
178
|
+
for (const r of scoped) {
|
|
126
179
|
const item = this.map.get(r.id);
|
|
127
180
|
this.__sort(item.child);
|
|
128
181
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nemigo/svelte",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": {
|
|
@@ -26,14 +26,30 @@
|
|
|
26
26
|
"types": "./dist/kit/navigation.d.ts",
|
|
27
27
|
"svelte": "./dist/kit/navigation.js"
|
|
28
28
|
},
|
|
29
|
+
"./heap": {
|
|
30
|
+
"types": "./dist/heap.d.ts",
|
|
31
|
+
"svelte": "./dist/heap.js"
|
|
32
|
+
},
|
|
33
|
+
"./list": {
|
|
34
|
+
"types": "./dist/list.d.ts",
|
|
35
|
+
"svelte": "./dist/list.js"
|
|
36
|
+
},
|
|
29
37
|
"./loader": {
|
|
30
38
|
"types": "./dist/loader.d.ts",
|
|
31
39
|
"svelte": "./dist/loader.js"
|
|
32
40
|
},
|
|
41
|
+
"./record": {
|
|
42
|
+
"types": "./dist/record.d.ts",
|
|
43
|
+
"svelte": "./dist/record.js"
|
|
44
|
+
},
|
|
33
45
|
"./transitions": {
|
|
34
46
|
"types": "./dist/transitions.d.ts",
|
|
35
47
|
"default": "./dist/transitions.js"
|
|
36
48
|
},
|
|
49
|
+
"./tree": {
|
|
50
|
+
"types": "./dist/tree.d.ts",
|
|
51
|
+
"default": "./dist/tree.js"
|
|
52
|
+
},
|
|
37
53
|
"./types": {
|
|
38
54
|
"types": "./dist/types.d.ts",
|
|
39
55
|
"default": "./dist/types.js"
|