dirvi-lib 0.7.0 → 0.8.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 (72) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/tree-surfer/cursor.d.ts +52 -26
  5. package/dist/tree-surfer/cursor.d.ts.map +1 -1
  6. package/dist/tree-surfer/cursor.js +19 -44
  7. package/dist/tree-surfer/fold-node/fold-node.arb.d.ts +2 -0
  8. package/dist/tree-surfer/fold-node/fold-node.arb.d.ts.map +1 -0
  9. package/dist/tree-surfer/fold-node/fold-node.arb.js +1 -0
  10. package/dist/tree-surfer/fold-node/fold-node.impl.d.ts +3 -4
  11. package/dist/tree-surfer/fold-node/fold-node.impl.d.ts.map +1 -1
  12. package/dist/tree-surfer/fold-node/fold-node.impl.js +73 -67
  13. package/dist/tree-surfer/fold-node/fold-node.schema.d.ts +3 -5
  14. package/dist/tree-surfer/fold-node/fold-node.schema.d.ts.map +1 -1
  15. package/dist/tree-surfer/fold-node/fold-node.schema.js +2 -9
  16. package/dist/tree-surfer/fold-node/fold-node.types.d.ts +169 -46
  17. package/dist/tree-surfer/fold-node/fold-node.types.d.ts.map +1 -1
  18. package/dist/tree-surfer/fold-node/tree-node.test.d.ts +2 -0
  19. package/dist/tree-surfer/fold-node/tree-node.test.d.ts.map +1 -0
  20. package/dist/tree-surfer/fold-node/tree-node.test.js +90 -0
  21. package/dist/tree-surfer/index.d.ts +3 -1
  22. package/dist/tree-surfer/index.d.ts.map +1 -1
  23. package/dist/tree-surfer/index.js +3 -1
  24. package/dist/tree-surfer/nav-node/nav-node.impl.d.ts +5 -5
  25. package/dist/tree-surfer/nav-node/nav-node.impl.d.ts.map +1 -1
  26. package/dist/tree-surfer/nav-node/nav-node.impl.js +84 -99
  27. package/dist/tree-surfer/nav-node/nav-node.types.d.ts +62 -34
  28. package/dist/tree-surfer/nav-node/nav-node.types.d.ts.map +1 -1
  29. package/dist/tree-surfer/nav-node/nav-node.types.js +1 -3
  30. package/dist/tree-surfer/state/state.impl.d.ts +7 -0
  31. package/dist/tree-surfer/state/state.impl.d.ts.map +1 -0
  32. package/dist/tree-surfer/state/state.impl.js +89 -0
  33. package/dist/tree-surfer/state/state.schemas.d.ts +9 -0
  34. package/dist/tree-surfer/state/state.schemas.d.ts.map +1 -0
  35. package/dist/tree-surfer/state/state.schemas.js +8 -0
  36. package/dist/tree-surfer/state/state.types.d.ts +21 -0
  37. package/dist/tree-surfer/state/state.types.d.ts.map +1 -0
  38. package/dist/tree-surfer/state/state.types.js +1 -0
  39. package/dist/tree-surfer/tree-node/tree-node.arb.d.ts +82 -17
  40. package/dist/tree-surfer/tree-node/tree-node.arb.d.ts.map +1 -1
  41. package/dist/tree-surfer/tree-node/tree-node.arb.debug.test.d.ts +2 -0
  42. package/dist/tree-surfer/tree-node/tree-node.arb.debug.test.d.ts.map +1 -0
  43. package/dist/tree-surfer/tree-node/tree-node.arb.debug.test.js +34 -0
  44. package/dist/tree-surfer/tree-node/tree-node.arb.js +164 -56
  45. package/dist/tree-surfer/tree-node/tree-node.impl.d.ts +1 -1
  46. package/dist/tree-surfer/tree-node/tree-node.impl.d.ts.map +1 -1
  47. package/dist/tree-surfer/tree-node/tree-node.impl.js +41 -48
  48. package/dist/tree-surfer/tree-node/tree-node.schemas.d.ts +2 -2
  49. package/dist/tree-surfer/tree-node/tree-node.schemas.d.ts.map +1 -1
  50. package/dist/tree-surfer/tree-node/tree-node.schemas.js +2 -2
  51. package/dist/tree-surfer/tree-node/tree-node.test.js +144 -76
  52. package/dist/tree-surfer/tree-node/tree-node.types.d.ts +89 -107
  53. package/dist/tree-surfer/tree-node/tree-node.types.d.ts.map +1 -1
  54. package/dist/tree-surfer-ui/application/intent-to-effect.d.ts +6 -2
  55. package/dist/tree-surfer-ui/application/intent-to-effect.d.ts.map +1 -1
  56. package/dist/tree-surfer-ui/application/intent-to-effect.js +1 -6
  57. package/dist/tree-surfer-ui/application/user-input-to-intent.d.ts +10 -2
  58. package/dist/tree-surfer-ui/application/user-input-to-intent.d.ts.map +1 -1
  59. package/dist/tree-surfer-ui/application/user-input-to-intent.js +12 -5
  60. package/dist/tree-surfer-ui/domain/effect.d.ts +9 -8
  61. package/dist/tree-surfer-ui/domain/effect.d.ts.map +1 -1
  62. package/dist/tree-surfer-ui/domain/index.d.ts +1 -1
  63. package/dist/tree-surfer-ui/domain/index.d.ts.map +1 -1
  64. package/dist/tree-surfer-ui/domain/index.js +1 -1
  65. package/dist/tree-surfer-ui/domain/{input-state.d.ts → input-mode-state.d.ts} +2 -2
  66. package/dist/tree-surfer-ui/domain/input-mode-state.d.ts.map +1 -0
  67. package/package.json +3 -2
  68. package/dist/tree-surfer/state.d.ts +0 -25
  69. package/dist/tree-surfer/state.d.ts.map +0 -1
  70. package/dist/tree-surfer/state.js +0 -118
  71. package/dist/tree-surfer-ui/domain/input-state.d.ts.map +0 -1
  72. /package/dist/tree-surfer-ui/domain/{input-state.js → input-mode-state.js} +0 -0
