@gtkx/components 1.0.0 → 1.2.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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/adw/toast.d.ts.map +1 -1
  3. package/dist/adw/toast.js +6 -2
  4. package/dist/adw/toast.js.map +1 -1
  5. package/dist/internal/cells.js +1 -1
  6. package/dist/internal/cells.js.map +1 -1
  7. package/dist/internal/collection-index.d.ts +4 -3
  8. package/dist/internal/collection-index.d.ts.map +1 -1
  9. package/dist/internal/collection-index.js +50 -33
  10. package/dist/internal/collection-index.js.map +1 -1
  11. package/dist/internal/collection-model.d.ts +3 -4
  12. package/dist/internal/collection-model.d.ts.map +1 -1
  13. package/dist/internal/collection-model.js +110 -74
  14. package/dist/internal/collection-model.js.map +1 -1
  15. package/dist/internal/collection.d.ts +2 -1
  16. package/dist/internal/collection.d.ts.map +1 -1
  17. package/dist/internal/collection.js +7 -6
  18. package/dist/internal/collection.js.map +1 -1
  19. package/dist/internal/expansion.d.ts.map +1 -1
  20. package/dist/internal/expansion.js +11 -19
  21. package/dist/internal/expansion.js.map +1 -1
  22. package/dist/internal/tree-expansion.d.ts +1 -2
  23. package/dist/internal/tree-expansion.d.ts.map +1 -1
  24. package/dist/internal/tree-expansion.js +12 -8
  25. package/dist/internal/tree-expansion.js.map +1 -1
  26. package/dist/internal/tree-order.d.ts +3 -4
  27. package/dist/internal/tree-order.d.ts.map +1 -1
  28. package/dist/internal/tree-order.js +61 -23
  29. package/dist/internal/tree-order.js.map +1 -1
  30. package/dist/types.d.ts +3 -2
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js.map +1 -1
  33. package/package.json +17 -9
  34. package/src/adw/toast.tsx +6 -2
  35. package/src/internal/cells.tsx +1 -1
  36. package/src/internal/collection-index.ts +63 -39
  37. package/src/internal/collection-model.ts +148 -85
  38. package/src/internal/collection.ts +10 -8
  39. package/src/internal/expansion.ts +12 -24
  40. package/src/internal/tree-expansion.ts +14 -9
  41. package/src/internal/tree-order.ts +98 -28
  42. package/src/types.ts +3 -2
@@ -2,9 +2,9 @@ import * as Gio from "@gtkx/gi/gio";
2
2
  import * as GObject from "@gtkx/gi/gobject";
3
3
  import * as Gtk from "@gtkx/gi/gtk";
4
4
  import { registerClass } from "@gtkx/runtime";
5
- import { createCollectionIndex } from "./collection-index.js";
5
+ import { createCollectionIndex, emptyLevel } from "./collection-index.js";
6
6
  import { encodePart } from "./keys.js";
7
- import { adoptIndex, createTreeExpansion, pruneSlots, resetExpansion } from "./tree-expansion.js";
7
+ import { adoptIndex, createTreeExpansion, pruneSlots } from "./tree-expansion.js";
8
8
  const STORE_CLASS_KEY = Symbol.for("gtkx.components.lazy-level-store");
9
9
  const SLOTS_KEY = Symbol.for("gtkx.components.lazy-level-store.slots");
10
10
  const EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);
@@ -37,59 +37,38 @@ function slotRefFor(value) {
37
37
  return ref === undefined || ref.slot === -1 ? null : ref;
38
38
  }
39
39
  function slotPathAt(store, slot) {
40
- return store.path + encodePart(String(slot));
40
+ return store.level.path + encodePart(String(slot));
41
41
  }
