@gtkx/components 1.0.0-rc.3 → 1.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.
Files changed (104) hide show
  1. package/README.md +8 -9
  2. package/dist/adw/combo-row.d.ts +1 -0
  3. package/dist/adw/combo-row.d.ts.map +1 -1
  4. package/dist/adw/combo-row.js.map +1 -1
  5. package/dist/adw/types.d.ts +2 -1
  6. package/dist/adw/types.d.ts.map +1 -1
  7. package/dist/adw/types.js.map +1 -1
  8. package/dist/column-view.d.ts +2 -2
  9. package/dist/column-view.d.ts.map +1 -1
  10. package/dist/column-view.js +15 -13
  11. package/dist/column-view.js.map +1 -1
  12. package/dist/drop-down.d.ts +1 -0
  13. package/dist/drop-down.d.ts.map +1 -1
  14. package/dist/drop-down.js.map +1 -1
  15. package/dist/grid-view.js +2 -2
  16. package/dist/grid-view.js.map +1 -1
  17. package/dist/index.d.ts +1 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +0 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/internal/cells.d.ts +32 -24
  22. package/dist/internal/cells.d.ts.map +1 -1
  23. package/dist/internal/cells.js +168 -77
  24. package/dist/internal/cells.js.map +1 -1
  25. package/dist/internal/collection-index.d.ts +9 -13
  26. package/dist/internal/collection-index.d.ts.map +1 -1
  27. package/dist/internal/collection-index.js +33 -70
  28. package/dist/internal/collection-index.js.map +1 -1
  29. package/dist/internal/collection-model.d.ts +23 -2
  30. package/dist/internal/collection-model.d.ts.map +1 -1
  31. package/dist/internal/collection-model.js +210 -98
  32. package/dist/internal/collection-model.js.map +1 -1
  33. package/dist/internal/collection.d.ts +9 -12
  34. package/dist/internal/collection.d.ts.map +1 -1
  35. package/dist/internal/collection.js +38 -49
  36. package/dist/internal/collection.js.map +1 -1
  37. package/dist/internal/controlled-sync.d.ts +11 -0
  38. package/dist/internal/controlled-sync.d.ts.map +1 -0
  39. package/dist/internal/controlled-sync.js +19 -0
  40. package/dist/internal/controlled-sync.js.map +1 -0
  41. package/dist/internal/drop-down.d.ts.map +1 -1
  42. package/dist/internal/drop-down.js +27 -15
  43. package/dist/internal/drop-down.js.map +1 -1
  44. package/dist/internal/expansion.d.ts +3 -2
  45. package/dist/internal/expansion.d.ts.map +1 -1
  46. package/dist/internal/expansion.js +80 -47
  47. package/dist/internal/expansion.js.map +1 -1
  48. package/dist/internal/keys.d.ts +5 -0
  49. package/dist/internal/keys.d.ts.map +1 -0
  50. package/dist/internal/keys.js +13 -0
  51. package/dist/internal/keys.js.map +1 -0
  52. package/dist/internal/selection.d.ts +3 -2
  53. package/dist/internal/selection.d.ts.map +1 -1
  54. package/dist/internal/selection.js +68 -35
  55. package/dist/internal/selection.js.map +1 -1
  56. package/dist/internal/slots.d.ts +10 -0
  57. package/dist/internal/slots.d.ts.map +1 -0
  58. package/dist/internal/slots.js +43 -0
  59. package/dist/internal/slots.js.map +1 -0
  60. package/dist/internal/tree-expansion.d.ts +20 -0
  61. package/dist/internal/tree-expansion.d.ts.map +1 -0
  62. package/dist/internal/tree-expansion.js +68 -0
  63. package/dist/internal/tree-expansion.js.map +1 -0
  64. package/dist/internal/tree-order.d.ts +27 -0
  65. package/dist/internal/tree-order.d.ts.map +1 -0
  66. package/dist/internal/tree-order.js +71 -0
  67. package/dist/internal/tree-order.js.map +1 -0
  68. package/dist/internal/use-collection.d.ts +5 -5
  69. package/dist/internal/use-collection.d.ts.map +1 -1
  70. package/dist/internal/use-collection.js +6 -6
  71. package/dist/internal/use-collection.js.map +1 -1
  72. package/dist/list-view.d.ts.map +1 -1
  73. package/dist/list-view.js +6 -6
  74. package/dist/list-view.js.map +1 -1
  75. package/dist/types.d.ts +127 -54
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/types.js.map +1 -1
  78. package/package.json +7 -7
  79. package/src/adw/combo-row.tsx +1 -0
  80. package/src/adw/types.ts +2 -1
  81. package/src/column-view.tsx +38 -35
  82. package/src/drop-down.tsx +1 -0
  83. package/src/grid-view.tsx +2 -2
  84. package/src/index.ts +10 -11
  85. package/src/internal/cells.tsx +345 -123
  86. package/src/internal/collection-index.ts +51 -99
  87. package/src/internal/collection-model.ts +259 -110
  88. package/src/internal/collection.ts +46 -68
  89. package/src/internal/controlled-sync.ts +34 -0
  90. package/src/internal/drop-down.tsx +44 -23
  91. package/src/internal/expansion.ts +104 -67
  92. package/src/internal/keys.ts +18 -0
  93. package/src/internal/selection.tsx +100 -51
  94. package/src/internal/slots.ts +67 -0
  95. package/src/internal/tree-expansion.ts +110 -0
  96. package/src/internal/tree-order.ts +138 -0
  97. package/src/internal/use-collection.tsx +11 -11
  98. package/src/list-view.tsx +14 -10
  99. package/src/types.ts +140 -65
  100. package/dist/size-group.d.ts +0 -12
  101. package/dist/size-group.d.ts.map +0 -1
  102. package/dist/size-group.js +0 -41
  103. package/dist/size-group.js.map +0 -1
  104. package/src/size-group.tsx +0 -77