@@ -1,70 +1,193 @@
1
- import { TreeNodeModifier, TreeNodeSelector } from '../tree-node/tree-node.types.js';
1
+ import { SerializableKey, TreeNodeApi } from '../tree-node/tree-node.types.js';
2
2
  /**
3
- * The whole fold state for a tree-node tree.
3
+ * A node in the fold-state tree.
4
4
  *
5
- * The root has no ID because it represents the fold at the root.
6
- * Its `children` contain the fold nodes for the forest's root entries.
5
+ * @remarks
7
6
  *
8
- * `folds` contains the IDs folded at this root. Fold order is not
9
- * represented here; the buffer tree determines entry order.
7
+ * A fold-state tree is a sparse projection of a buffer tree. Apart from its
8
+ * root, it stores only nodes that are folded or that have fold information
9
+ * somewhere below them. It does not contain buffer entries or buffer-specific
10
+ * properties.
11
+ *
12
+ * The `id` identifies the corresponding buffer entry among its siblings.
13
+ *
14
+ * `children` contains fold-state nodes for direct buffer entries that are not
15
+ * folded at this node but have fold information below them.
16
+ *
17
+ * `foldedChildren` contains fold-state nodes for direct buffer entries whose contents
18
+ * are folded at this node. Each folded entry is represented by a complete
19
+ * `FoldNode`, allowing fold state within a folded entry to be preserved
20
+ * recursively.
21
+ *
22
+ * A direct buffer entry with no fold state at or below it is omitted from both
23
+ * collections. Consequently, the union of `children` and `foldedChildren` does not
24
+ * need to contain every direct buffer child.
25
+ *
26
+ * The following invariant holds for every fold-state node:
27
+ *
28
+ * - no ID occurs more than once in `children`;
29
+ * - no ID occurs more than once in `foldedChildren`;
30
+ * - no ID occurs in both collections;
31
+ * - every ID in either collection identifies a direct child in the
32
+ * corresponding buffer-tree node.
33
+ *
34
+ * Every fold node is an open branch from the perspective of `TreeNodeApi`.
35
+ * Missing paths may nevertheless be created lazily by `FoldNodeService`.
36
+ *
37
+ * @typeParam Id - The type of IDs in the actual tree nodes.
38
+ *
39
+ * @example
40
+ *
41
+ * ```ts
42
+ * type FileId = string;
43
+ * type FileFoldNode = FoldNode<FileId>;
44
+ *
45
+ * const root: FileFoldNode = {
46
+ * id: '/',
47
+ * children: [],
48
+ * foldedChildren: [],
49
+ * };
50
+ * ```
10
51
  */