42
- function newLevelStore(path) {
43
- const store = new (registeredStoreClass())();
44
- store.path = path;
45
- return store;
46
- }
47
- function buildChildStore(context, path) {
48
- const level = context.index.children.get(path);
49
- if (level === undefined) {
50
- return null;
42
+ function growStore(store) {
43
+ for (let slot = store.refs.length; slot < store.level.items.length; slot++) {
44
+ store.refs.push({ store, slot });
45
+ store.objects.push(null);
46
+ store.childStores.push(null);
51
47
  }
52
- const store = newLevelStore(path);
53
- growStore(context, store, level);
54
- return store;
55
- }
56
- function pushSlot(context, store, level, slot) {
57
- const canExpand = level.expandableFlags[slot] ?? false;
58
- store.refs.push({ store, slot });
59
- store.objects.push(null);
60
- store.expandableFlags.push(canExpand);
61
- store.childStores.push(canExpand ? buildChildStore(context, slotPathAt(store, slot)) : null);
62
48
  }
63
- function growStore(context, store, level) {
64
- for (let slot = store.refs.length; slot < level.items.length; slot++) {
65
- pushSlot(context, store, level, slot);
66
- }
67
- }
68
- function flipSlot(context, store, slot) {
69
- const canExpand = !(store.expandableFlags[slot] ?? false);
70
- store.expandableFlags[slot] = canExpand;
71
- store.childStores[slot] = canExpand ? buildChildStore(context, slotPathAt(store, slot)) : null;
49
+ function newLevelStore(level) {
50
+ const store = new (registeredStoreClass())();
51
+ store.level = level;
52
+ growStore(store);
53
+ return store;
72
54
  }
73
- function collectFlips(store, level) {
74
- const overlap = Math.min(store.refs.length, level.items.length);
55
+ function collectFlips(previous, next, overlap) {
75
56
  const flipped = new Set();
76
57
  for (let slot = 0; slot < overlap; slot++) {
77
- if ((store.expandableFlags[slot] ?? false) !== (level.expandableFlags[slot] ?? false)) {
58
+ if ((previous.expandableFlags[slot] ?? false) !== (next.expandableFlags[slot] ?? false)) {
78
59
  flipped.add(slot);
79
60
  }
80
61
  }
81
62
  return flipped;
82
63
  }
83
- function syncOverlap(context, store, level) {
84
- const flipped = collectFlips(store, level);
64
+ function pruneFlips(context, store, flipped) {
85
65
  if (flipped.size === 0) {
86
- return flipped;
66
+ return;
87
67
  }
88
- pruneSlots(context.expansion, store.path, (slot) => flipped.has(slot));
68
+ pruneSlots(context.expansion, store.level.path, (slot) => flipped.has(slot));
89
69
  for (const slot of flipped) {
90
- flipSlot(context, store, slot);
70
+ store.childStores[slot] = null;
91
71
  }
92
- return flipped;
93
72
  }
94
73
  function detachRefs(store, nextLength) {
95
74
  for (let slot = nextLength; slot < store.refs.length; slot++) {
@@ -104,11 +83,10 @@ function shrinkStore(context, store, nextLength) {
104
83
  return;
105
84
  }
106
85
  detachRefs(store, nextLength);
107
- pruneSlots(context.expansion, store.path, (slot) => slot >= nextLength);
86
+ pruneSlots(context.expansion, store.level.path, (slot) => slot >= nextLength);
108
87
  store.refs.length = nextLength;
109
88
  store.objects.length = nextLength;
110
89
  store.childStores.length = nextLength;
111
- store.expandableFlags.length = nextLength;
112
90
  }
113
91
  function emitTailSplice(store, previousLength, nextLength) {
114
92
  if (nextLength < previousLength) {
@@ -139,48 +117,108 @@ function emitFlips(store, flipped) {
139
117
  store.itemsChanged(run.start, run.length, run.length);
140
118
  }
141
119
  }
142
- function stepChildStore(context, store, slot, flipped) {
143
- const child = store.childStores[slot];
144
- if (child == null || flipped.has(slot)) {
145
- return;
120
+ function childSync(context, store, slot, flipped) {
121
+ const child = store.childStores[slot] ?? null;
122
+ if (child === null || flipped.has(slot)) {
123
+ return undefined;
146
124
  }
147
- const level = context.index.children.get(slotPathAt(store, slot));
148
- if (level !== undefined) {
149
- syncLevel(context, child, level);
125
+ const level = context.index.childLevel(store.level, slot);
126
+ return level === undefined ? undefined : { store: child, level };
127
+ }
128
+ function childSyncs(context, store, overlap, flipped) {
129
+ const syncs = [];
130
+ for (let slot = 0; slot < overlap; slot++) {
131
+ const sync = childSync(context, store, slot, flipped);
132
+ if (sync !== undefined) {
133
+ syncs.push(sync);
134
+ }
150
135
  }
136
+ return syncs;
151
137
  }
152
- function syncLevel(context, store, level) {
138
+ function syncEntry(context, entry) {
139
+ const { store, level } = entry;
153
140
  const previousLength = store.refs.length;
154
141
  const overlap = Math.min(previousLength, level.items.length);
155
- const flipped = syncOverlap(context, store, level);
142
+ const flipped = collectFlips(store.level, level, overlap);
143
+ store.level = level;
144
+ pruneFlips(context, store, flipped);
156
145
  shrinkStore(context, store, level.items.length);
157
- growStore(context, store, level);
146
+ growStore(store);
158
147
  emitTailSplice(store, previousLength, level.items.length);
159
148
  emitFlips(store, flipped);
160
- for (let slot = 0; slot < overlap; slot++) {
161
- stepChildStore(context, store, slot, flipped);
149
+ return childSyncs(context, store, overlap, flipped);
150
+ }
151
+ function pushSyncs(pending, syncs) {
152
+ for (const sync of syncs) {
153
+ pending.push(sync);
154
+ }
155
+ }
156
+ function syncLevel(context, store, level) {
157
+ const pending = [{ store, level }];
158
+ while (pending.length > 0) {
159
+ const entry = pending.pop();
160
+ if (entry !== undefined) {
161
+ pushSyncs(pending, syncEntry(context, entry).toReversed());
162
+ }
163
+ }
164
+ }
165
+ function ensureChildStore(index, store, slot) {
166
+ const existing = store.childStores[slot] ?? null;
167
+ if (existing !== null || !(store.level.expandableFlags[slot] ?? false)) {
168
+ return existing;
169
+ }
170
+ const level = index.childLevel(store.level, slot);
171
+ if (level === undefined) {
172
+ return null;
162
173
  }
174
+ const created = newLevelStore(level);
175
+ store.childStores[slot] = created;
176
+ return created;
163
177
  }
164
- function childStoreFor(object) {
178
+ function childStoreFor(state, object) {
165
179
  const ref = slotRefFor(object);
166
180
  if (ref === null) {
167
181
  return null;
168
182
  }
169
- return ref.store.childStores[ref.slot] ?? null;
183
+ return ensureChildStore(state.index, ref.store, ref.slot);
184
+ }
185
+ function treeFor(state, store) {
186
+ return (state.trees.get(store) ?? Gtk.TreeListModel.new(store, false, false, (object) => childStoreFor(state, object)));
170
187
  }
171
- function ensureTree(state, first) {
172
- if (state.tree === null || state.treeRoot !== first) {
173
- state.tree = Gtk.TreeListModel.new(first, false, false, (object) => childStoreFor(object));
174
- state.treeRoot = first;
188
+ function nextTrees(state, index) {
189
+ if (!index.isTree) {
190
+ return new Map();
175
191
  }
176
- return state.tree;
192
+ return new Map(state.groupStores.map((store) => [store, treeFor(state, store)]));
193
+ }
194
+ function pruneRebuiltLevels(state, next) {
195
+ const stores = new Set([...state.trees.keys(), ...next.keys()]);
196
+ for (const store of stores) {
197
+ if (state.trees.get(store) !== next.get(store)) {
198
+ pruneSlots(state.expansion, store.level.path, () => true);
199
+ }
200
+ }
201
+ }
202
+ function adoptTrees(state, index) {
203
+ const next = nextTrees(state, index);
204
+ pruneRebuiltLevels(state, next);
205
+ state.trees = next;
206
+ state.treeModels = next.values().toArray();
177
207
  }
178
208
  function desiredRootModels(state, index) {
179
- const [first] = state.groupStores;
180
- if (first !== undefined && index.isTree) {
181
- return [ensureTree(state, first)];
209
+ adoptTrees(state, index);
210
+ return index.isTree ? [...state.treeModels] : [...state.groupStores];
211
+ }
212
+ function rowAt(state, position) {
213
+ let offset = position;
214
+ for (const tree of state.treeModels) {
215
+ const count = tree.getNItems();
216
+ if (offset < count) {
217
+ return tree.getRow(offset);
218
+ }
219
+ offset -= count;
182
220
  }
183
- return [...state.groupStores];
221
+ return null;
184
222
  }
185
223
  function hasSameModels(previous, next) {
186
224
  return previous.length === next.length && next.every((model, index) => previous[index] === model);
@@ -192,15 +230,12 @@ function syncRoot(state, index) {
192
230
  }
193
231
  state.root.splice(0, state.rootModels.length, next);
194
232
  state.rootModels = next;
195
- resetExpansion(state.expansion);
196
233
  }
197
234
  function adjustGroupStores(state, context) {
198
235
  const { groups } = context.index;
199
236
  state.groupStores.length = Math.min(state.groupStores.length, groups.length);
200
237
  for (const level of groups.slice(state.groupStores.length)) {
201
- const store = newLevelStore(level.path);
202
- growStore(context, store, level);
203
- state.groupStores.push(store);
238
+ state.groupStores.push(newLevelStore(level));
204
239
  }
205
240
  }
206
241
  function stepGroupStores(state, context, surviving) {
@@ -214,6 +249,7 @@ function stepGroupStores(state, context, surviving) {
214
249
  function syncModel(state, index) {
215
250
  const context = { index, expansion: state.expansion };
216
251
  const surviving = Math.min(state.groupStores.length, index.groups.length);
252
+ state.index = index;
217
253
  state.expansion.isSyncing = true;
218
254
  try {
219
255
  adjustGroupStores(state, context);
@@ -233,25 +269,25 @@ function createCollectionModel() {
233
269
  rootModels: [],
234
270
  model: Gtk.FlattenListModel.new(root),
235
271
  groupStores: [],
236
- tree: null,
237
- treeRoot: null,
272
+ trees: new Map(),
273
+ treeModels: [],
238
274
  expansion: createTreeExpansion(EMPTY_INDEX),
275
+ index: EMPTY_INDEX,
239
276
  };
240
277
  return {
241
278
  model: state.model,
242
279
  expansion: state.expansion,
243
- treeModel: () => state.tree,
280
+ rowAt: (position) => rowAt(state, position),
244
281
  sync: (index) => {
245
282
  syncModel(state, index);
246
283
  },
247
284
  };
248
285
  }
249
286
  class LazyLevelStore extends GObject.Object {
250
- path = "";
287
+ level = emptyLevel();
251
288
  refs = [];
252
289
  objects = [];
253
290
  childStores = [];
254
- expandableFlags = [];
255
291
  createItem(position, ref) {
256
292
  const created = Gtk.StringObject.new("");
257
293
  this.objects[position] = created;
@@ -1 +1 @@
1
- {"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { registerClass } from \"@gtkx/runtime\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport { createCollectionIndex } from \"./collection-index.js\";\nimport { encodePart } from \"./keys.js\";\nimport { adoptIndex, createTreeExpansion, pruneSlots, resetExpansion } from \"./tree-expansion.js\";\n\ntype LevelStore = Gio.ListModel & LazyLevelStore;\n\ntype SlotRef = {\n store: LevelStore;\n slot: number;\n};\n\ntype SyncContext = {\n index: CollectionIndex;\n expansion: TreeExpansion;\n};\n\ntype SlotRun = {\n start: number;\n length: number;\n};\n\ntype ModelState = {\n root: Gio.ListStore;\n rootModels: GObject.Object[];\n model: Gtk.FlattenListModel;\n groupStores: LevelStore[];\n tree: Gtk.TreeListModel | null;\n treeRoot: LevelStore | null;\n expansion: TreeExpansion;\n};\n\ntype CollectionModel = {\n model: Gtk.FlattenListModel;\n expansion: TreeExpansion;\n treeModel: () => Gtk.TreeListModel | null;\n sync: (index: CollectionIndex) => void;\n};\n\nconst STORE_CLASS_KEY = Symbol.for(\"gtkx.components.lazy-level-store\");\nconst SLOTS_KEY = Symbol.for(\"gtkx.components.lazy-level-store.slots\");\nconst EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);\nconst SLOTS = sharedSlots();\n\nconst newRootStore = (): Gio.ListStore => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });\n\nfunction sharedSlots(): WeakMap<GObject.Object, SlotRef> {\n const cached: unknown = Reflect.get(globalThis, SLOTS_KEY);\n\n if (cached instanceof WeakMap) {\n return cached as WeakMap<GObject.Object, SlotRef>;\n }\n\n const created: WeakMap<GObject.Object, SlotRef> = new WeakMap();\n Reflect.set(globalThis, SLOTS_KEY, created);\n\n return created;\n}\n\nfunction registeredStoreClass(): typeof LazyLevelStore {\n const cached: unknown = Reflect.get(globalThis, STORE_CLASS_KEY);\n\n if (typeof cached === \"function\") {\n return cached as typeof LazyLevelStore;\n }\n\n registerClass(LazyLevelStore, { typeName: \"GtkxLazyLevelStore\", implements: [Gio.ListModel] });\n Reflect.set(globalThis, STORE_CLASS_KEY, LazyLevelStore);\n\n return LazyLevelStore;\n}\n\nfunction slotRefFor(value: GObject.Object | null): SlotRef | null {\n const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;\n\n if (item === null) {\n return null;\n }\n\n const ref = SLOTS.get(item);\n\n return ref === undefined || ref.slot === -1 ? null : ref;\n}\n\nfunction slotPathAt(store: LevelStore, slot: number): string {\n return store.path + encodePart(String(slot));\n}\n\nfunction newLevelStore(path: string): LevelStore {\n const store = new (registeredStoreClass())() as LevelStore;\n store.path = path;\n\n return store;\n}\n\nfunction buildChildStore(context: SyncContext, path: string): LevelStore | null {\n const level = context.index.children.get(path);\n\n if (level === undefined) {\n return null;\n }\n\n const store = newLevelStore(path);\n growStore(context, store, level);\n\n return store;\n}\n\nfunction pushSlot(context: SyncContext, store: LevelStore, level: Level, slot: number): void {\n const canExpand = level.expandableFlags[slot] ?? false;\n store.refs.push({ store, slot });\n store.objects.push(null);\n store.expandableFlags.push(canExpand);\n store.childStores.push(canExpand ? buildChildStore(context, slotPathAt(store, slot)) : null);\n}\n\nfunction growStore(context: SyncContext, store: LevelStore, level: Level): void {\n for (let slot = store.refs.length; slot < level.items.length; slot++) {\n pushSlot(context, store, level, slot);\n }\n}\n\nfunction flipSlot(context: SyncContext, store: LevelStore, slot: number): void {\n const canExpand = !(store.expandableFlags[slot] ?? false);\n store.expandableFlags[slot] = canExpand;\n store.childStores[slot] = canExpand ? buildChildStore(context, slotPathAt(store, slot)) : null;\n}\n\nfunction collectFlips(store: LevelStore, level: Level): Set<number> {\n const overlap = Math.min(store.refs.length, level.items.length);\n const flipped: Set<number> = new Set();\n\n for (let slot = 0; slot < overlap; slot++) {\n if ((store.expandableFlags[slot] ?? false) !== (level.expandableFlags[slot] ?? false)) {\n flipped.add(slot);\n }\n }\n\n return flipped;\n}\n\nfunction syncOverlap(context: SyncContext, store: LevelStore, level: Level): Set<number> {\n const flipped = collectFlips(store, level);\n\n if (flipped.size === 0) {\n return flipped;\n }\n\n pruneSlots(context.expansion, store.path, (slot) => flipped.has(slot));\n\n for (const slot of flipped) {\n flipSlot(context, store, slot);\n }\n\n return flipped;\n}\n\nfunction detachRefs(store: LevelStore, nextLength: number): void {\n for (let slot = nextLength; slot < store.refs.length; slot++) {\n const ref = store.refs[slot];\n\n if (ref !== undefined) {\n ref.slot = -1;\n }\n }\n}\n\nfunction shrinkStore(context: SyncContext, store: LevelStore, nextLength: number): void {\n if (store.refs.length <= nextLength) {\n return;\n }\n\n detachRefs(store, nextLength);\n pruneSlots(context.expansion, store.path, (slot) => slot >= nextLength);\n store.refs.length = nextLength;\n store.objects.length = nextLength;\n store.childStores.length = nextLength;\n store.expandableFlags.length = nextLength;\n}\n\nfunction emitTailSplice(store: LevelStore, previousLength: number, nextLength: number): void {\n if (nextLength < previousLength) {\n store.itemsChanged(nextLength, previousLength - nextLength, 0);\n\n return;\n }\n\n if (nextLength > previousLength) {\n store.itemsChanged(previousLength, 0, nextLength - previousLength);\n }\n}\n\nfunction extendRuns(runs: SlotRun[], slot: number): void {\n const last = runs.at(-1);\n\n if (last !== undefined && last.start + last.length === slot) {\n last.length += 1;\n\n return;\n }\n\n runs.push({ start: slot, length: 1 });\n}\n\nfunction collectFlipRuns(flipped: Set<number>): SlotRun[] {\n const runs: SlotRun[] = [];\n\n for (const slot of flipped) {\n extendRuns(runs, slot);\n }\n\n return runs;\n}\n\nfunction emitFlips(store: LevelStore, flipped: Set<number>): void {\n for (const run of collectFlipRuns(flipped)) {\n store.itemsChanged(run.start, run.length, run.length);\n }\n}\n\nfunction stepChildStore(context: SyncContext, store: LevelStore, slot: number, flipped: Set<number>): void {\n const child = store.childStores[slot];\n\n if (child == null || flipped.has(slot)) {\n return;\n }\n\n const level = context.index.children.get(slotPathAt(store, slot));\n\n if (level !== undefined) {\n syncLevel(context, child, level);\n }\n}\n\nfunction syncLevel(context: SyncContext, store: LevelStore, level: Level): void {\n const previousLength = store.refs.length;\n const overlap = Math.min(previousLength, level.items.length);\n const flipped = syncOverlap(context, store, level);\n shrinkStore(context, store, level.items.length);\n growStore(context, store, level);\n emitTailSplice(store, previousLength, level.items.length);\n emitFlips(store, flipped);\n\n for (let slot = 0; slot < overlap; slot++) {\n stepChildStore(context, store, slot, flipped);\n }\n}\n\nfunction childStoreFor(object: GObject.Object): Gio.ListModel | null {\n const ref = slotRefFor(object);\n\n if (ref === null) {\n return null;\n }\n\n return ref.store.childStores[ref.slot] ?? null;\n}\n\nfunction ensureTree(state: ModelState, first: LevelStore): Gtk.TreeListModel {\n if (state.tree === null || state.treeRoot !== first) {\n state.tree = Gtk.TreeListModel.new(first, false, false, (object) => childStoreFor(object));\n state.treeRoot = first;\n }\n\n return state.tree;\n}\n\nfunction desiredRootModels(state: ModelState, index: CollectionIndex): GObject.Object[] {\n const [first] = state.groupStores;\n\n if (first !== undefined && index.isTree) {\n return [ensureTree(state, first)];\n }\n\n return [...state.groupStores];\n}\n\nfunction hasSameModels(previous: GObject.Object[], next: GObject.Object[]): boolean {\n return previous.length === next.length && next.every((model, index) => previous[index] === model);\n}\n\nfunction syncRoot(state: ModelState, index: CollectionIndex): void {\n const next = desiredRootModels(state, index);\n\n if (hasSameModels(state.rootModels, next)) {\n return;\n }\n\n state.root.splice(0, state.rootModels.length, next);\n state.rootModels = next;\n resetExpansion(state.expansion);\n}\n\nfunction adjustGroupStores(state: ModelState, context: SyncContext): void {\n const { groups } = context.index;\n state.groupStores.length = Math.min(state.groupStores.length, groups.length);\n\n for (const level of groups.slice(state.groupStores.length)) {\n const store = newLevelStore(level.path);\n growStore(context, store, level);\n state.groupStores.push(store);\n }\n}\n\nfunction stepGroupStores(state: ModelState, context: SyncContext, surviving: number): void {\n for (const [group, level] of context.index.groups.entries()) {\n const store = state.groupStores[group];\n\n if (store !== undefined && group < surviving) {\n syncLevel(context, store, level);\n }\n }\n}\n\nfunction syncModel(state: ModelState, index: CollectionIndex): void {\n const context: SyncContext = { index, expansion: state.expansion };\n const surviving = Math.min(state.groupStores.length, index.groups.length);\n state.expansion.isSyncing = true;\n\n try {\n adjustGroupStores(state, context);\n syncRoot(state, index);\n stepGroupStores(state, context, surviving);\n } finally {\n state.expansion.isSyncing = false;\n }\n\n adoptIndex(state.expansion, index);\n}\n\nfunction createCollectionModel(): CollectionModel {\n registeredStoreClass();\n const root = newRootStore();\n\n const state: ModelState = {\n root,\n rootModels: [],\n model: Gtk.FlattenListModel.new(root),\n groupStores: [],\n tree: null,\n treeRoot: null,\n expansion: createTreeExpansion(EMPTY_INDEX),\n };\n\n return {\n model: state.model,\n expansion: state.expansion,\n treeModel: () => state.tree,\n sync: (index) => {\n syncModel(state, index);\n },\n };\n}\n\nclass LazyLevelStore extends GObject.Object implements Gio.ListModelImpl {\n declare itemsChanged: Gio.ListModel[\"itemsChanged\"];\n path = \"\";\n refs: SlotRef[] = [];\n objects: (Gtk.StringObject | null)[] = [];\n childStores: (LevelStore | null)[] = [];\n expandableFlags: boolean[] = [];\n\n private createItem(position: number, ref: SlotRef): Gtk.StringObject {\n const created = Gtk.StringObject.new(\"\");\n this.objects[position] = created;\n SLOTS.set(created, ref);\n\n return created;\n }\n\n vfuncGetItemType(): bigint {\n return GObject.TYPE_OBJECT;\n }\n\n vfuncGetNItems(): number {\n return this.refs.length;\n }\n\n vfuncGetItem(position: number): GObject.Object | null {\n const ref = this.refs[position];\n\n if (ref === undefined) {\n return null;\n }\n\n return this.objects[position] ?? this.createItem(position, ref);\n }\n}\n\nexport { createCollectionModel, slotPathAt, slotRefFor, type CollectionModel, type SlotRef };\n"]}
1
+ {"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { registerClass } from \"@gtkx/runtime\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport { createCollectionIndex, emptyLevel } from \"./collection-index.js\";\nimport { encodePart } from \"./keys.js\";\nimport { adoptIndex, createTreeExpansion, pruneSlots } from \"./tree-expansion.js\";\n\ntype LevelStore = Gio.ListModel & LazyLevelStore;\n\ntype SlotRef = {\n store: LevelStore;\n slot: number;\n};\n\ntype SyncContext = {\n index: CollectionIndex;\n expansion: TreeExpansion;\n};\n\ntype SlotRun = {\n start: number;\n length: number;\n};\n\ntype LevelSync = {\n store: LevelStore;\n level: Level;\n};\n\ntype ModelState = {\n root: Gio.ListStore;\n rootModels: GObject.Object[];\n model: Gtk.FlattenListModel;\n groupStores: LevelStore[];\n trees: Map<LevelStore, Gtk.TreeListModel>;\n treeModels: Gtk.TreeListModel[];\n expansion: TreeExpansion;\n index: CollectionIndex;\n};\n\ntype CollectionModel = {\n model: Gtk.FlattenListModel;\n expansion: TreeExpansion;\n rowAt: (position: number) => Gtk.TreeListRow | null;\n sync: (index: CollectionIndex) => void;\n};\n\nconst STORE_CLASS_KEY = Symbol.for(\"gtkx.components.lazy-level-store\");\nconst SLOTS_KEY = Symbol.for(\"gtkx.components.lazy-level-store.slots\");\nconst EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);\nconst SLOTS = sharedSlots();\n\nconst newRootStore = (): Gio.ListStore => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });\n\nfunction sharedSlots(): WeakMap<GObject.Object, SlotRef> {\n const cached: unknown = Reflect.get(globalThis, SLOTS_KEY);\n\n if (cached instanceof WeakMap) {\n return cached as WeakMap<GObject.Object, SlotRef>;\n }\n\n const created: WeakMap<GObject.Object, SlotRef> = new WeakMap();\n Reflect.set(globalThis, SLOTS_KEY, created);\n\n return created;\n}\n\nfunction registeredStoreClass(): typeof LazyLevelStore {\n const cached: unknown = Reflect.get(globalThis, STORE_CLASS_KEY);\n\n if (typeof cached === \"function\") {\n return cached as typeof LazyLevelStore;\n }\n\n registerClass(LazyLevelStore, { typeName: \"GtkxLazyLevelStore\", implements: [Gio.ListModel] });\n Reflect.set(globalThis, STORE_CLASS_KEY, LazyLevelStore);\n\n return LazyLevelStore;\n}\n\nfunction slotRefFor(value: GObject.Object | null): SlotRef | null {\n const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;\n\n if (item === null) {\n return null;\n }\n\n const ref = SLOTS.get(item);\n\n return ref === undefined || ref.slot === -1 ? null : ref;\n}\n\nfunction slotPathAt(store: LevelStore, slot: number): string {\n return store.level.path + encodePart(String(slot));\n}\n\nfunction growStore(store: LevelStore): void {\n for (let slot = store.refs.length; slot < store.level.items.length; slot++) {\n store.refs.push({ store, slot });\n store.objects.push(null);\n store.childStores.push(null);\n }\n}\n\nfunction newLevelStore(level: Level): LevelStore {\n const store = new (registeredStoreClass())() as LevelStore;\n store.level = level;\n growStore(store);\n\n return store;\n}\n\nfunction collectFlips(previous: Level, next: Level, overlap: number): Set<number> {\n const flipped: Set<number> = new Set();\n\n for (let slot = 0; slot < overlap; slot++) {\n if ((previous.expandableFlags[slot] ?? false) !== (next.expandableFlags[slot] ?? false)) {\n flipped.add(slot);\n }\n }\n\n return flipped;\n}\n\nfunction pruneFlips(context: SyncContext, store: LevelStore, flipped: Set<number>): void {\n if (flipped.size === 0) {\n return;\n }\n\n pruneSlots(context.expansion, store.level.path, (slot) => flipped.has(slot));\n\n for (const slot of flipped) {\n store.childStores[slot] = null;\n }\n}\n\nfunction detachRefs(store: LevelStore, nextLength: number): void {\n for (let slot = nextLength; slot < store.refs.length; slot++) {\n const ref = store.refs[slot];\n\n if (ref !== undefined) {\n ref.slot = -1;\n }\n }\n}\n\nfunction shrinkStore(context: SyncContext, store: LevelStore, nextLength: number): void {\n if (store.refs.length <= nextLength) {\n return;\n }\n\n detachRefs(store, nextLength);\n pruneSlots(context.expansion, store.level.path, (slot) => slot >= nextLength);\n store.refs.length = nextLength;\n store.objects.length = nextLength;\n store.childStores.length = nextLength;\n}\n\nfunction emitTailSplice(store: LevelStore, previousLength: number, nextLength: number): void {\n if (nextLength < previousLength) {\n store.itemsChanged(nextLength, previousLength - nextLength, 0);\n\n return;\n }\n\n if (nextLength > previousLength) {\n store.itemsChanged(previousLength, 0, nextLength - previousLength);\n }\n}\n\nfunction extendRuns(runs: SlotRun[], slot: number): void {\n const last = runs.at(-1);\n\n if (last !== undefined && last.start + last.length === slot) {\n last.length += 1;\n\n return;\n }\n\n runs.push({ start: slot, length: 1 });\n}\n\nfunction collectFlipRuns(flipped: Set<number>): SlotRun[] {\n const runs: SlotRun[] = [];\n\n for (const slot of flipped) {\n extendRuns(runs, slot);\n }\n\n return runs;\n}\n\nfunction emitFlips(store: LevelStore, flipped: Set<number>): void {\n for (const run of collectFlipRuns(flipped)) {\n store.itemsChanged(run.start, run.length, run.length);\n }\n}\n\nfunction childSync(\n context: SyncContext,\n store: LevelStore,\n slot: number,\n flipped: Set<number>,\n): LevelSync | undefined {\n const child = store.childStores[slot] ?? null;\n\n if (child === null || flipped.has(slot)) {\n return undefined;\n }\n\n const level = context.index.childLevel(store.level, slot);\n\n return level === undefined ? undefined : { store: child, level };\n}\n\nfunction childSyncs(context: SyncContext, store: LevelStore, overlap: number, flipped: Set<number>): LevelSync[] {\n const syncs: LevelSync[] = [];\n\n for (let slot = 0; slot < overlap; slot++) {\n const sync = childSync(context, store, slot, flipped);\n\n if (sync !== undefined) {\n syncs.push(sync);\n }\n }\n\n return syncs;\n}\n\nfunction syncEntry(context: SyncContext, entry: LevelSync): LevelSync[] {\n const { store, level } = entry;\n const previousLength = store.refs.length;\n const overlap = Math.min(previousLength, level.items.length);\n const flipped = collectFlips(store.level, level, overlap);\n store.level = level;\n pruneFlips(context, store, flipped);\n shrinkStore(context, store, level.items.length);\n growStore(store);\n emitTailSplice(store, previousLength, level.items.length);\n emitFlips(store, flipped);\n\n return childSyncs(context, store, overlap, flipped);\n}\n\nfunction pushSyncs(pending: LevelSync[], syncs: LevelSync[]): void {\n for (const sync of syncs) {\n pending.push(sync);\n }\n}\n\nfunction syncLevel(context: SyncContext, store: LevelStore, level: Level): void {\n const pending: LevelSync[] = [{ store, level }];\n\n while (pending.length > 0) {\n const entry = pending.pop();\n\n if (entry !== undefined) {\n pushSyncs(pending, syncEntry(context, entry).toReversed());\n }\n }\n}\n\nfunction ensureChildStore(index: CollectionIndex, store: LevelStore, slot: number): LevelStore | null {\n const existing = store.childStores[slot] ?? null;\n\n if (existing !== null || !(store.level.expandableFlags[slot] ?? false)) {\n return existing;\n }\n\n const level = index.childLevel(store.level, slot);\n\n if (level === undefined) {\n return null;\n }\n\n const created = newLevelStore(level);\n store.childStores[slot] = created;\n\n return created;\n}\n\nfunction childStoreFor(state: ModelState, object: GObject.Object): Gio.ListModel | null {\n const ref = slotRefFor(object);\n\n if (ref === null) {\n return null;\n }\n\n return ensureChildStore(state.index, ref.store, ref.slot);\n}\n\nfunction treeFor(state: ModelState, store: LevelStore): Gtk.TreeListModel {\n return (\n state.trees.get(store) ?? Gtk.TreeListModel.new(store, false, false, (object) => childStoreFor(state, object))\n );\n}\n\nfunction nextTrees(state: ModelState, index: CollectionIndex): Map<LevelStore, Gtk.TreeListModel> {\n if (!index.isTree) {\n return new Map();\n }\n\n return new Map(state.groupStores.map((store) => [store, treeFor(state, store)]));\n}\n\nfunction pruneRebuiltLevels(state: ModelState, next: Map<LevelStore, Gtk.TreeListModel>): void {\n const stores: Set<LevelStore> = new Set([...state.trees.keys(), ...next.keys()]);\n\n for (const store of stores) {\n if (state.trees.get(store) !== next.get(store)) {\n pruneSlots(state.expansion, store.level.path, () => true);\n }\n }\n}\n\nfunction adoptTrees(state: ModelState, index: CollectionIndex): void {\n const next = nextTrees(state, index);\n pruneRebuiltLevels(state, next);\n state.trees = next;\n state.treeModels = next.values().toArray();\n}\n\nfunction desiredRootModels(state: ModelState, index: CollectionIndex): GObject.Object[] {\n adoptTrees(state, index);\n\n return index.isTree ? [...state.treeModels] : [...state.groupStores];\n}\n\nfunction rowAt(state: ModelState, position: number): Gtk.TreeListRow | null {\n let offset = position;\n\n for (const tree of state.treeModels) {\n const count = tree.getNItems();\n\n if (offset < count) {\n return tree.getRow(offset);\n }\n\n offset -= count;\n }\n\n return null;\n}\n\nfunction hasSameModels(previous: GObject.Object[], next: GObject.Object[]): boolean {\n return previous.length === next.length && next.every((model, index) => previous[index] === model);\n}\n\nfunction syncRoot(state: ModelState, index: CollectionIndex): void {\n const next = desiredRootModels(state, index);\n\n if (hasSameModels(state.rootModels, next)) {\n return;\n }\n\n state.root.splice(0, state.rootModels.length, next);\n state.rootModels = next;\n}\n\nfunction adjustGroupStores(state: ModelState, context: SyncContext): void {\n const { groups } = context.index;\n state.groupStores.length = Math.min(state.groupStores.length, groups.length);\n\n for (const level of groups.slice(state.groupStores.length)) {\n state.groupStores.push(newLevelStore(level));\n }\n}\n\nfunction stepGroupStores(state: ModelState, context: SyncContext, surviving: number): void {\n for (const [group, level] of context.index.groups.entries()) {\n const store = state.groupStores[group];\n\n if (store !== undefined && group < surviving) {\n syncLevel(context, store, level);\n }\n }\n}\n\nfunction syncModel(state: ModelState, index: CollectionIndex): void {\n const context: SyncContext = { index, expansion: state.expansion };\n const surviving = Math.min(state.groupStores.length, index.groups.length);\n state.index = index;\n state.expansion.isSyncing = true;\n\n try {\n adjustGroupStores(state, context);\n syncRoot(state, index);\n stepGroupStores(state, context, surviving);\n } finally {\n state.expansion.isSyncing = false;\n }\n\n adoptIndex(state.expansion, index);\n}\n\nfunction createCollectionModel(): CollectionModel {\n registeredStoreClass();\n const root = newRootStore();\n\n const state: ModelState = {\n root,\n rootModels: [],\n model: Gtk.FlattenListModel.new(root),\n groupStores: [],\n trees: new Map(),\n treeModels: [],\n expansion: createTreeExpansion(EMPTY_INDEX),\n index: EMPTY_INDEX,\n };\n\n return {\n model: state.model,\n expansion: state.expansion,\n rowAt: (position) => rowAt(state, position),\n sync: (index) => {\n syncModel(state, index);\n },\n };\n}\n\nclass LazyLevelStore extends GObject.Object implements Gio.ListModelImpl {\n declare itemsChanged: Gio.ListModel[\"itemsChanged\"];\n level: Level = emptyLevel();\n refs: SlotRef[] = [];\n objects: (Gtk.StringObject | null)[] = [];\n childStores: (LevelStore | null)[] = [];\n\n private createItem(position: number, ref: SlotRef): Gtk.StringObject {\n const created = Gtk.StringObject.new(\"\");\n this.objects[position] = created;\n SLOTS.set(created, ref);\n\n return created;\n }\n\n vfuncGetItemType(): bigint {\n return GObject.TYPE_OBJECT;\n }\n\n vfuncGetNItems(): number {\n return this.refs.length;\n }\n\n vfuncGetItem(position: number): GObject.Object | null {\n const ref = this.refs[position];\n\n if (ref === undefined) {\n return null;\n }\n\n return this.objects[position] ?? this.createItem(position, ref);\n }\n}\n\nexport { createCollectionModel, slotPathAt, slotRefFor, type CollectionModel, type SlotRef };\n"]}
@@ -1,7 +1,8 @@
1
1
  import type { ListItem } from "../types.js";
2
2
  import type { CollectionIndex } from "./collection-index.js";
3
3
  import type { CollectionModel, SlotRef } from "./collection-model.js";
4
- type Collection = Pick<CollectionModel, "model" | "expansion" | "treeModel"> & {
4
+ type Collection = Pick<CollectionModel, "model" | "expansion" | "rowAt"> & {
5
+ isTree: boolean;
5
6
  itemAt: (ref: SlotRef) => ListItem | undefined;
6
7
  sectionFor: (levelPath: string) => unknown;
7
8
  idAt: (position: number) => string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAItE,KAAK,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG;IAC3E,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC/C,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CAC7C,CAAC;AAgDF,iBAAS,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAIzD;AAED,iBAAS,gBAAgB,CAAC,eAAe,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAY9F;AAED,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAItE,KAAK,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC,GAAG;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC/C,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CAC7C,CAAC;AAgDF,iBAAS,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAIzD;AAED,iBAAS,gBAAgB,CAAC,eAAe,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAa9F;AAED,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,CAAC"}
@@ -18,12 +18,12 @@ function refAt(collectionModel, position) {
18
18
  }
19
19
  return slotRefFor(collectionModel.model.getItem(position));
20
20
  }
21
+ function itemAt(index, ref) {
22
+ return index.itemAt(ref.store.level.path, ref.slot);
23
+ }
21
24
  function idAt(collectionModel, index, position) {
22
25
  const ref = refAt(collectionModel, position);
23
- if (ref === null) {
24
- return null;
25
- }
26
- return index.itemAt(ref.store.path, ref.slot)?.id ?? null;
26
+ return ref === null ? null : (itemAt(index, ref)?.id ?? null);
27
27
  }
28
28
  function pathAt(collectionModel, position) {
29
29
  const ref = refAt(collectionModel, position);
@@ -40,8 +40,9 @@ function createCollection(collectionModel, index) {
40
40
  return {
41
41
  model: collectionModel.model,
42
42
  expansion: collectionModel.expansion,
43
- treeModel: () => (index.isTree ? collectionModel.treeModel() : null),
44
- itemAt: (ref) => index.itemAt(ref.store.path, ref.slot),
43
+ isTree: index.isTree,
44
+ rowAt: collectionModel.rowAt,
45
+ itemAt: (ref) => itemAt(index, ref),
45
46
  sectionFor: index.sectionFor,
46
47
  idAt: (position) => idAt(collectionModel, index, position),
47
48
  pathAt: (position) => pathAt(collectionModel, position),
@@ -1 +1 @@
1
- {"version":3,"file":"collection.js","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListItem } from \"../types.js\";\nimport type { CollectionIndex } from \"./collection-index.js\";\nimport type { CollectionModel, SlotRef } from \"./collection-model.js\";\nimport { slotPathAt, slotRefFor } from \"./collection-model.js\";\nimport { findPositions } from \"./tree-order.js\";\n\ntype Collection = Pick<CollectionModel, \"model\" | \"expansion\" | \"treeModel\"> & {\n itemAt: (ref: SlotRef) => ListItem | undefined;\n sectionFor: (levelPath: string) => unknown;\n idAt: (position: number) => string | null;\n pathAt: (position: number) => string | null;\n positionFor: (id: string) => number;\n positionsFor: (ids: string[]) => number[];\n};\n\nconst NO_POSITIONS: number[] = [];\n\nfunction positionsFor(collectionModel: CollectionModel, ids: string[]): number[] {\n if (ids.length === 0) {\n return NO_POSITIONS;\n }\n\n const { expansion } = collectionModel;\n\n return findPositions(expansion.index, expansion.slots, new Set(ids));\n}\n\nfunction positionFor(collectionModel: CollectionModel, id: string): number {\n const [first = -1] = positionsFor(collectionModel, [id]);\n\n return first;\n}\n\nfunction refAt(collectionModel: CollectionModel, position: number): SlotRef | null {\n if (position < 0) {\n return null;\n }\n\n return slotRefFor(collectionModel.model.getItem(position));\n}\n\nfunction idAt(collectionModel: CollectionModel, index: CollectionIndex, position: number): string | null {\n const ref = refAt(collectionModel, position);\n\n if (ref === null) {\n return null;\n }\n\n return index.itemAt(ref.store.path, ref.slot)?.id ?? null;\n}\n\nfunction pathAt(collectionModel: CollectionModel, position: number): string | null {\n const ref = refAt(collectionModel, position);\n\n if (ref === null) {\n return null;\n }\n\n return slotPathAt(ref.store, ref.slot);\n}\n\nfunction isCollectionIdle(collection: Collection): boolean {\n const { expansion } = collection;\n\n return !expansion.isApplying && !expansion.isSyncing;\n}\n\nfunction createCollection(collectionModel: CollectionModel, index: CollectionIndex): Collection {\n return {\n model: collectionModel.model,\n expansion: collectionModel.expansion,\n treeModel: () => (index.isTree ? collectionModel.treeModel() : null),\n itemAt: (ref) => index.itemAt(ref.store.path, ref.slot),\n sectionFor: index.sectionFor,\n idAt: (position) => idAt(collectionModel, index, position),\n pathAt: (position) => pathAt(collectionModel, position),\n positionFor: (id) => positionFor(collectionModel, id),\n positionsFor: (ids) => positionsFor(collectionModel, ids),\n };\n}\n\nexport { createCollection, isCollectionIdle, type Collection };\n"]}
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListItem } from \"../types.js\";\nimport type { CollectionIndex } from \"./collection-index.js\";\nimport type { CollectionModel, SlotRef } from \"./collection-model.js\";\nimport { slotPathAt, slotRefFor } from \"./collection-model.js\";\nimport { findPositions } from \"./tree-order.js\";\n\ntype Collection = Pick<CollectionModel, \"model\" | \"expansion\" | \"rowAt\"> & {\n isTree: boolean;\n itemAt: (ref: SlotRef) => ListItem | undefined;\n sectionFor: (levelPath: string) => unknown;\n idAt: (position: number) => string | null;\n pathAt: (position: number) => string | null;\n positionFor: (id: string) => number;\n positionsFor: (ids: string[]) => number[];\n};\n\nconst NO_POSITIONS: number[] = [];\n\nfunction positionsFor(collectionModel: CollectionModel, ids: string[]): number[] {\n if (ids.length === 0) {\n return NO_POSITIONS;\n }\n\n const { expansion } = collectionModel;\n\n return findPositions(expansion.index, expansion.slots, new Set(ids));\n}\n\nfunction positionFor(collectionModel: CollectionModel, id: string): number {\n const [first = -1] = positionsFor(collectionModel, [id]);\n\n return first;\n}\n\nfunction refAt(collectionModel: CollectionModel, position: number): SlotRef | null {\n if (position < 0) {\n return null;\n }\n\n return slotRefFor(collectionModel.model.getItem(position));\n}\n\nfunction itemAt(index: CollectionIndex, ref: SlotRef): ListItem | undefined {\n return index.itemAt(ref.store.level.path, ref.slot);\n}\n\nfunction idAt(collectionModel: CollectionModel, index: CollectionIndex, position: number): string | null {\n const ref = refAt(collectionModel, position);\n\n return ref === null ? null : (itemAt(index, ref)?.id ?? null);\n}\n\nfunction pathAt(collectionModel: CollectionModel, position: number): string | null {\n const ref = refAt(collectionModel, position);\n\n if (ref === null) {\n return null;\n }\n\n return slotPathAt(ref.store, ref.slot);\n}\n\nfunction isCollectionIdle(collection: Collection): boolean {\n const { expansion } = collection;\n\n return !expansion.isApplying && !expansion.isSyncing;\n}\n\nfunction createCollection(collectionModel: CollectionModel, index: CollectionIndex): Collection {\n return {\n model: collectionModel.model,\n expansion: collectionModel.expansion,\n isTree: index.isTree,\n rowAt: collectionModel.rowAt,\n itemAt: (ref) => itemAt(index, ref),\n sectionFor: index.sectionFor,\n idAt: (position) => idAt(collectionModel, index, position),\n pathAt: (position) => pathAt(collectionModel, position),\n positionFor: (id) => positionFor(collectionModel, id),\n positionsFor: (ids) => positionsFor(collectionModel, ids),\n };\n}\n\nexport { createCollection, isCollectionIdle, type Collection };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"expansion.d.ts","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAUlD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACnE,CAAC;AAQF,KAAK,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAoHrF,iBAAS,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAgBnE;AAED,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"expansion.d.ts","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAUlD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACnE,CAAC;AAQF,KAAK,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAyGrF,iBAAS,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAgBnE;AAED,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,CAAC"}
@@ -4,30 +4,22 @@ import { useControlledSync } from "./controlled-sync.js";
4
4
  import { joinParts } from "./keys.js";
5
5
  import { trackPaths } from "./slots.js";
6
6
  import { adoptOrder, markExpanded, orderFor } from "./tree-expansion.js";
7
- import { walkVisible } from "./tree-order.js";
7
+ import { expandedPathsFor, walkVisible } from "./tree-order.js";
8
8
  function newLastExpansion() {
9
9
  return { key: "" };
10
10
  }
11
- function wantedSet(expansion, expandedIds) {
12
- const wanted = new Set();
13
- for (const id of expandedIds) {
14
- for (const path of expansion.index.expandablePathsFor(id)) {
15
- wanted.add(path);
16
- }
17
- }
18
- return wanted;
19
- }
20
11
  function hasSameExpansion(expanded, wanted) {
21
12
  return expanded.size === wanted.size && wanted.isSubsetOf(expanded);
22
13
  }
23
- function toggleOptions(expansion, tree, wanted) {
14
+ function toggleOptions(collection, wanted) {
15
+ const { expansion } = collection;
24
16
  return {
25
17
  index: expansion.index,
26
18
  slots: trackPaths(wanted),
27
19
  marks: trackPaths(wanted.symmetricDifference(expansion.expanded)),
28
20
  visit: (row) => {
29
21
  if (row.isMarked) {
30
- tree.getRow(row.position)?.setExpanded(row.isOpen);
22
+ collection.rowAt(row.position)?.setExpanded(row.isOpen);
31
23
  }
32
24
  },
33
25
  };
@@ -41,12 +33,13 @@ function walkApplying(expansion, options) {
41
33
  expansion.isApplying = false;
42
34
  }
43
35
  }
44
- function applyWanted(expansion, tree, expandedIds) {
45
- const wanted = wantedSet(expansion, expandedIds);
36
+ function applyWanted(collection, expandedIds) {
37
+ const { expansion } = collection;
38
+ const wanted = expandedPathsFor(expansion.index, new Set(expandedIds));
46
39
  if (hasSameExpansion(expansion.expanded, wanted)) {
47
40
  return;
48
41
  }
49
- adoptOrder(expansion, walkApplying(expansion, toggleOptions(expansion, tree, wanted)));
42
+ adoptOrder(expansion, walkApplying(expansion, toggleOptions(collection, wanted)));
50
43
  }
51
44
  function reportExpansion(context) {
52
45
  const { expandedIds, expandedPaths } = orderFor(context.collection.expansion);
@@ -58,15 +51,14 @@ function reportExpansion(context) {
58
51
  context.onExpandedChange?.([...expandedIds]);
59
52
  }
60
53
  function applyControlledExpansion(context, expandedIds) {
61
- const tree = context.collection.treeModel();
62
- if (tree === null) {
54
+ if (!context.collection.isTree) {
63
55
  return;
64
56
  }
65
- applyWanted(context.collection.expansion, tree, expandedIds ?? []);
57
+ applyWanted(context.collection, expandedIds ?? []);
66
58
  reportExpansion(context);
67
59
  }
68
60
  function isExpansionIdle(collection) {
69
- return collection.treeModel() !== null && isCollectionIdle(collection);
61
+ return collection.isTree && isCollectionIdle(collection);
70
62
  }
71
63
  function didRowDrift(collection, change) {
72
64
  const path = collection.pathAt(change.position - 1);
@@ -1 +1 @@
1
- {"version":3,"file":"expansion.js","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { useState } from \"react\";\nimport type { Collection } from \"./collection.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport type { VisibleOrder, WalkOptions } from \"./tree-order.js\";\nimport { isCollectionIdle } from \"./collection.js\";\nimport { useControlledSync } from \"./controlled-sync.js\";\nimport { joinParts } from \"./keys.js\";\nimport { trackPaths } from \"./slots.js\";\nimport { adoptOrder, markExpanded, orderFor } from \"./tree-expansion.js\";\nimport { walkVisible } from \"./tree-order.js\";\n\ntype ExpansionOptions = {\n collection: Collection;\n expandedIds?: string[] | null | undefined;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\ntype ItemsChange = {\n position: number;\n removed: number;\n added: number;\n};\n\ntype ItemsChangeHandler = (position: number, removed: number, added: number) => void;\ntype LastExpansion = { key: string };\n\ntype ExpansionContext = {\n collection: Collection;\n last: LastExpansion;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\nfunction newLastExpansion(): LastExpansion {\n return { key: \"\" };\n}\n\nfunction wantedSet(expansion: TreeExpansion, expandedIds: string[]): Set<string> {\n const wanted: Set<string> = new Set();\n\n for (const id of expandedIds) {\n for (const path of expansion.index.expandablePathsFor(id)) {\n wanted.add(path);\n }\n }\n\n return wanted;\n}\n\nfunction hasSameExpansion(expanded: Set<string>, wanted: Set<string>): boolean {\n return expanded.size === wanted.size && wanted.isSubsetOf(expanded);\n}\n\nfunction toggleOptions(expansion: TreeExpansion, tree: Gtk.TreeListModel, wanted: Set<string>): WalkOptions {\n return {\n index: expansion.index,\n slots: trackPaths(wanted),\n marks: trackPaths(wanted.symmetricDifference(expansion.expanded)),\n visit: (row) => {\n if (row.isMarked) {\n tree.getRow(row.position)?.setExpanded(row.isOpen);\n }\n },\n };\n}\n\nfunction walkApplying(expansion: TreeExpansion, options: WalkOptions): VisibleOrder {\n expansion.isApplying = true;\n\n try {\n return walkVisible(options);\n } finally {\n expansion.isApplying = false;\n }\n}\n\nfunction applyWanted(expansion: TreeExpansion, tree: Gtk.TreeListModel, expandedIds: string[]): void {\n const wanted = wantedSet(expansion, expandedIds);\n\n if (hasSameExpansion(expansion.expanded, wanted)) {\n return;\n }\n\n adoptOrder(expansion, walkApplying(expansion, toggleOptions(expansion, tree, wanted)));\n}\n\nfunction reportExpansion(context: ExpansionContext): void {\n const { expandedIds, expandedPaths } = orderFor(context.collection.expansion);\n const key = joinParts(expandedPaths);\n\n if (context.last.key === key) {\n return;\n }\n\n context.last.key = key;\n context.onExpandedChange?.([...expandedIds]);\n}\n\nfunction applyControlledExpansion(context: ExpansionContext, expandedIds: string[] | null | undefined): void {\n const tree = context.collection.treeModel();\n\n if (tree === null) {\n return;\n }\n\n applyWanted(context.collection.expansion, tree, expandedIds ?? []);\n reportExpansion(context);\n}\n\nfunction isExpansionIdle(collection: Collection): boolean {\n return collection.treeModel() !== null && isCollectionIdle(collection);\n}\n\nfunction didRowDrift(collection: Collection, change: ItemsChange): boolean {\n const path = collection.pathAt(change.position - 1);\n const isExpanded = change.removed === 0 && change.added > 0;\n const isCollapsed = change.added === 0 && change.removed > 0;\n\n if (path === null || isExpanded === isCollapsed) {\n return false;\n }\n\n markExpanded(collection.expansion, path, isExpanded);\n\n return true;\n}\n\nfunction observeExpansion(context: ExpansionContext, change: ItemsChange, onDrift: () => void): void {\n if (!isExpansionIdle(context.collection)) {\n return;\n }\n\n const didDrift = didRowDrift(context.collection, change);\n reportExpansion(context);\n\n if (didDrift) {\n onDrift();\n }\n}\n\nfunction useExpansion(options: ExpansionOptions): ItemsChangeHandler {\n const { collection, expandedIds, onExpandedChange } = options;\n const [last] = useState<LastExpansion>(newLastExpansion);\n const context: ExpansionContext = { collection, last, onExpandedChange };\n\n const markDrift = useControlledSync({\n ids: expandedIds,\n collection,\n apply: (ids) => {\n applyControlledExpansion(context, ids);\n },\n });\n\n return (position, removed, added) => {\n observeExpansion(context, { position, removed, added }, markDrift);\n };\n}\n\nexport { useExpansion, type ItemsChangeHandler };\n"]}
1
+ {"version":3,"file":"expansion.js","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport type { Collection } from \"./collection.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport type { VisibleOrder, WalkOptions } from \"./tree-order.js\";\nimport { isCollectionIdle } from \"./collection.js\";\nimport { useControlledSync } from \"./controlled-sync.js\";\nimport { joinParts } from \"./keys.js\";\nimport { trackPaths } from \"./slots.js\";\nimport { adoptOrder, markExpanded, orderFor } from \"./tree-expansion.js\";\nimport { expandedPathsFor, walkVisible } from \"./tree-order.js\";\n\ntype ExpansionOptions = {\n collection: Collection;\n expandedIds?: string[] | null | undefined;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\ntype ItemsChange = {\n position: number;\n removed: number;\n added: number;\n};\n\ntype ItemsChangeHandler = (position: number, removed: number, added: number) => void;\ntype LastExpansion = { key: string };\n\ntype ExpansionContext = {\n collection: Collection;\n last: LastExpansion;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\nfunction newLastExpansion(): LastExpansion {\n return { key: \"\" };\n}\n\nfunction hasSameExpansion(expanded: Set<string>, wanted: Set<string>): boolean {\n return expanded.size === wanted.size && wanted.isSubsetOf(expanded);\n}\n\nfunction toggleOptions(collection: Collection, wanted: Set<string>): WalkOptions {\n const { expansion } = collection;\n\n return {\n index: expansion.index,\n slots: trackPaths(wanted),\n marks: trackPaths(wanted.symmetricDifference(expansion.expanded)),\n visit: (row) => {\n if (row.isMarked) {\n collection.rowAt(row.position)?.setExpanded(row.isOpen);\n }\n },\n };\n}\n\nfunction walkApplying(expansion: TreeExpansion, options: WalkOptions): VisibleOrder {\n expansion.isApplying = true;\n\n try {\n return walkVisible(options);\n } finally {\n expansion.isApplying = false;\n }\n}\n\nfunction applyWanted(collection: Collection, expandedIds: string[]): void {\n const { expansion } = collection;\n const wanted = expandedPathsFor(expansion.index, new Set(expandedIds));\n\n if (hasSameExpansion(expansion.expanded, wanted)) {\n return;\n }\n\n adoptOrder(expansion, walkApplying(expansion, toggleOptions(collection, wanted)));\n}\n\nfunction reportExpansion(context: ExpansionContext): void {\n const { expandedIds, expandedPaths } = orderFor(context.collection.expansion);\n const key = joinParts(expandedPaths);\n\n if (context.last.key === key) {\n return;\n }\n\n context.last.key = key;\n context.onExpandedChange?.([...expandedIds]);\n}\n\nfunction applyControlledExpansion(context: ExpansionContext, expandedIds: string[] | null | undefined): void {\n if (!context.collection.isTree) {\n return;\n }\n\n applyWanted(context.collection, expandedIds ?? []);\n reportExpansion(context);\n}\n\nfunction isExpansionIdle(collection: Collection): boolean {\n return collection.isTree && isCollectionIdle(collection);\n}\n\nfunction didRowDrift(collection: Collection, change: ItemsChange): boolean {\n const path = collection.pathAt(change.position - 1);\n const isExpanded = change.removed === 0 && change.added > 0;\n const isCollapsed = change.added === 0 && change.removed > 0;\n\n if (path === null || isExpanded === isCollapsed) {\n return false;\n }\n\n markExpanded(collection.expansion, path, isExpanded);\n\n return true;\n}\n\nfunction observeExpansion(context: ExpansionContext, change: ItemsChange, onDrift: () => void): void {\n if (!isExpansionIdle(context.collection)) {\n return;\n }\n\n const didDrift = didRowDrift(context.collection, change);\n reportExpansion(context);\n\n if (didDrift) {\n onDrift();\n }\n}\n\nfunction useExpansion(options: ExpansionOptions): ItemsChangeHandler {\n const { collection, expandedIds, onExpandedChange } = options;\n const [last] = useState<LastExpansion>(newLastExpansion);\n const context: ExpansionContext = { collection, last, onExpandedChange };\n\n const markDrift = useControlledSync({\n ids: expandedIds,\n collection,\n apply: (ids) => {\n applyControlledExpansion(context, ids);\n },\n });\n\n return (position, removed, added) => {\n observeExpansion(context, { position, removed, added }, markDrift);\n };\n}\n\nexport { useExpansion, type ItemsChangeHandler };\n"]}
@@ -14,7 +14,6 @@ declare function orderFor(expansion: TreeExpansion): VisibleOrder;
14
14
  declare function adoptOrder(expansion: TreeExpansion, order: VisibleOrder): void;
15
15
  declare function pruneSlots(expansion: TreeExpansion, levelPath: string, isPruned: (slot: number) => boolean): void;
16
16
  declare function markExpanded(expansion: TreeExpansion, path: string, isExpanded: boolean): void;
17
- declare function resetExpansion(expansion: TreeExpansion): void;
18
17
  declare function adoptIndex(expansion: TreeExpansion, index: CollectionIndex): void;
19
- export { adoptIndex, adoptOrder, createTreeExpansion, markExpanded, orderFor, pruneSlots, resetExpansion, type TreeExpansion, };
18
+ export { adoptIndex, adoptOrder, createTreeExpansion, markExpanded, orderFor, pruneSlots, type TreeExpansion, };
20
19
  //# sourceMappingURL=tree-expansion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree-expansion.d.ts","sourceRoot":"","sources":["../../src/internal/tree-expansion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD,KAAK,aAAa,GAAG;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAiBF,iBAAS,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,aAAa,CAElE;AAED,iBAAS,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG,YAAY,CAIxD;AAED,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAIvE;AAaD,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAiB1G;AAED,iBAAS,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAUvF;AAED,iBAAS,cAAc,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAItD;AAED,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAG1E;AAED,OAAO,EACH,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,cAAc,EACd,KAAK,aAAa,GACrB,CAAC"}
1
+ {"version":3,"file":"tree-expansion.d.ts","sourceRoot":"","sources":["../../src/internal/tree-expansion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD,KAAK,aAAa,GAAG;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AA6BF,iBAAS,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,aAAa,CAElE;AAED,iBAAS,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG,YAAY,CAIxD;AAED,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAIvE;AAaD,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAiB1G;AAED,iBAAS,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAUvF;AAED,iBAAS,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAG1E;AAED,OAAO,EACH,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,KAAK,aAAa,GACrB,CAAC"}