@@ -1 +1 @@
1
- {"version":3,"file":"collection-index.js","sourceRoot":"","sources":["../../src/internal/collection-index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Item, Section } from \"../types.js\";\n\ntype Level = {\n key: string;\n ids: string[];\n isExpandable: boolean[];\n};\n\ntype CollectionIndex = {\n isTree: boolean;\n size: number;\n groups: Level[];\n children: Map<string, Level>;\n has: (id: string) => boolean;\n itemFor: (id: string) => Item | undefined;\n sectionFor: (id: string) => unknown;\n positionFor: (id: string) => number;\n};\n\ntype IndexState = {\n isTree: boolean;\n groups: Level[];\n children: Map<string, Level>;\n itemsById: Map<string, Item>;\n sections: Section[] | undefined;\n positions: Map<string, number> | null;\n starts: number[] | null;\n};\n\nconst ROOT_LEVEL_KEY = \"\";\n\nconst hasChildren = (item: Item): boolean => item.children !== undefined && item.children.length > 0;\nconst childLevelKey = (id: string): string => `child:${id}`;\n\nfunction collectChildren(state: IndexState, level: Level, item: Item): void {\n if (!state.isTree) {\n return;\n }\n\n const canExpand = hasChildren(item);\n level.isExpandable.push(canExpand);\n\n if (!canExpand) {\n return;\n }\n\n const key = childLevelKey(item.id);\n state.children.set(key, collectLevel(state, key, item.children ?? []));\n}\n\nfunction collectLevel(state: IndexState, key: string, items: Item[]): Level {\n const level: Level = { key, ids: [], isExpandable: [] };\n\n for (const item of items) {\n level.ids.push(item.id);\n state.itemsById.set(item.id, item);\n collectChildren(state, level, item);\n }\n\n return level;\n}\n\nfunction buildPositions(state: IndexState): void {\n const positions: Map<string, number> = new Map();\n const starts: number[] = [];\n let offset = 0;\n\n for (const level of state.groups) {\n starts.push(offset);\n\n for (const id of level.ids) {\n positions.set(id, offset);\n offset += 1;\n }\n }\n\n state.positions = positions;\n state.starts = starts;\n}\n\nfunction positionFor(state: IndexState, id: string): number {\n if (state.isTree) {\n return -1;\n }\n\n if (state.positions === null) {\n buildPositions(state);\n }\n\n return state.positions?.get(id) ?? -1;\n}\n\nfunction sectionAt(starts: number[], position: number): number {\n let low = 0;\n let high = starts.length - 1;\n\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n\n if ((starts[middle] ?? 0) <= position) {\n low = middle;\n } else {\n high = middle - 1;\n }\n }\n\n return low;\n}\n\nfunction sectionFor(state: IndexState, id: string): unknown {\n const sections = state.sections;\n const position = positionFor(state, id);\n\n if (sections === undefined || position < 0 || state.starts === null) {\n return undefined;\n }\n\n return sections[sectionAt(state.starts, position)]?.value;\n}\n\nfunction buildGroups(state: IndexState, source: Item[], sections: Section[] | undefined): Level[] {\n if (sections === undefined) {\n return [collectLevel(state, ROOT_LEVEL_KEY, source)];\n }\n\n return sections.map((section) => collectLevel(state, section.id, section.data));\n}\n\nfunction isTreeSource(source: Item[], sections: Section[] | undefined, isFlat: boolean): boolean {\n if (sections !== undefined || isFlat) {\n return false;\n }\n\n return source.some((item) => hasChildren(item));\n}\n\nfunction createCollectionIndex(\n items: Item[] | undefined,\n sections: Section[] | undefined,\n isFlat: boolean,\n): CollectionIndex {\n const source = items ?? [];\n\n const state: IndexState = {\n isTree: isTreeSource(source, sections, isFlat),\n groups: [],\n children: new Map(),\n itemsById: new Map(),\n sections,\n positions: null,\n starts: null,\n };\n\n state.groups = buildGroups(state, source, sections);\n\n return {\n isTree: state.isTree,\n size: state.itemsById.size,\n groups: state.groups,\n children: state.children,\n has: (id) => state.itemsById.has(id),\n itemFor: (id) => state.itemsById.get(id),\n sectionFor: (id) => sectionFor(state, id),\n positionFor: (id) => positionFor(state, id),\n };\n}\n\nexport { createCollectionIndex, childLevelKey, ROOT_LEVEL_KEY, type CollectionIndex, type Level };\n"]}
1
+ {"version":3,"file":"collection-index.js","sourceRoot":"","sources":["../../src/internal/collection-index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListItem, ListSection } from \"../types.js\";\nimport { encodePart } from \"./keys.js\";\n\ntype Level = {\n path: string;\n items: ListItem[];\n expandableFlags: boolean[];\n};\n\ntype CollectionIndex = {\n isTree: boolean;\n groups: Level[];\n children: Map<string, Level>;\n itemAt: (levelPath: string, slot: number) => ListItem | undefined;\n sectionFor: (levelPath: string) => unknown;\n expandablePathsFor: (id: string) => string[];\n};\n\ntype IndexState = {\n isTree: boolean;\n groups: Level[];\n children: Map<string, Level>;\n levels: Map<string, Level>;\n expandablePaths: Map<string, string[]>;\n sectionValues: Map<string, unknown>;\n};\n\nconst NO_PATHS: string[] = [];\n\nconst hasChildren = (item: ListItem): boolean => item.children !== undefined && item.children.length > 0;\n\nfunction pushPath(table: Map<string, string[]>, id: string, path: string): void {\n const existing = table.get(id);\n\n if (existing === undefined) {\n table.set(id, [path]);\n\n return;\n }\n\n existing.push(path);\n}\n\nfunction collectChildren(state: IndexState, level: Level, slotPath: string, item: ListItem): void {\n const canExpand = hasChildren(item);\n level.expandableFlags.push(canExpand);\n\n if (!canExpand) {\n return;\n }\n\n pushPath(state.expandablePaths, item.id, slotPath);\n state.children.set(slotPath, collectLevel(state, slotPath, item.children ?? []));\n}\n\nfunction collectLevel(state: IndexState, path: string, items: ListItem[]): Level {\n const level: Level = { path, items, expandableFlags: [] };\n state.levels.set(path, level);\n\n if (!state.isTree) {\n return level;\n }\n\n for (const [slot, item] of items.entries()) {\n collectChildren(state, level, path + encodePart(String(slot)), item);\n }\n\n return level;\n}\n\nfunction buildGroups(state: IndexState, source: ListItem[], sections: ListSection[] | undefined): Level[] {\n if (sections === undefined) {\n return [collectLevel(state, encodePart(\"0\"), source)];\n }\n\n return sections.map((section, group) => {\n const path = encodePart(String(group));\n state.sectionValues.set(path, section.value);\n\n return collectLevel(state, path, section.data);\n });\n}\n\nfunction isTreeSource(source: ListItem[], sections: ListSection[] | undefined, isFlat: boolean): boolean {\n if (sections !== undefined || isFlat) {\n return false;\n }\n\n return source.some((item) => hasChildren(item));\n}\n\nfunction createCollectionIndex(\n items: ListItem[] | undefined,\n sections: ListSection[] | undefined,\n isFlat: boolean,\n): CollectionIndex {\n const source = items ?? [];\n\n const state: IndexState = {\n isTree: isTreeSource(source, sections, isFlat),\n groups: [],\n children: new Map(),\n levels: new Map(),\n expandablePaths: new Map(),\n sectionValues: new Map(),\n };\n\n state.groups = buildGroups(state, source, sections);\n\n return {\n isTree: state.isTree,\n groups: state.groups,\n children: state.children,\n itemAt: (levelPath, slot) => state.levels.get(levelPath)?.items[slot],\n sectionFor: (levelPath) => state.sectionValues.get(levelPath),\n expandablePathsFor: (id) => state.expandablePaths.get(id) ?? NO_PATHS,\n };\n}\n\nexport { createCollectionIndex, type CollectionIndex, type Level };\n"]}
@@ -1,12 +1,33 @@
1
+ import * as Gio from "@gtkx/gi/gio";
1
2
  import * as GObject from "@gtkx/gi/gobject";