11
- export type FoldNodeRoot<Id extends PropertyKey> = {
52
+ export type FoldNode<Id extends SerializableKey> = {
53
+ id: Id;
12
54
  children: FoldNode<Id>[];
13
- folds: ReadonlySet<Id>;
55
+ foldedChildren: FoldNode<Id>[];
14
56
  };
15
57
  /**
16
- * Fold state associated with a node in the buffer tree.
58
+ * Operations for inspecting and immutably updating a fold-state tree.
59
+ *
60
+ * @remarks
61
+ *
62
+ * This API is `TreeNodeApi` specialized for `FoldNode`. It provides structural
63
+ * tree operations such as node lookup and immutable path updates.
64
+ *
65
+ * Paths are relative to the supplied root node:
66
+ *
67
+ * - `[]` identifies the root;
68
+ * - `['child']` identifies a direct child of the root;
69
+ * - `['child', 'grandchild']` identifies a descendant.
17
70
  *
18
- * A fold node has the shape of an open tree node: its children are always
19
- * represented by an array, and an empty `children` array means that no child
20
- * fold nodes are currently represented.
71
+ * Path operations are strict. They operate only on nodes that already exist
72
+ * in the fold-state tree. Use `FoldNodeService` when missing fold-state nodes
73
+ * should be automatically created.
21
74
  *
22
- * The `folds` set contains the IDs of entries folded at this node. Fold
23
- * order is not represented here; the buffer tree determines entry order.
75
+ * The API does not interpret the `foldedChildren` collection. It only navigates and
76
+ * updates the structural `children` tree. The semantic operations for adding
77
+ * and removing foldedChildren belong to `FoldNodeService`.
24
78
  *
25
- * The type is structurally compatible with `TreeNode`, allowing the shared
26
- * `TreeNodeApi` to be used for path traversal and immutable updates.
79
+ * @typeParam Id - The type of IDs in the actual tree nodes.
27
80
  */
28
- export type FoldNode<Id extends PropertyKey> = FoldNodeRoot<Id> & {
29
- id: Id;
30
- };
81
+ export type FoldNodeApi<Id extends SerializableKey> = TreeNodeApi<Id, FoldNode<Id>>;
31
82
  /**
32
- * Operations for navigating and immutably updating fold-tree structure.
83
+ * Semantic operations for managing fold state.
84
+ *
85
+ * @remarks
86
+ *
87
+ * `FoldNodeService` provides operations in terms of folded buffer entries
88
+ * rather than generic tree-node updates.
33
89
  *
34
- * This API is a projection of `TreeNodeApi` onto the fold-tree
35
- * representation. Path operations are strict: they only operate on
36
- * paths that already exist. Creation of missing fold paths belongs to
37
- * `FoldNodeService`.
90
+ * Paths are relative to the supplied root node:
91
+ *
92
+ * - `[]` addresses the root
93
+ * - `['child']` addresses a direct child of the root;
94
+ * - `['child', 'grandchild']` addresses a descendant.
95
+ *
96
+ * Lookup and removal operations are strict and return `undefined` when the
97
+ * requested path does not exist. Adding a folded entry may create missing
98
+ * fold-state nodes along the requested path.
99
+ *
100
+ * @typeParam Id - The type of IDs in the actual tree nodes.
38
101
  */
39
- export type FoldNodeApi<Id extends PropertyKey> = {
102
+ export type FoldNodeService<Id extends SerializableKey> = {
40
103
  /**
41
- * Returns the children of either the fold root or a fold node.
104
+ * Creates an empty fold-state node.
105
+ *
106
+ * It has no structural children and no folded entries.
107
+ *
108
+ * @returns A new empty fold-state node.
42
109
  */
43
- getChildren(node: FoldNodeRoot<Id> | FoldNode<Id>): Iterable<FoldNode<Id>>;
110
+ createEmptyNode(id: Id): FoldNode<Id>;
44
111
  /**
45
- * Returns a direct child by ID.
112
+ * Tests whether a node is folded.
113
+ *
114
+ * The path identifies the node whose `foldedChildren` collection is inspected. An
115
+ * empty path selects the root.
116
+ *
117
+ * This operation does not create missing fold-state nodes, or otherwise
118
+ * mutate the `rootNode`.
119
+ *
120
+ * @param rootNode - The root of the fold-state tree.
121
+ * @param path - A path relative to `rootNode`.
122
+ * @param entryId - The ID of the direct buffer entry to test.
123
+ * @returns `true` when the entry is folded at the resolved node;
124
+ * otherwise `false`. Missing paths also return `false`.
46
125
  */
47
- getChildById(node: FoldNodeRoot<Id> | FoldNode<Id>, id: Id): FoldNode<Id> | undefined;
126
+ getIfEntryFoldedAtPath(rootNode: FoldNode<Id>, path: readonly Id[], entryId: Id): boolean;
48
127
  /**
49
- * Selects a fold node at a path below the root.
128
+ * Returns the IDs of folded entries at the node at the path.
129
+ *
130
+ * Returns undefined if path has no fold node.
50
131
  */
51
- getAtPath<Result>(rootNode: FoldNodeRoot<Id>, path: Id[], selector: TreeNodeSelector<FoldNode<Id>, Result>): Result | undefined;
132
+ foldedEntriesAtPath(rootNode: FoldNode<Id>, path: readonly Id[]): Id[] | undefined;
52
133
  /**
53
- * Immutably modifies a fold node at a path below the root.
134
+ * Marks a direct buffer entry as folded at a node.
135
+ *
136
+ * Missing fold-state nodes along the path are created. If the entry is
137
+ * already folded, the existing fold-state tree is returned unchanged.
138
+ * If the entry is currently in `children`, it is moved to `foldedChildren` while
139
+ * preserving its nested fold state.
140
+ *
141
+ * Moving an entry preserves its nested `children` and `foldedChildren`, so fold
142
+ * state below the newly folded entry is not lost.
143
+ *
144
+ * @param rootNode - The root of the fold-state tree.
145
+ * @param path - A path relative to `rootNode`. An empty path selects the
146
+ * root.
147
+ * @param entryId - The ID of the direct buffer entry to fold.
148
+ * @returns A new root containing the fold, or `undefined` when the path
149
+ * cannot be updated.
54
150
  */
55
- modifyAtPath(rootNode: FoldNodeRoot<Id>, path: Id[], modifier: TreeNodeModifier<FoldNode<Id>>): FoldNodeRoot<Id> | undefined;
56
- };
57
- /**
58
- * Semantic operations for managing folded buffer entries.
59
- *
60
- * Unlike `FoldNodeApi`, the service may create missing fold paths when
61
- * adding a fold. This allows an empty root to be populated lazily.
62
- */
63
- export type FoldNodeService<Id extends PropertyKey> = {
64
- createEmptyRoot(): FoldNodeRoot<Id>;
65
- getIfEntryFoldedAtPath(rootNode: FoldNodeRoot<Id>, path: Id[], entryId: Id): boolean;
66
- addFoldedEntryAtPath(rootNode: FoldNodeRoot<Id>, path: Id[], entryId: Id): FoldNodeRoot<Id> | undefined;
67
- removeFoldedEntryAtPath(rootNode: FoldNodeRoot<Id>, path: Id[], entryId: Id): FoldNodeRoot<Id> | undefined;
68
- clearFoldedEntriesAtPath(rootNode: FoldNodeRoot<Id>, path: Id[]): FoldNodeRoot<Id> | undefined;
151
+ addFoldedEntryAtPath(rootNode: FoldNode<Id>, path: readonly Id[], entryId: Id): FoldNode<Id> | undefined;
152
+ /**
153
+ * Removes the folded state for a direct buffer entry at a node.
154
+ *
155
+ * The entry is removed from `foldedChildren`. If the entry contains nested fold
156
+ * state in either its `children` or `foldedChildren` collections, it is moved to
157
+ * `children` so that the nested state is preserved. If it has no nested
158
+ * fold state, it is omitted from both collections.
159
+ *
160
+ * This operation does not create missing fold-state nodes. If the entry is
161
+ * not currently folded, the existing fold-state tree is returned unchanged.
162
+ *
163
+ * @param rootNode - The root of the fold-state tree.
164
+ * @param path - A path relative to `rootNode`. An empty path selects the
165
+ * root.
166
+ * @param entryId - The ID of the direct buffer entry to unfold.
167
+ * @returns A new root without the fold, or `undefined` when the path does
168
+ * not exist.
169
+ */
170
+ removeFoldedEntryAtPath(rootNode: FoldNode<Id>, path: readonly Id[], entryId: Id): FoldNode<Id> | undefined;
171
+ /**
172
+ * Removes the folded state for all direct buffer entries at a node.
173
+ *
174
+ * Each entry is removed from `foldedChildren`. Entries that contain nested
175
+ * fold state in either their `children` or `foldedChildren` collections are
176
+ * moved to `children` so that their nested fold state is preserved. Entries
177
+ * with no nested fold state are omitted from both collections.
178
+ *
179
+ * This operation does not create missing fold-state nodes. If the path does
180
+ * not exist, the existing fold-state tree cannot be updated and `undefined`
181
+ * is returned. When the resolved node has no folded entries, the existing
182
+ * fold-state tree is returned unchanged.
183
+ *
184
+ * @param rootNode - The root of the fold-state tree.
185
+ * @param path - A path relative to `rootNode`. An empty path selects the
186
+ * root.
187
+ * @returns A new root without the folds at the resolved node, or
188
+ * `undefined` when the path does not exist.
189
+ */
190
+ clearFoldedEntriesAtPath(rootNode: FoldNode<Id>, path: readonly Id[]): FoldNode<Id> | undefined;
191
+ clearFoldedEntriesAtPath(rootNode: FoldNode<Id>, path: readonly Id[]): FoldNode<Id> | undefined;
69
192
  };
70
193
  //# sourceMappingURL=fold-node.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fold-node.types.d.ts","sourceRoot":"","sources":["../../../src/tree-surfer/fold-node/fold-node.types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,iCAAiC,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,CAAC,EAAE,SAAS,WAAW,IAAI;IACjD,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;CACxB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,CAAC,EAAE,SAAS,WAAW,IAAI,YAAY,CAAC,EAAE,CAAC,GAAG;IAChE,EAAE,EAAE,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,WAAW,IAAI;IAChD;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAE3E;;OAEG;IACH,YAAY,CACV,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,EACrC,EAAE,EAAE,EAAE,GACL,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,SAAS,CAAC,MAAM,EACd,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,EACV,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,GAC/C,MAAM,GAAG,SAAS,CAAC;IAEtB;;OAEG;IACH,YAAY,CACV,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,EACV,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,GACvC,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,WAAW,IAAI;IACpD,eAAe,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC;IAEpC,sBAAsB,CACpB,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAEX,oBAAoB,CAClB,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,GACV,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEhC,uBAAuB,CACrB,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,GACV,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEhC,wBAAwB,CACtB,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAC1B,IAAI,EAAE,EAAE,EAAE,GACT,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CACjC,CAAC"}
1
+ {"version":3,"file":"fold-node.types.d.ts","sourceRoot":"","sources":["../../../src/tree-surfer/fold-node/fold-node.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAM,MAAM,QAAQ,CAAC,EAAE,SAAS,eAAe,IAAI;IACjD,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACzB,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,eAAe,IAAI,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,eAAe,IAAI;IACxD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;OAcG;IACH,sBAAsB,CACpB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAEX;;;;OAIG;IACH,mBAAmB,CACjB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,GAClB,EAAE,EAAE,GAAG,SAAS,CAAC;IAEpB;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAAoB,CAClB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE5B;;;;;;;;;;;;;;;;;OAiBG;IACH,uBAAuB,CACrB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE5B;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBAAwB,CACtB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,GAClB,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAC5B,wBAAwB,CACtB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,IAAI,EAAE,SAAS,EAAE,EAAE,GAClB,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CAC7B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tree-node.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-node.test.d.ts","sourceRoot":"","sources":["../../../src/tree-surfer/fold-node/tree-node.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createTreeNodeApi } from '../tree-node/tree-node.impl.js';
3
+ import { createFoldNodeService } from './fold-node.impl.js';
4
+ const foldNodeApi = createTreeNodeApi();
5
+ const service = createFoldNodeService(foldNodeApi);
6
+ describe('createFoldNodeService', () => {
7
+ it('UT: adds a new entry to foldedChildren', () => {
8
+ const root = service.createEmptyNode(0);
9
+ const updated = service.addFoldedEntryAtPath(root, [], 0);
10
+ expect(updated).toStrictEqual({
11
+ id: 0,
12
+ children: [],
13
+ foldedChildren: [
14
+ {
15
+ id: 0,
16
+ children: [],
17
+ foldedChildren: [],
18
+ },
19
+ ],
20
+ });
21
+ });
22
+ it('UT: moves an existing structural entry to foldedChildren', () => {
23
+ const child = {
24
+ id: 1,
25
+ children: [],
26
+ foldedChildren: [],
27
+ };
28
+ const root = {
29
+ id: 0,
30
+ children: [child],
31
+ foldedChildren: [],
32
+ };
33
+ const updated = service.addFoldedEntryAtPath(root, [], 1);
34
+ expect(updated).toStrictEqual({
35
+ id: 0,
36
+ children: [],
37
+ foldedChildren: [child],
38
+ });
39
+ });
40
+ it('UT: preserves nested fold state when moving an entry', () => {
41
+ const nestedChild = {
42
+ id: 2,
43
+ children: [],
44
+ foldedChildren: [],
45
+ };
46
+ const child = {
47
+ id: 1,
48
+ children: [],
49
+ foldedChildren: [nestedChild],
50
+ };
51
+ const root = {
52
+ id: 0,
53
+ children: [child],
54
+ foldedChildren: [],
55
+ };
56
+ const updated = service.addFoldedEntryAtPath(root, [], 1);
57
+ expect(updated).toStrictEqual({
58
+ id: 0,
59
+ children: [],
60
+ foldedChildren: [
61
+ {
62
+ id: 1,
63
+ children: [],
64
+ foldedChildren: [nestedChild],
65
+ },
66
+ ],
67
+ });
68
+ expect(updated?.foldedChildren[0]).toBe(child);
69
+ expect(updated?.foldedChildren[0]?.foldedChildren[0]).toBe(nestedChild);
70
+ });
71
+ it('UT: rejects a path through a folded entry', () => {
72
+ const foldedChild = {
73
+ id: 1,
74
+ children: [],
75
+ foldedChildren: [],
76
+ };
77
+ const root = {
78
+ id: 0,
79
+ children: [],
80
+ foldedChildren: [foldedChild],
81
+ };
82
+ const updated = service.addFoldedEntryAtPath(root, [1], 2);
83
+ expect(updated).toBeUndefined();
84
+ expect(root).toStrictEqual({
85
+ id: 0,
86
+ children: [],
87
+ foldedChildren: [foldedChild],
88
+ });
89
+ });
90
+ });
@@ -7,5 +7,7 @@ export * from './tree-node/tree-node.impl.js';
7
7
  export * from './tree-node/tree-node.schemas.js';
8
8
  export * from './tree-node/tree-node.types.js';
9
9
  export * from './cursor.js';
10
- export * from './state.js';
10
+ export * from './state/state.impl.js';
11
+ export * from './state/state.schemas.js';
12
+ export * from './state/state.types.js';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tree-surfer/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAE/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAE/C,cAAc,aAAa,CAAC;AAE5B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tree-surfer/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAE/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAE/C,cAAc,aAAa,CAAC;AAE5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC"}
@@ -7,4 +7,6 @@ export * from './tree-node/tree-node.impl.js';
7
7
  export * from './tree-node/tree-node.schemas.js';
8
8
  export * from './tree-node/tree-node.types.js';
9
9
  export * from './cursor.js';
10
- export * from './state.js';
10
+ export * from './state/state.impl.js';
11
+ export * from './state/state.schemas.js';
12
+ export * from './state/state.types.js';
@@ -1,6 +1,6 @@
1
- import { SerializableKey, TreeNode, TreeNodeApi } from '../tree-node/tree-node.types.js';
2
- import { FoldNodeApi } from '../fold-node/fold-node.types.js';
3
- import { CursorApi } from '../cursor.js';
4
- import { NavNodeApi } from './nav-node.types.js';
5
- export declare function createNavNodeApi<Id extends SerializableKey, BufferNode extends TreeNode<Id, BufferNode>>(treeNodeApi: TreeNodeApi<Id, BufferNode>, foldNodeApi: FoldNodeApi<Id>, cursorApi: CursorApi<Id>): NavNodeApi<Id, BufferNode>;
1
+ import type { SerializableKey, TreeNode, TreeNodeApi } from '../tree-node/tree-node.types.js';
2
+ import type { FoldNodeService } from '../fold-node/fold-node.types.js';
3
+ import type { CursorApi } from '../cursor.js';
4
+ import type { NavNodeApi } from './nav-node.types.js';
5
+ export declare function createNavNodeApi<Id extends SerializableKey, Node extends TreeNode<Id, Node>>(treeNodeApi: TreeNodeApi<Id, Node>, foldNodeService: FoldNodeService<Id>, cursorApi: CursorApi<Id>): NavNodeApi<Id, Node>;
6
6
  //# sourceMappingURL=nav-node.impl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nav-node.impl.d.ts","sourceRoot":"","sources":["../../../src/tree-surfer/nav-node/nav-node.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,QAAQ,EACR,WAAW,EACZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAgB,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAU,SAAS,EAAc,MAAM,cAAc,CAAC;AAC7D,OAAO,EAKL,UAAU,EACX,MAAM,qBAAqB,CAAC;AAE7B,wBAAgB,gBAAgB,CAC9B,EAAE,SAAS,eAAe,EAC1B,UAAU,SAAS,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,EAE3C,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,UAAU,CAAC,EACxC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,EAC5B,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,GACvB,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAqP5B"}
1
+ {"version":3,"file":"nav-node.impl.d.ts","sourceRoot":"","sources":["../../../src/tree-surfer/nav-node/nav-node.impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,WAAW,EACZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAY,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAIV,UAAU,EACX,MAAM,qBAAqB,CAAC;AAE7B,wBAAgB,gBAAgB,CAC9B,EAAE,SAAS,eAAe,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,EAE/B,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,EAClC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,EACpC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,GACvB,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CA2RtB"}