2
3
  import * as Gtk from "@gtkx/gi/gtk";
3
4
  import type { CollectionIndex } from "./collection-index.js";
5
+ import type { TreeExpansion } from "./tree-expansion.js";
6
+ type LevelStore = Gio.ListModel & LazyLevelStore;
7
+ type SlotRef = {
8
+ store: LevelStore;
9
+ slot: number;
10
+ };
4
11
  type CollectionModel = {
5
12
  model: Gtk.FlattenListModel;
13
+ expansion: TreeExpansion;
6
14
  treeModel: () => Gtk.TreeListModel | null;
7
15
  sync: (index: CollectionIndex) => void;
8
16
  };
9
- declare function getId(value: GObject.Object | null): string | null;
17
+ declare function slotRefFor(value: GObject.Object | null): SlotRef | null;
18
+ declare function slotPathAt(store: LevelStore, slot: number): string;
10
19
  declare function createCollectionModel(): CollectionModel;
11
- export { createCollectionModel, getId, type CollectionModel };
20
+ declare class LazyLevelStore extends GObject.Object implements Gio.ListModelImpl {
21
+ itemsChanged: Gio.ListModel["itemsChanged"];
22
+ path: string;
23
+ refs: SlotRef[];
24
+ objects: (Gtk.StringObject | null)[];
25
+ childStores: (LevelStore | null)[];
26
+ expandableFlags: boolean[];
27
+ private createItem;
28
+ vfuncGetItemType(): bigint;
29
+ vfuncGetNItems(): number;
30
+ vfuncGetItem(position: number): GObject.Object | null;
31
+ }
32
+ export { createCollectionModel, slotPathAt, slotRefFor, type CollectionModel, type SlotRef };
12
33
  //# sourceMappingURL=collection-model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection-model.d.ts","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAS,MAAM,uBAAuB,CAAC;AAwBpE,KAAK,eAAe,GAAG;IACnB,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC1C,CAAC;AAMF,iBAAS,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAI1D;AAuLD,iBAAS,qBAAqB,IAAI,eAAe,CAmBhD;AAED,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"collection-model.d.ts","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAS,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,KAAK,UAAU,GAAG,GAAG,CAAC,SAAS,GAAG,cAAc,CAAC;AAEjD,KAAK,OAAO,GAAG;IACX,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAsBF,KAAK,eAAe,GAAG;IACnB,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC;IAC5B,SAAS,EAAE,aAAa,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC1C,CAAC;AAmCF,iBAAS,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAUhE;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAoPD,iBAAS,qBAAqB,IAAI,eAAe,CAsBhD;AAED,cAAM,cAAe,SAAQ,OAAO,CAAC,MAAO,YAAW,GAAG,CAAC,aAAa;IAC5D,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACpD,IAAI,SAAM;IACV,IAAI,EAAE,OAAO,EAAE,CAAM;IACrB,OAAO,EAAE,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAM;IAC1C,WAAW,EAAE,CAAC,UAAU,GAAG,IAAI,CAAC,EAAE,CAAM;IACxC,eAAe,EAAE,OAAO,EAAE,CAAM;IAEhC,OAAO,CAAC,UAAU;IAQlB,gBAAgB,IAAI,MAAM;IAI1B,cAAc,IAAI,MAAM;IAIxB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI;CASxD;AAED,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,OAAO,EAAE,CAAC"}
@@ -1,112 +1,186 @@
1
1
  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
- import { childLevelKey, ROOT_LEVEL_KEY } from "./collection-index.js";
5
- const OBJECT_CACHE_MAX = 1 << 20;
6
- const newStore = () => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });
7
- function getId(value) {
8
- const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;
9
- return item instanceof Gtk.StringObject ? item.getString() : null;
10
- }
11
- function objectFor(state, id) {
12
- const existing = state.objects.get(id);
13
- if (existing !== undefined) {
14
- return existing;
4
+ import { registerClass } from "@gtkx/runtime";
5
+ import { createCollectionIndex } from "./collection-index.js";
6
+ import { encodePart } from "./keys.js";
7
+ import { adoptIndex, createTreeExpansion, pruneSlots, resetExpansion } from "./tree-expansion.js";
8
+ const STORE_CLASS_KEY = Symbol.for("gtkx.components.lazy-level-store");
9
+ const SLOTS_KEY = Symbol.for("gtkx.components.lazy-level-store.slots");
10
+ const EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);
11
+ const SLOTS = sharedSlots();
12
+ const newRootStore = () => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });
13
+ function sharedSlots() {
14
+ const cached = Reflect.get(globalThis, SLOTS_KEY);
15
+ if (cached instanceof WeakMap) {
16
+ return cached;
15
17
  }
16
- const created = Gtk.StringObject.new(id);
17
- state.objects.set(id, created);
18
+ const created = new WeakMap();
19
+ Reflect.set(globalThis, SLOTS_KEY, created);
18
20
  return created;
19
21
  }
20
- function commonPrefix(previous, next, max) {
21
- let count = 0;
22
- while (count < max && previous[count] === next[count]) {
23
- count += 1;
22
+ function registeredStoreClass() {
23
+ const cached = Reflect.get(globalThis, STORE_CLASS_KEY);
24
+ if (typeof cached === "function") {
25
+ return cached;
24
26
  }
25
- return count;
27
+ registerClass(LazyLevelStore, { typeName: "GtkxLazyLevelStore", implements: [Gio.ListModel] });
28
+ Reflect.set(globalThis, STORE_CLASS_KEY, LazyLevelStore);
29
+ return LazyLevelStore;
26
30
  }
27
- function commonSuffix(previous, next, max) {
28
- let count = 0;
29
- while (count < max && previous[previous.length - 1 - count] === next[next.length - 1 - count]) {
30
- count += 1;
31
+ function slotRefFor(value) {
32
+ const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;
33
+ if (item === null) {
34
+ return null;
31
35
  }
32
- return count;
36
+ const ref = SLOTS.get(item);
37
+ return ref === undefined || ref.slot === -1 ? null : ref;
38
+ }
39
+ function slotPathAt(store, slot) {
40
+ return store.path + encodePart(String(slot));
33
41
  }
34
- function spliceRange(previous, next) {
35
- const shared = Math.min(previous.length, next.length);
36
- const start = commonPrefix(previous, next, shared);
37
- if (start === previous.length && start === next.length) {
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) {
38
50
  return null;
39
51
  }
40
- const tail = commonSuffix(previous, next, shared - start);
41
- return { start, removed: previous.length - start - tail, added: next.slice(start, next.length - tail) };
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);
42
62
  }
43
- function levelFor(state, key) {
44
- const existing = state.levels.get(key);
45
- if (existing !== undefined) {
46
- return existing;
63
+ function growStore(context, store, level) {
64
+ for (let slot = store.refs.length; slot < level.items.length; slot++) {
65
+ pushSlot(context, store, level, slot);
47
66
  }
48
- const created = { store: newStore(), ids: [], canExpand: new Map() };
49
- state.levels.set(key, created);
50
- return created;
51
67
  }
52
- function refreshExpandable(current, level) {
53
- const next = new Map();
54
- for (const [index, id] of level.ids.entries()) {
55
- const isWanted = level.isExpandable[index] ?? false;
56
- const previous = current.canExpand.get(id);
57
- next.set(id, isWanted);
58
- if (previous !== undefined && previous !== isWanted) {
59
- current.store.itemsChanged(index, 1, 1);
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;
72
+ }
73
+ function collectFlips(store, level) {
74
+ const overlap = Math.min(store.refs.length, level.items.length);
75
+ const flipped = new Set();
76
+ for (let slot = 0; slot < overlap; slot++) {
77
+ if ((store.expandableFlags[slot] ?? false) !== (level.expandableFlags[slot] ?? false)) {
78
+ flipped.add(slot);
60
79
  }
61
80
  }
62
- current.canExpand = next;
81
+ return flipped;
63
82
  }
64
- function didSpliceLevel(state, level) {
65
- const current = levelFor(state, level.key);
66
- const range = spliceRange(current.ids, level.ids);
67
- if (range === null) {
68
- return false;
83
+ function syncOverlap(context, store, level) {
84
+ const flipped = collectFlips(store, level);
85
+ if (flipped.size === 0) {
86
+ return flipped;
87
+ }
88
+ pruneSlots(context.expansion, store.path, (slot) => flipped.has(slot));
89
+ for (const slot of flipped) {
90
+ flipSlot(context, store, slot);
69
91
  }
70
- current.store.splice(range.start, range.removed, range.added.map((id) => objectFor(state, id)));
71
- current.ids = [...level.ids];
72
- return true;
92
+ return flipped;
73
93
  }
74
- function dropUnvisited(state, visited) {
75
- for (const key of state.levels.keys()) {
76
- if (!visited.has(key)) {
77
- state.levels.delete(key);
94
+ function detachRefs(store, nextLength) {
95
+ for (let slot = nextLength; slot < store.refs.length; slot++) {
96
+ const ref = store.refs[slot];
97
+ if (ref !== undefined) {
98
+ ref.slot = -1;
78
99
  }
79
100
  }
80
101
  }
81
- // Items keep their identity by id, so a collection that shrinks keeps its objects cached: filtering a long
82
- // list down and back up reuses them instead of rebuilding one GObject per row. Incremental filters shrink and
83
- // grow the list many times per keystroke, so the cache is only swept once it passes an absolute bound.
84
- function pruneObjects(state, index) {
85
- if (state.objects.size <= OBJECT_CACHE_MAX) {
102
+ function shrinkStore(context, store, nextLength) {
103
+ if (store.refs.length <= nextLength) {
86
104
  return;
87
105
  }
88
- for (const id of state.objects.keys()) {
89
- if (!index.has(id)) {
90
- state.objects.delete(id);
91
- }
106
+ detachRefs(store, nextLength);
107
+ pruneSlots(context.expansion, store.path, (slot) => slot >= nextLength);
108
+ store.refs.length = nextLength;
109
+ store.objects.length = nextLength;
110
+ store.childStores.length = nextLength;
111
+ store.expandableFlags.length = nextLength;
112
+ }
113
+ function emitTailSplice(store, previousLength, nextLength) {
114
+ if (nextLength < previousLength) {
115
+ store.itemsChanged(nextLength, previousLength - nextLength, 0);
116
+ return;
117
+ }
118
+ if (nextLength > previousLength) {
119
+ store.itemsChanged(previousLength, 0, nextLength - previousLength);
120
+ }
121
+ }
122
+ function extendRuns(runs, slot) {
123
+ const last = runs.at(-1);
124
+ if (last !== undefined && last.start + last.length === slot) {
125
+ last.length += 1;
126
+ return;
127
+ }
128
+ runs.push({ start: slot, length: 1 });
129
+ }
130
+ function collectFlipRuns(flipped) {
131
+ const runs = [];
132
+ for (const slot of flipped) {
133
+ extendRuns(runs, slot);
134
+ }
135
+ return runs;
136
+ }
137
+ function emitFlips(store, flipped) {
138
+ for (const run of collectFlipRuns(flipped)) {
139
+ store.itemsChanged(run.start, run.length, run.length);
140
+ }
141
+ }
142
+ function stepChildStore(context, store, slot, flipped) {
143
+ const child = store.childStores[slot];
144
+ if (child == null || flipped.has(slot)) {
145
+ return;
146
+ }
147
+ const level = context.index.children.get(slotPathAt(store, slot));
148
+ if (level !== undefined) {
149
+ syncLevel(context, child, level);
92
150
  }
93
151
  }
94
- function childStoreFor(state, object) {
95
- const id = getId(object);
96
- if (id === null) {
152
+ function syncLevel(context, store, level) {
153
+ const previousLength = store.refs.length;
154
+ const overlap = Math.min(previousLength, level.items.length);
155
+ const flipped = syncOverlap(context, store, level);
156
+ shrinkStore(context, store, level.items.length);
157
+ growStore(context, store, level);
158
+ emitTailSplice(store, previousLength, level.items.length);
159
+ emitFlips(store, flipped);
160
+ for (let slot = 0; slot < overlap; slot++) {
161
+ stepChildStore(context, store, slot, flipped);
162
+ }
163
+ }
164
+ function childStoreFor(object) {
165
+ const ref = slotRefFor(object);
166
+ if (ref === null) {
97
167
  return null;
98
168
  }
99
- return state.levels.get(childLevelKey(id))?.store ?? null;
169
+ return ref.store.childStores[ref.slot] ?? null;
100
170
  }
101
- function ensureTree(state) {
102
- state.tree ??= Gtk.TreeListModel.new(levelFor(state, ROOT_LEVEL_KEY).store, false, false, (object) => childStoreFor(state, object));
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;
175
+ }
103
176
  return state.tree;
104
177
  }
105
178
  function desiredRootModels(state, index) {
106
- if (index.isTree) {
107
- return [ensureTree(state)];
179
+ const [first] = state.groupStores;
180
+ if (first !== undefined && index.isTree) {
181
+ return [ensureTree(state, first)];
108
182
  }
109
- return index.groups.map((level) => levelFor(state, level.key).store);
183
+ return [...state.groupStores];
110
184
  }
111
185
  function hasSameModels(previous, next) {
112
186
  return previous.length === next.length && next.every((model, index) => previous[index] === model);
@@ -118,47 +192,85 @@ function syncRoot(state, index) {
118
192
  }
119
193
  state.root.splice(0, state.rootModels.length, next);
120
194
  state.rootModels = next;
195
+ resetExpansion(state.expansion);
196
+ }
197
+ function adjustGroupStores(state, context) {
198
+ const { groups } = context.index;
199
+ state.groupStores.length = Math.min(state.groupStores.length, groups.length);
200
+ 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);
204
+ }
205
+ }
206
+ function stepGroupStores(state, context, surviving) {
207
+ for (const [group, level] of context.index.groups.entries()) {
208
+ const store = state.groupStores[group];
209
+ if (store !== undefined && group < surviving) {
210
+ syncLevel(context, store, level);
211
+ }
212
+ }
121
213
  }
122
214
  function syncModel(state, index) {
123
- const levels = [...index.groups, ...index.children.values()];
124
- const visited = new Set();
125
- let didChange = false;
126
- for (const level of levels) {
127
- didChange = didSpliceLevel(state, level) || didChange;
128
- visited.add(level.key);
129
- }
130
- if (didChange || visited.size !== state.levels.size) {
131
- dropUnvisited(state, visited);
132
- pruneObjects(state, index);
133
- }
134
- syncRoot(state, index);
135
- refreshExpandableLevels(state, index, levels);
136
- }
137
- function refreshExpandableLevels(state, index, levels) {
138
- if (!index.isTree) {
139
- return;
215
+ const context = { index, expansion: state.expansion };
216
+ const surviving = Math.min(state.groupStores.length, index.groups.length);
217
+ state.expansion.isSyncing = true;
218
+ try {
219
+ adjustGroupStores(state, context);
220
+ syncRoot(state, index);
221
+ stepGroupStores(state, context, surviving);
140
222
  }
141
- for (const level of levels) {
142
- refreshExpandable(levelFor(state, level.key), level);
223
+ finally {
224
+ state.expansion.isSyncing = false;
143
225
  }
226
+ adoptIndex(state.expansion, index);
144
227
  }
145
228
  function createCollectionModel() {
146
- const root = newStore();
229
+ registeredStoreClass();
230
+ const root = newRootStore();
147
231
  const state = {
148
232
  root,
149
233
  rootModels: [],
150
234
  model: Gtk.FlattenListModel.new(root),
151
- objects: new Map(),
152
- levels: new Map(),
235
+ groupStores: [],
153
236
  tree: null,
237
+ treeRoot: null,
238
+ expansion: createTreeExpansion(EMPTY_INDEX),
154
239
  };
155
240
  return {
156
241
  model: state.model,
242
+ expansion: state.expansion,
157
243
  treeModel: () => state.tree,
158
244
  sync: (index) => {
159
245
  syncModel(state, index);
160
246
  },
161
247
  };
162
248
  }
163
- export { createCollectionModel, getId };
249
+ class LazyLevelStore extends GObject.Object {
250
+ path = "";
251
+ refs = [];
252
+ objects = [];
253
+ childStores = [];
254
+ expandableFlags = [];
255
+ createItem(position, ref) {
256
+ const created = Gtk.StringObject.new("");
257
+ this.objects[position] = created;
258
+ SLOTS.set(created, ref);
259
+ return created;
260
+ }
261
+ vfuncGetItemType() {
262
+ return GObject.TYPE_OBJECT;
263
+ }
264
+ vfuncGetNItems() {
265
+ return this.refs.length;
266
+ }
267
+ vfuncGetItem(position) {
268
+ const ref = this.refs[position];
269
+ if (ref === undefined) {
270
+ return null;
271
+ }
272
+ return this.objects[position] ?? this.createItem(position, ref);
273
+ }
274
+ }
275
+ export { createCollectionModel, slotPathAt, slotRefFor };
164
276
  //# sourceMappingURL=collection-model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA6BtE,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,CAAC;AAEjC,MAAM,QAAQ,GAAG,GAAkB,EAAE,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAE3F,SAAS,KAAK,CAAC,KAA4B;IACvC,MAAM,IAAI,GAAG,KAAK,YAAY,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAExE,OAAO,IAAI,YAAY,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB,EAAE,EAAU;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,QAAkB,EAAE,IAAc,EAAE,GAAW;IACjE,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,KAAK,IAAI,CAAC,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,QAAkB,EAAE,IAAc,EAAE,GAAW;IACjE,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;QAC5F,KAAK,IAAI,CAAC,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,QAAkB,EAAE,IAAc;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAEnD,IAAI,KAAK,KAAK,QAAQ,CAAC,MAAM,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;IAE1D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;AAC5G,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiB,EAAE,GAAW;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACjF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAmB,EAAE,KAAY;IACxD,MAAM,IAAI,GAAyB,IAAI,GAAG,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAEvB,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IAED,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;AAC7B,CAAC;AAED,SAAS,cAAc,CAAC,KAAiB,EAAE,KAAY;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAElD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7B,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB,EAAE,OAAoB;IAC1D,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;AACL,CAAC;AAED,2GAA2G;AAC3G,8GAA8G;AAC9G,uGAAuG;AACvG,SAAS,YAAY,CAAC,KAAiB,EAAE,KAAsB;IAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACzC,OAAO;IACX,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACjB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB,EAAE,MAAsB;IAC5D,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAEzB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;AAC9D,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB;IACjC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CACjG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAElC,OAAO,KAAK,CAAC,IAAI,CAAC;AACtB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB,EAAE,KAAsB;IAChE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,aAAa,CAAC,QAA0B,EAAE,IAAsB;IACrE,OAAO,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiB,EAAE,KAAsB;IACvD,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE7C,IAAI,aAAa,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO;IACX,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;AAC5B,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB,EAAE,KAAsB;IACxD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAgB,IAAI,GAAG,EAAE,CAAC;IACvC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,SAAS,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAClD,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9B,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACvB,uBAAuB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAiB,EAAE,KAAsB,EAAE,MAAe;IACvF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO;IACX,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,iBAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB;IAC1B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IAExB,MAAM,KAAK,GAAe;QACtB,IAAI;QACJ,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QACrC,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,IAAI,EAAE,IAAI;KACb,CAAC;IAEF,OAAO;QACH,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI;QAC3B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YACZ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;KACJ,CAAC;AACN,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAwB,CAAC","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport { childLevelKey, ROOT_LEVEL_KEY } from \"./collection-index.js\";\n\ntype LevelState = {\n store: Gio.ListStore;\n ids: string[];\n canExpand: Map<string, boolean>;\n};\n\ntype SpliceRange = {\n start: number;\n removed: number;\n added: string[];\n};\n\ntype ModelState = {\n root: Gio.ListStore;\n rootModels: GObject.Object[];\n model: Gtk.FlattenListModel;\n objects: Map<string, Gtk.StringObject>;\n levels: Map<string, LevelState>;\n tree: Gtk.TreeListModel | null;\n};\n\ntype CollectionModel = {\n model: Gtk.FlattenListModel;\n treeModel: () => Gtk.TreeListModel | null;\n sync: (index: CollectionIndex) => void;\n};\n\nconst OBJECT_CACHE_MAX = 1 << 20;\n\nconst newStore = (): Gio.ListStore => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });\n\nfunction getId(value: GObject.Object | null): string | null {\n const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;\n\n return item instanceof Gtk.StringObject ? item.getString() : null;\n}\n\nfunction objectFor(state: ModelState, id: string): Gtk.StringObject {\n const existing = state.objects.get(id);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const created = Gtk.StringObject.new(id);\n state.objects.set(id, created);\n\n return created;\n}\n\nfunction commonPrefix(previous: string[], next: string[], max: number): number {\n let count = 0;\n\n while (count < max && previous[count] === next[count]) {\n count += 1;\n }\n\n return count;\n}\n\nfunction commonSuffix(previous: string[], next: string[], max: number): number {\n let count = 0;\n\n while (count < max && previous[previous.length - 1 - count] === next[next.length - 1 - count]) {\n count += 1;\n }\n\n return count;\n}\n\nfunction spliceRange(previous: string[], next: string[]): SpliceRange | null {\n const shared = Math.min(previous.length, next.length);\n const start = commonPrefix(previous, next, shared);\n\n if (start === previous.length && start === next.length) {\n return null;\n }\n\n const tail = commonSuffix(previous, next, shared - start);\n\n return { start, removed: previous.length - start - tail, added: next.slice(start, next.length - tail) };\n}\n\nfunction levelFor(state: ModelState, key: string): LevelState {\n const existing = state.levels.get(key);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const created: LevelState = { store: newStore(), ids: [], canExpand: new Map() };\n state.levels.set(key, created);\n\n return created;\n}\n\nfunction refreshExpandable(current: LevelState, level: Level): void {\n const next: Map<string, boolean> = new Map();\n\n for (const [index, id] of level.ids.entries()) {\n const isWanted = level.isExpandable[index] ?? false;\n const previous = current.canExpand.get(id);\n next.set(id, isWanted);\n\n if (previous !== undefined && previous !== isWanted) {\n current.store.itemsChanged(index, 1, 1);\n }\n }\n\n current.canExpand = next;\n}\n\nfunction didSpliceLevel(state: ModelState, level: Level): boolean {\n const current = levelFor(state, level.key);\n const range = spliceRange(current.ids, level.ids);\n\n if (range === null) {\n return false;\n }\n\n current.store.splice(range.start, range.removed, range.added.map((id) => objectFor(state, id)));\n current.ids = [...level.ids];\n\n return true;\n}\n\nfunction dropUnvisited(state: ModelState, visited: Set<string>): void {\n for (const key of state.levels.keys()) {\n if (!visited.has(key)) {\n state.levels.delete(key);\n }\n }\n}\n\n// Items keep their identity by id, so a collection that shrinks keeps its objects cached: filtering a long\n// list down and back up reuses them instead of rebuilding one GObject per row. Incremental filters shrink and\n// grow the list many times per keystroke, so the cache is only swept once it passes an absolute bound.\nfunction pruneObjects(state: ModelState, index: CollectionIndex): void {\n if (state.objects.size <= OBJECT_CACHE_MAX) {\n return;\n }\n\n for (const id of state.objects.keys()) {\n if (!index.has(id)) {\n state.objects.delete(id);\n }\n }\n}\n\nfunction childStoreFor(state: ModelState, object: GObject.Object): Gio.ListStore | null {\n const id = getId(object);\n\n if (id === null) {\n return null;\n }\n\n return state.levels.get(childLevelKey(id))?.store ?? null;\n}\n\nfunction ensureTree(state: ModelState): Gtk.TreeListModel {\n state.tree ??= Gtk.TreeListModel.new(levelFor(state, ROOT_LEVEL_KEY).store, false, false, (object) =>\n childStoreFor(state, object));\n\n return state.tree;\n}\n\nfunction desiredRootModels(state: ModelState, index: CollectionIndex): GObject.Object[] {\n if (index.isTree) {\n return [ensureTree(state)];\n }\n\n return index.groups.map((level) => levelFor(state, level.key).store);\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 syncModel(state: ModelState, index: CollectionIndex): void {\n const levels = [...index.groups, ...index.children.values()];\n const visited: Set<string> = new Set();\n let didChange = false;\n\n for (const level of levels) {\n didChange = didSpliceLevel(state, level) || didChange;\n visited.add(level.key);\n }\n\n if (didChange || visited.size !== state.levels.size) {\n dropUnvisited(state, visited);\n pruneObjects(state, index);\n }\n\n syncRoot(state, index);\n refreshExpandableLevels(state, index, levels);\n}\n\nfunction refreshExpandableLevels(state: ModelState, index: CollectionIndex, levels: Level[]): void {\n if (!index.isTree) {\n return;\n }\n\n for (const level of levels) {\n refreshExpandable(levelFor(state, level.key), level);\n }\n}\n\nfunction createCollectionModel(): CollectionModel {\n const root = newStore();\n\n const state: ModelState = {\n root,\n rootModels: [],\n model: Gtk.FlattenListModel.new(root),\n objects: new Map(),\n levels: new Map(),\n tree: null,\n };\n\n return {\n model: state.model,\n treeModel: () => state.tree,\n sync: (index) => {\n syncModel(state, index);\n },\n };\n}\n\nexport { createCollectionModel, getId, type CollectionModel };\n"]}
1
+ {"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAoClG,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AACvE,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACvE,MAAM,WAAW,GAAG,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AACtE,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;AAE5B,MAAM,YAAY,GAAG,GAAkB,EAAE,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAE/F,SAAS,WAAW;IAChB,MAAM,MAAM,GAAY,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAE3D,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;QAC5B,OAAO,MAA0C,CAAC;IACtD,CAAC;IAED,MAAM,OAAO,GAAqC,IAAI,OAAO,EAAE,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAE5C,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,oBAAoB;IACzB,MAAM,MAAM,GAAY,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAEjE,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,MAA+B,CAAC;IAC3C,CAAC;IAED,aAAa,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;IAEzD,OAAO,cAAc,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,KAA4B;IAC5C,MAAM,IAAI,GAAG,KAAK,YAAY,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAExE,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE5B,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AAC7D,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB,EAAE,IAAY;IAC/C,OAAO,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC,EAAgB,CAAC;IAC3D,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAElB,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,OAAoB,EAAE,IAAY;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEjC,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,QAAQ,CAAC,OAAoB,EAAE,KAAiB,EAAE,KAAY,EAAE,IAAY;IACjF,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACjG,CAAC;AAED,SAAS,SAAS,CAAC,OAAoB,EAAE,KAAiB,EAAE,KAAY;IACpE,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACnE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,OAAoB,EAAE,KAAiB,EAAE,IAAY;IACnE,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;IAC1D,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnG,CAAC;AAED,SAAS,YAAY,CAAC,KAAiB,EAAE,KAAY;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,OAAO,GAAgB,IAAI,GAAG,EAAE,CAAC;IAEvC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACpF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,OAAoB,EAAE,KAAiB,EAAE,KAAY;IACtE,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE3C,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QACzB,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB,EAAE,UAAkB;IACrD,KAAK,IAAI,IAAI,GAAG,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE7B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QAClB,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,OAAoB,EAAE,KAAiB,EAAE,UAAkB;IAC5E,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAClC,OAAO;IACX,CAAC;IAED,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC9B,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC;IACxE,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;IAC/B,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC;IAClC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;IACtC,KAAK,CAAC,eAAe,CAAC,MAAM,GAAG,UAAU,CAAC;AAC9C,CAAC;AAED,SAAS,cAAc,CAAC,KAAiB,EAAE,cAAsB,EAAE,UAAkB;IACjF,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAC9B,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAE/D,OAAO;IACX,CAAC;IAED,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAC9B,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,EAAE,UAAU,GAAG,cAAc,CAAC,CAAC;IACvE,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,IAAe,EAAE,IAAY;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAEjB,OAAO;IACX,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,OAAoB;IACzC,MAAM,IAAI,GAAc,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB,EAAE,OAAoB;IACtD,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,OAAoB,EAAE,KAAiB,EAAE,IAAY,EAAE,OAAoB;IAC/F,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAElE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,OAAoB,EAAE,KAAiB,EAAE,KAAY;IACpE,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACnD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChD,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1D,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACxC,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,MAAsB;IACzC,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAE/B,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACnD,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB,EAAE,KAAiB;IACpD,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3F,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC3B,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC;AACtB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB,EAAE,KAAsB;IAChE,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;IAElC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,aAAa,CAAC,QAA0B,EAAE,IAAsB;IACrE,OAAO,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiB,EAAE,KAAsB;IACvD,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE7C,IAAI,aAAa,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO;IACX,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IACxB,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB,EAAE,OAAoB;IAC9D,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IACjC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAE7E,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,KAAiB,EAAE,OAAoB,EAAE,SAAiB;IAC/E,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YAC3C,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB,EAAE,KAAsB;IACxD,MAAM,OAAO,GAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1E,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;IAEjC,IAAI,CAAC;QACD,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACvB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;YAAS,CAAC;QACP,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,KAAK,CAAC;IACtC,CAAC;IAED,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,qBAAqB;IAC1B,oBAAoB,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAE5B,MAAM,KAAK,GAAe;QACtB,IAAI;QACJ,UAAU,EAAE,EAAE;QACd,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QACrC,WAAW,EAAE,EAAE;QACf,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC;KAC9C,CAAC;IAEF,OAAO;QACH,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI;QAC3B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YACZ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;KACJ,CAAC;AACN,CAAC;AAED,MAAM,cAAe,SAAQ,OAAO,CAAC,MAAM;IAEvC,IAAI,GAAG,EAAE,CAAC;IACV,IAAI,GAAc,EAAE,CAAC;IACrB,OAAO,GAAgC,EAAE,CAAC;IAC1C,WAAW,GAA0B,EAAE,CAAC;IACxC,eAAe,GAAc,EAAE,CAAC;IAExB,UAAU,CAAC,QAAgB,EAAE,GAAY;QAC7C,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAExB,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,gBAAgB;QACZ,OAAO,OAAO,CAAC,WAAW,CAAC;IAC/B,CAAC;IAED,cAAc;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,YAAY,CAAC,QAAgB;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEhC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACpE,CAAC;CACJ;AAED,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,UAAU,EAAsC,CAAC","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,18 +1,15 @@
1
- import type * as Gtk from "@gtkx/gi/gtk";
2
- import type { Item } from "../types.js";
1
+ import type { ListItem } from "../types.js";
3
2
  import type { CollectionIndex } from "./collection-index.js";
4
- import type { CollectionModel } from "./collection-model.js";
5
- type Collection = {
6
- isTree: boolean;
7
- model: Gtk.FlattenListModel;
8
- treeModel: () => Gtk.TreeListModel | null;
9
- itemFor: (id: string) => Item | undefined;
10
- sectionFor: (id: string) => unknown;
3
+ import type { CollectionModel, SlotRef } from "./collection-model.js";
4
+ type Collection = Pick<CollectionModel, "model" | "expansion" | "treeModel"> & {
5
+ itemAt: (ref: SlotRef) => ListItem | undefined;
6
+ sectionFor: (levelPath: string) => unknown;
11
7
  idAt: (position: number) => string | null;
8
+ pathAt: (position: number) => string | null;
12
9
  positionFor: (id: string) => number;
13
10
  positionsFor: (ids: string[]) => number[];
14
11
  };
15
- declare function eachRow(tree: Gtk.TreeListModel, visit: (row: Gtk.TreeListRow, id: string | null) => void): void;
16
- declare function createCollection(gtk: CollectionModel, index: CollectionIndex): Collection;
17
- export { createCollection, eachRow, type Collection };
12
+ declare function isCollectionIdle(collection: Collection): boolean;
13
+ declare function createCollection(collectionModel: CollectionModel, index: CollectionIndex): Collection;
14
+ export { createCollection, isCollectionIdle, type Collection };
18
15
  //# sourceMappingURL=collection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,KAAK,UAAU,GAAG;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;IAC1C,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACpC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1C,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CAC7C,CAAC;AAkBF,iBAAS,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAIxG;AAoDD,iBAAS,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAWlF;AAED,OAAO,EAAE,gBAAgB,EAAE,OAAO,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,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"}