dirvi-lib 0.8.1 → 0.9.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 (194) hide show
  1. package/dist/app/app-api.d.ts +74 -0
  2. package/dist/app/app-api.d.ts.map +1 -0
  3. package/dist/app/app-api.js +11 -0
  4. package/dist/app/effect-to-action.d.ts +6 -0
  5. package/dist/app/effect-to-action.d.ts.map +1 -0
  6. package/dist/app/effect-to-action.js +120 -0
  7. package/dist/app/index.d.ts +6 -0
  8. package/dist/app/index.d.ts.map +1 -0
  9. package/dist/app/index.js +5 -0
  10. package/dist/app/reducer-action.d.ts +40 -0
  11. package/dist/app/reducer-action.d.ts.map +1 -0
  12. package/dist/app/reducer.d.ts +5 -0
  13. package/dist/app/reducer.d.ts.map +1 -0
  14. package/dist/app/reducer.js +115 -0
  15. package/dist/app/view-api.d.ts +11 -0
  16. package/dist/app/view-api.d.ts.map +1 -0
  17. package/dist/feedback/feedback.impl.d.ts +9 -0
  18. package/dist/feedback/feedback.impl.d.ts.map +1 -0
  19. package/dist/feedback/feedback.impl.js +34 -0
  20. package/dist/feedback/feedback.types.d.ts +24 -0
  21. package/dist/feedback/feedback.types.d.ts.map +1 -0
  22. package/dist/feedback/index.d.ts +3 -0
  23. package/dist/feedback/index.d.ts.map +1 -0
  24. package/dist/feedback/index.js +1 -0
  25. package/dist/index.d.ts +5 -7
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +5 -7
  28. package/dist/input/application/index.d.ts.map +1 -0
  29. package/dist/input/application/intent-to-effect-no-state.test.d.ts.map +1 -0
  30. package/dist/input/application/intent-to-effect.d.ts +14 -0
  31. package/dist/input/application/intent-to-effect.d.ts.map +1 -0
  32. package/dist/{tree-surfer-ui → input}/application/intent-to-effect.js +66 -42
  33. package/dist/input/application/parse-command.d.ts +14 -0
  34. package/dist/input/application/parse-command.d.ts.map +1 -0
  35. package/dist/input/application/parse-command.js +92 -0
  36. package/dist/input/application/parse-normal-command.d.ts +12 -0
  37. package/dist/input/application/parse-normal-command.d.ts.map +1 -0
  38. package/dist/input/application/parse-normal-command.js +89 -0
  39. package/dist/input/application/tokenize-normal-command.d.ts +24 -0
  40. package/dist/input/application/tokenize-normal-command.d.ts.map +1 -0
  41. package/dist/input/application/tokenize-normal-command.js +110 -0
  42. package/dist/{tree-surfer-ui → input}/application/user-input-to-intent.d.ts +4 -2
  43. package/dist/input/application/user-input-to-intent.d.ts.map +1 -0
  44. package/dist/{tree-surfer-ui → input}/application/user-input-to-intent.js +9 -6
  45. package/dist/input/application/user-input-to-intent.test.d.ts.map +1 -0
  46. package/dist/input/domain/effect.d.ts +84 -0
  47. package/dist/input/domain/effect.d.ts.map +1 -0
  48. package/dist/input/domain/index.d.ts.map +1 -0
  49. package/dist/input/domain/input-mode-state.d.ts.map +1 -0
  50. package/dist/input/domain/intent.d.ts.map +1 -0
  51. package/dist/input/domain/user-input.d.ts.map +1 -0
  52. package/dist/trees/cursor.d.ts.map +1 -0
  53. package/dist/trees/fold-node/deprecated/fold-node.impl.d.ts +10 -0
  54. package/dist/trees/fold-node/deprecated/fold-node.impl.d.ts.map +1 -0
  55. package/dist/trees/fold-node/deprecated/fold-node.impl.js +248 -0
  56. package/dist/trees/fold-node/deprecated/fold-node.test.d.ts +2 -0
  57. package/dist/trees/fold-node/deprecated/fold-node.test.d.ts.map +1 -0
  58. package/dist/trees/fold-node/deprecated/fold-node.test.js +130 -0
  59. package/dist/{tree-surfer/fold-node → trees/fold-node/deprecated}/fold-node.types.d.ts +15 -76
  60. package/dist/trees/fold-node/deprecated/fold-node.types.d.ts.map +1 -0
  61. package/dist/trees/fold-node/fold-node.impl.d.ts +16 -0
  62. package/dist/trees/fold-node/fold-node.impl.d.ts.map +1 -0
  63. package/dist/trees/fold-node/fold-node.impl.js +472 -0
  64. package/dist/trees/fold-node/fold-node.model.d.ts +120 -0
  65. package/dist/trees/fold-node/fold-node.model.d.ts.map +1 -0
  66. package/dist/trees/fold-node/fold-node.model.js +80 -0
  67. package/dist/trees/fold-node/fold-node.types.d.ts +214 -0
  68. package/dist/trees/fold-node/fold-node.types.d.ts.map +1 -0
  69. package/dist/trees/fold-node/index.d.ts +4 -0
  70. package/dist/trees/fold-node/index.d.ts.map +1 -0
  71. package/dist/trees/fold-node/index.js +3 -0
  72. package/dist/trees/index.d.ts +9 -0
  73. package/dist/trees/index.d.ts.map +1 -0
  74. package/dist/trees/index.js +8 -0
  75. package/dist/trees/nav-node/nav-node.impl.d.ts +29 -0
  76. package/dist/trees/nav-node/nav-node.impl.d.ts.map +1 -0
  77. package/dist/{tree-surfer → trees}/nav-node/nav-node.impl.js +89 -42
  78. package/dist/trees/nav-node/nav-node.types.d.ts +103 -0
  79. package/dist/trees/nav-node/nav-node.types.d.ts.map +1 -0
  80. package/dist/trees/nav-node/nav-node.types.js +1 -0
  81. package/dist/trees/state/state.impl.d.ts +8 -0
  82. package/dist/trees/state/state.impl.d.ts.map +1 -0
  83. package/dist/trees/state/state.impl.js +128 -0
  84. package/dist/trees/state/state.schemas.d.ts +25 -0
  85. package/dist/trees/state/state.schemas.d.ts.map +1 -0
  86. package/dist/trees/state/state.schemas.js +17 -0
  87. package/dist/trees/state/state.types.d.ts +36 -0
  88. package/dist/trees/state/state.types.d.ts.map +1 -0
  89. package/dist/trees/state/state.types.js +1 -0
  90. package/dist/trees/tree-node/deprecated/tree-node.arb.d.ts.map +1 -0
  91. package/dist/trees/tree-node/deprecated/tree-node.arb.debug.test.d.ts.map +1 -0
  92. package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.arb.debug.test.js +1 -1
  93. package/dist/trees/tree-node/deprecated/tree-node.impl.d.ts.map +1 -0
  94. package/dist/trees/tree-node/deprecated/tree-node.schemas.d.ts.map +1 -0
  95. package/dist/trees/tree-node/deprecated/tree-node.test.d.ts.map +1 -0
  96. package/dist/trees/tree-node/deprecated/tree-node.types.d.ts.map +1 -0
  97. package/dist/trees/tree-node/deprecated/tree-node.types.js +1 -0
  98. package/dist/trees/tree-node/index.d.ts +5 -0
  99. package/dist/trees/tree-node/index.d.ts.map +1 -0
  100. package/dist/trees/tree-node/index.js +2 -0
  101. package/dist/trees/tree-node/tree-node.arb.d.ts +104 -0
  102. package/dist/trees/tree-node/tree-node.arb.d.ts.map +1 -0
  103. package/dist/trees/tree-node/tree-node.arb.js +191 -0
  104. package/dist/trees/tree-node/tree-node.impl.d.ts +15 -0
  105. package/dist/trees/tree-node/tree-node.impl.d.ts.map +1 -0
  106. package/dist/trees/tree-node/tree-node.impl.js +286 -0
  107. package/dist/trees/tree-node/tree-node.model.d.ts +78 -0
  108. package/dist/trees/tree-node/tree-node.model.d.ts.map +1 -0
  109. package/dist/trees/tree-node/tree-node.model.js +37 -0
  110. package/dist/trees/tree-node/tree-node.types.d.ts +419 -0
  111. package/dist/trees/tree-node/tree-node.types.d.ts.map +1 -0
  112. package/dist/trees/tree-node/tree-node.types.js +1 -0
  113. package/package.json +1 -1
  114. package/dist/tree-surfer/cursor.d.ts.map +0 -1
  115. package/dist/tree-surfer/fold-node/fold-node.arb.d.ts +0 -2
  116. package/dist/tree-surfer/fold-node/fold-node.arb.d.ts.map +0 -1
  117. package/dist/tree-surfer/fold-node/fold-node.impl.d.ts +0 -4
  118. package/dist/tree-surfer/fold-node/fold-node.impl.d.ts.map +0 -1
  119. package/dist/tree-surfer/fold-node/fold-node.impl.js +0 -149
  120. package/dist/tree-surfer/fold-node/fold-node.schema.d.ts +0 -5
  121. package/dist/tree-surfer/fold-node/fold-node.schema.d.ts.map +0 -1
  122. package/dist/tree-surfer/fold-node/fold-node.schema.js +0 -9
  123. package/dist/tree-surfer/fold-node/fold-node.types.d.ts.map +0 -1
  124. package/dist/tree-surfer/fold-node/tree-node.test.d.ts.map +0 -1
  125. package/dist/tree-surfer/fold-node/tree-node.test.js +0 -90
  126. package/dist/tree-surfer/index.d.ts +0 -13
  127. package/dist/tree-surfer/index.d.ts.map +0 -1
  128. package/dist/tree-surfer/index.js +0 -12
  129. package/dist/tree-surfer/nav-node/nav-node.impl.d.ts +0 -6
  130. package/dist/tree-surfer/nav-node/nav-node.impl.d.ts.map +0 -1
  131. package/dist/tree-surfer/nav-node/nav-node.types.d.ts +0 -70
  132. package/dist/tree-surfer/nav-node/nav-node.types.d.ts.map +0 -1
  133. package/dist/tree-surfer/state/state.impl.d.ts +0 -7
  134. package/dist/tree-surfer/state/state.impl.d.ts.map +0 -1
  135. package/dist/tree-surfer/state/state.impl.js +0 -89
  136. package/dist/tree-surfer/state/state.schemas.d.ts +0 -9
  137. package/dist/tree-surfer/state/state.schemas.d.ts.map +0 -1
  138. package/dist/tree-surfer/state/state.schemas.js +0 -8
  139. package/dist/tree-surfer/state/state.types.d.ts +0 -21
  140. package/dist/tree-surfer/state/state.types.d.ts.map +0 -1
  141. package/dist/tree-surfer/tree-node/tree-node.arb.d.ts.map +0 -1
  142. package/dist/tree-surfer/tree-node/tree-node.arb.debug.test.d.ts.map +0 -1
  143. package/dist/tree-surfer/tree-node/tree-node.impl.d.ts.map +0 -1
  144. package/dist/tree-surfer/tree-node/tree-node.schemas.d.ts.map +0 -1
  145. package/dist/tree-surfer/tree-node/tree-node.test.d.ts +0 -2
  146. package/dist/tree-surfer/tree-node/tree-node.test.d.ts.map +0 -1
  147. package/dist/tree-surfer/tree-node/tree-node.types.d.ts.map +0 -1
  148. package/dist/tree-surfer-ui/application/index.d.ts.map +0 -1
  149. package/dist/tree-surfer-ui/application/intent-to-effect-no-state.test.d.ts.map +0 -1
  150. package/dist/tree-surfer-ui/application/intent-to-effect.d.ts +0 -10
  151. package/dist/tree-surfer-ui/application/intent-to-effect.d.ts.map +0 -1
  152. package/dist/tree-surfer-ui/application/parse-command.d.ts +0 -4
  153. package/dist/tree-surfer-ui/application/parse-command.d.ts.map +0 -1
  154. package/dist/tree-surfer-ui/application/parse-command.js +0 -48
  155. package/dist/tree-surfer-ui/application/user-input-to-intent.d.ts.map +0 -1
  156. package/dist/tree-surfer-ui/application/user-input-to-intent.test.d.ts.map +0 -1
  157. package/dist/tree-surfer-ui/domain/effect.d.ts +0 -43
  158. package/dist/tree-surfer-ui/domain/effect.d.ts.map +0 -1
  159. package/dist/tree-surfer-ui/domain/index.d.ts.map +0 -1
  160. package/dist/tree-surfer-ui/domain/input-mode-state.d.ts.map +0 -1
  161. package/dist/tree-surfer-ui/domain/intent.d.ts.map +0 -1
  162. package/dist/tree-surfer-ui/domain/user-input.d.ts.map +0 -1
  163. /package/dist/{tree-surfer-ui/domain/effect.js → app/reducer-action.js} +0 -0
  164. /package/dist/{tree-surfer-ui/domain/input-mode-state.js → app/view-api.js} +0 -0
  165. /package/dist/{tree-surfer-ui/domain/intent.js → feedback/feedback.types.js} +0 -0
  166. /package/dist/{tree-surfer-ui → input}/application/index.d.ts +0 -0
  167. /package/dist/{tree-surfer-ui → input}/application/index.js +0 -0
  168. /package/dist/{tree-surfer-ui → input}/application/intent-to-effect-no-state.test.d.ts +0 -0
  169. /package/dist/{tree-surfer-ui → input}/application/intent-to-effect-no-state.test.js +0 -0
  170. /package/dist/{tree-surfer-ui → input}/application/user-input-to-intent.test.d.ts +0 -0
  171. /package/dist/{tree-surfer-ui → input}/application/user-input-to-intent.test.js +0 -0
  172. /package/dist/{tree-surfer-ui/domain/user-input.js → input/domain/effect.js} +0 -0
  173. /package/dist/{tree-surfer-ui → input}/domain/index.d.ts +0 -0
  174. /package/dist/{tree-surfer-ui → input}/domain/index.js +0 -0
  175. /package/dist/{tree-surfer-ui → input}/domain/input-mode-state.d.ts +0 -0
  176. /package/dist/{tree-surfer/fold-node/fold-node.arb.js → input/domain/input-mode-state.js} +0 -0
  177. /package/dist/{tree-surfer-ui → input}/domain/intent.d.ts +0 -0
  178. /package/dist/{tree-surfer/fold-node/fold-node.types.js → input/domain/intent.js} +0 -0
  179. /package/dist/{tree-surfer-ui → input}/domain/user-input.d.ts +0 -0
  180. /package/dist/{tree-surfer/nav-node/nav-node.types.js → input/domain/user-input.js} +0 -0
  181. /package/dist/{tree-surfer → trees}/cursor.d.ts +0 -0
  182. /package/dist/{tree-surfer → trees}/cursor.js +0 -0
  183. /package/dist/{tree-surfer/state/state.types.js → trees/fold-node/deprecated/fold-node.types.js} +0 -0
  184. /package/dist/{tree-surfer/tree-node/tree-node.types.js → trees/fold-node/fold-node.types.js} +0 -0
  185. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.arb.d.ts +0 -0
  186. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.arb.debug.test.d.ts +0 -0
  187. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.arb.js +0 -0
  188. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.impl.d.ts +0 -0
  189. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.impl.js +0 -0
  190. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.schemas.d.ts +0 -0
  191. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.schemas.js +0 -0
  192. /package/dist/{tree-surfer/fold-node → trees/tree-node/deprecated}/tree-node.test.d.ts +0 -0
  193. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.test.js +0 -0
  194. /package/dist/{tree-surfer/tree-node → trees/tree-node/deprecated}/tree-node.types.d.ts +0 -0
@@ -0,0 +1,214 @@
1
+ import type { SerializableKey } from '../tree-node/index.js';
2
+ import type { FoldSlotModel, FoldsModel } from './fold-node.model.js';
3
+ declare const foldsBrand: unique symbol;
4
+ /**
5
+ * A slot index within Folds.
6
+ *
7
+ * Index 0 is always occupied by the required primary fold tree.
8
+ *
9
+ * Other valid indexes are non-negative safe integers. TypeScript cannot
10
+ * represent that restriction for number, so indexes must be validated at
11
+ * runtime at API boundaries.
12
+ */
13
+ export type FoldIndex = number;
14
+ /**
15
+ * Public user-facing metadata for a fold tree.
16
+ *
17
+ * Every fold tree has a name. `description: null` means that no description
18
+ * has been supplied. An empty string is distinct: it is a supplied
19
+ * description with no text.
20
+ */
21
+ export type FoldInfo = Readonly<{
22
+ /**
23
+ * Durable user-facing name of the fold tree.
24
+ */
25
+ name: string;
26
+ /**
27
+ * User-facing description of the fold tree, or `null` when none exists.
28
+ */
29
+ description: string | null;
30
+ }>;
31
+ /**
32
+ * Immutable collection of fold-data slots for one source node tree.
33
+ *
34
+ * Every contained fold tree uses the same ID paths as the source TreeNode
35
+ * tree. Slot zero always contains a fold tree.
36
+ */
37
+ export type Folds<Id extends SerializableKey> = {
38
+ readonly [foldsBrand]: {
39
+ readonly id: Id;
40
+ };
41
+ };
42
+ export type FoldsApi<Id extends SerializableKey> = Readonly<{
43
+ /**
44
+ * Creates Folds with its required primary fold tree in slot zero.
45
+ *
46
+ * The new fold tree initially contains no hidden entries and is active.
47
+ */
48
+ create(rootId: Id, initialPrimaryInfo: FoldInfo): Folds<Id>;
49
+ /**
50
+ * Returns the occupied slot index for a unique fold-tree name.
51
+ *
52
+ * Returns `undefined` when no occupied fold tree has the name, or when the
53
+ * name is ambiguous. Fold-tree names should be kept unique so they remain
54
+ * durable user-facing references.
55
+ */
56
+ getIndexByName(folds: Folds<Id>, name: string): FoldIndex | undefined;
57
+ /**
58
+ * Returns metadata for the fold tree at an occupied slot.
59
+ *
60
+ * Index zero always returns FoldInfo for a valid Folds value.
61
+ */
62
+ getInfoAtIndex(folds: Folds<Id>, index: FoldIndex): FoldInfo | undefined;
63
+ /**
64
+ * Returns whether the fold tree at an occupied slot is active.
65
+ *
66
+ * Returns `undefined` when the slot is unoccupied.
67
+ */
68
+ isActiveAtIndex(folds: Folds<Id>, index: FoldIndex): boolean | undefined;
69
+ /**
70
+ * Returns whether a slot is occupied.
71
+ *
72
+ * For valid Folds values, `hasAtIndex(folds, 0)` is always true.
73
+ */
74
+ hasAtIndex(folds: Folds<Id>, index: FoldIndex): boolean;
75
+ /**
76
+ * Returns occupied slot indexes.
77
+ *
78
+ * The ordering is ascending slot order.
79
+ */
80
+ indexes(folds: Folds<Id>): Iterable<FoldIndex>;
81
+ /**
82
+ * Stores a serialized occupied fold slot at an index.
83
+ *
84
+ * Replaces any existing slot at that index. The supplied `Folds` value is not
85
+ * mutated.
86
+ *
87
+ * `foldData` is converted into the internal opaque fold-tree representation.
88
+ * This operation returns `undefined` when `index` is not a non-negative safe
89
+ * integer or when the slot's fold-tree model cannot be restored.
90
+ *
91
+ * This is a low-level operation. Most callers should use
92
+ * `setAdditionalFoldAtIndex`, `updateInfoAtIndex`, or the fold-state
93
+ * operations instead.
94
+ */
95
+ setAtIndex(folds: Folds<Id>, index: FoldIndex, foldData: FoldSlotModel<Id>): Folds<Id> | undefined;
96
+ /**
97
+ * Creates or replaces a non-primary fold tree at a slot.
98
+ *
99
+ * The new fold tree initially contains no hidden entries.
100
+ *
101
+ * This operation rejects index zero because the required primary fold tree
102
+ * must not be replaced accidentally.
103
+ */
104
+ setAdditionalFoldAtIndex(folds: Folds<Id>, index: FoldIndex, rootId: Id, info: FoldInfo): Folds<Id> | undefined;
105
+ /**
106
+ * Removes a non-primary fold tree from a slot.
107
+ *
108
+ * Returns `undefined` when `index` is zero because the primary fold tree may
109
+ * not be removed.
110
+ *
111
+ * Returns the original `Folds` reference when the non-primary slot is already
112
+ * unoccupied.
113
+ */
114
+ removeAdditionalFoldAtIndex(folds: Folds<Id>, index: FoldIndex): Folds<Id> | undefined;
115
+ /**
116
+ * Replaces supplied user-facing metadata while preserving the fold tree.
117
+ *
118
+ * Omitted properties are left unchanged.
119
+ *
120
+ * - `description: string` sets or replaces the description.
121
+ * - `description: null` clears the description.
122
+ */
123
+ updateInfoAtIndex(folds: Folds<Id>, index: FoldIndex, update: Readonly<{
124
+ name?: string;
125
+ description?: string | null;
126
+ }>): Folds<Id> | undefined;
127
+ /**
128
+ * Marks the fold tree at an occupied slot as active.
129
+ *
130
+ * An active fold tree contributes to hiding entries.
131
+ *
132
+ * Returns `undefined` when the slot is unoccupied. Returns the original
133
+ * Folds reference when the fold tree is already active.
134
+ */
135
+ activateAtIndex(folds: Folds<Id>, index: FoldIndex): Folds<Id> | undefined;
136
+ /**
137
+ * Marks the fold tree at an occupied slot as inactive.
138
+ *
139
+ * An inactive fold tree retains its definition but does not contribute to
140
+ * hiding entries.
141
+ *
142
+ * Returns `undefined` when the slot is unoccupied. Returns the original
143
+ * Folds reference when the fold tree is already inactive.
144
+ */
145
+ deactivateAtIndex(folds: Folds<Id>, index: FoldIndex): Folds<Id> | undefined;
146
+ /**
147
+ * Inverts whether the fold tree at an occupied slot is active.
148
+ *
149
+ * Returns `undefined` when the slot is unoccupied.
150
+ */
151
+ toggleActiveAtIndex(folds: Folds<Id>, index: FoldIndex): Folds<Id> | undefined;
152
+ /**
153
+ * Returns whether an entry is hidden by one fold tree at an occupied slot.
154
+ *
155
+ * This checks the fold definition regardless of whether that fold tree is
156
+ * currently active.
157
+ */
158
+ isEntryHiddenInFoldAtPath(folds: Folds<Id>, index: FoldIndex, path: readonly Id[], entryId: Id): boolean;
159
+ /**
160
+ * Returns whether an entry is hidden by at least one active fold tree.
161
+ *
162
+ * Inactive fold trees retain fold definitions but do not contribute to this
163
+ * result.
164
+ */
165
+ isEntryHiddenAtPath(folds: Folds<Id>, path: readonly Id[], entryId: Id): boolean;
166
+ /**
167
+ * Returns IDs hidden directly at a branch path in one fold tree.
168
+ */
169
+ hiddenEntryIdsAtPath(folds: Folds<Id>, index: FoldIndex, path: readonly Id[]): Iterable<Id> | undefined;
170
+ /**
171
+ * Marks an entry as hidden at a branch path in one fold tree.
172
+ */
173
+ hideEntryAtPath(folds: Folds<Id>, index: FoldIndex, path: readonly Id[], entryId: Id): Folds<Id> | undefined;
174
+ /**
175
+ * Removes hidden state for an entry at a branch path in one fold tree.
176
+ */
177
+ showEntryAtPath(folds: Folds<Id>, index: FoldIndex, path: readonly Id[], entryId: Id): Folds<Id> | undefined;
178
+ /**
179
+ * Shows every entry hidden directly at the branch addressed by `path`.
180
+ *
181
+ * This removes all hidden-entry IDs at that fold-tree node but retains
182
+ * descendant fold-tree nodes and their fold state.
183
+ *
184
+ * For example, given:
185
+ *
186
+ * root
187
+ * └── src
188
+ * hiddenEntryIds: ["lib", "main.ts"]
189
+ * └── lib
190
+ * hiddenEntryIds: ["parser.ts"]
191
+ *
192
+ * showAllHiddenEntriesAtPath(folds, index, ["src"]) produces:
193
+ *
194
+ * root
195
+ * └── src
196
+ * hiddenEntryIds: []
197
+ * └── lib
198
+ * hiddenEntryIds: ["parser.ts"]
199
+ */
200
+ showAllHiddenEntriesAtPath(folds: Folds<Id>, index: FoldIndex, path: readonly Id[]): Folds<Id> | undefined;
201
+ /**
202
+ * Converts opaque runtime folds into a serializable fold-state model.
203
+ */
204
+ toModel(folds: Folds<Id>): FoldsModel<Id>;
205
+ /**
206
+ * Restores opaque runtime folds from a validated serialized model.
207
+ *
208
+ * This validates fold-internal invariants, but does not validate that paths
209
+ * correspond to a specific source node tree.
210
+ */
211
+ fromModel(model: FoldsModel<Id>): Folds<Id> | undefined;
212
+ }>;
213
+ export {};
214
+ //# sourceMappingURL=fold-node.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold-node.types.d.ts","sourceRoot":"","sources":["../../../src/trees/fold-node/fold-node.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC9B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,KAAK,CAAC,EAAE,SAAS,eAAe,IAAI;IAC9C,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE;QACrB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,EAAE,SAAS,eAAe,IAAI,QAAQ,CAAC;IAC1D;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,kBAAkB,EAAE,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;IAE5D;;;;;;OAMG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAEtE;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAEzE;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAEzE;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IAExD;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAG/C;;;;;;;;;;;;;OAaG;IACH,UAAU,CACR,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,GAC1B,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;;;OAOG;IACH,wBAAwB,CACtB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,QAAQ,GACb,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;;;;OAQG;IACH,2BAA2B,CACzB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,GACf,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;;;OAOG;IACH,iBAAiB,CACf,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,QAAQ,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,CAAC,GACD,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;;;OAOG;IACH,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE3E;;;;;;;;OAQG;IACH,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE7E;;;;OAIG;IACH,mBAAmB,CACjB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,GACf,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;OAKG;IACH,yBAAyB,CACvB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAEX;;;;;OAKG;IACH,mBAAmB,CACjB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAEX;;OAEG;IACH,oBAAoB,CAClB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,GAClB,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,eAAe,CACb,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;OAEG;IACH,eAAe,CACb,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,EACnB,OAAO,EAAE,EAAE,GACV,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,0BAA0B,CACxB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAChB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,SAAS,EAAE,EAAE,GAClB,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAE1C;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CACzD,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './fold-node.impl.js';
2
+ export * from './fold-node.model.js';
3
+ export * from './fold-node.types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trees/fold-node/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './fold-node.impl.js';
2
+ export * from './fold-node.model.js';
3
+ export * from './fold-node.types.js';
@@ -0,0 +1,9 @@
1
+ export * from './fold-node/index.js';
2
+ export * from './nav-node/nav-node.impl.js';
3
+ export * from './nav-node/nav-node.types.js';
4
+ export * from './tree-node/index.js';
5
+ export * from './cursor.js';
6
+ export * from './state/state.impl.js';
7
+ export * from './state/state.schemas.js';
8
+ export * from './state/state.types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/trees/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AAErC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,sBAAsB,CAAC;AAErC,cAAc,aAAa,CAAC;AAE5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from './fold-node/index.js';
2
+ export * from './nav-node/nav-node.impl.js';
3
+ export * from './nav-node/nav-node.types.js';
4
+ export * from './tree-node/index.js';
5
+ export * from './cursor.js';
6
+ export * from './state/state.impl.js';
7
+ export * from './state/state.schemas.js';
8
+ export * from './state/state.types.js';
@@ -0,0 +1,29 @@
1
+ import type { SerializableKey, TreeNodeApi } from '../tree-node/index.js';
2
+ import type { FoldsApi } from '../fold-node/index.js';
3
+ import type { CursorApi } from '../cursor.js';
4
+ import type { NavNodeApi } from './nav-node.types.js';
5
+ export type NavEntryComparator<Id extends SerializableKey, Value> = (left: Readonly<{
6
+ id: Id;
7
+ value: Value;
8
+ }>, right: Readonly<{
9
+ id: Id;
10
+ value: Value;
11
+ }>) => number;
12
+ export type CreateNavNodeApiOptions<Id extends SerializableKey, Value> = Readonly<{
13
+ /**
14
+ * Defines display and cursor-navigation order among sibling entries.
15
+ *
16
+ * For deterministic navigation, this should define a total order for
17
+ * distinct sibling entries. If two entries compare equal, their order falls
18
+ * back to the source TreeNode child iteration order.
19
+ */
20
+ compareEntries: NavEntryComparator<Id, Value>;
21
+ }>;
22
+ /**
23
+ * Creates operations for projecting an opaque tree into a navigation model.
24
+ *
25
+ * Navigation ordering is intentionally a UI concern. The underlying TreeNode
26
+ * API need not promise a particular child-storage representation or ordering.
27
+ */
28
+ export declare function createNavNodeApi<Id extends SerializableKey, Value>(treeNodeApi: TreeNodeApi<Id, Value>, foldsApi: FoldsApi<Id>, cursorApi: CursorApi<Id>, options: CreateNavNodeApiOptions<Id, Value>): NavNodeApi<Id, Value>;
29
+ //# sourceMappingURL=nav-node.impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav-node.impl.d.ts","sourceRoot":"","sources":["../../../src/trees/nav-node/nav-node.impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAY,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAIV,UAAU,EACX,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,kBAAkB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,IAAI,CAClE,IAAI,EAAE,QAAQ,CAAC;IACb,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,KAAK,CAAC;CACd,CAAC,EACF,KAAK,EAAE,QAAQ,CAAC;IACd,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,KAAK,CAAC;CACd,CAAC,KACC,MAAM,CAAC;AAEZ,MAAM,MAAM,uBAAuB,CACjC,EAAE,SAAS,eAAe,EAC1B,KAAK,IACH,QAAQ,CAAC;IACX;;;;;;OAMG;IACH,cAAc,EAAE,kBAAkB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;CAC/C,CAAC,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAChE,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,EACnC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EACtB,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,EACxB,OAAO,EAAE,uBAAuB,CAAC,EAAE,EAAE,KAAK,CAAC,GAC1C,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CA8UvB"}
@@ -1,17 +1,40 @@
1
- export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
1
+ /**
2
+ * Creates operations for projecting an opaque tree into a navigation model.
3
+ *
4
+ * Navigation ordering is intentionally a UI concern. The underlying TreeNode
5
+ * API need not promise a particular child-storage representation or ordering.
6
+ */
7
+ export function createNavNodeApi(treeNodeApi, foldsApi, cursorApi, options) {
2
8
  function entryIsBranch(entry) {
3
9
  return 'children' in entry;
4
10
  }
11
+ function compareTreeNodes(left, right) {
12
+ return options.compareEntries({
13
+ id: treeNodeApi.id(left),
14
+ value: treeNodeApi.value(left),
15
+ }, {
16
+ id: treeNodeApi.id(right),
17
+ value: treeNodeApi.value(right),
18
+ });
19
+ }
20
+ /**
21
+ * Projects loaded children into navigation entries.
22
+ *
23
+ * Folded source entries are omitted from `entries` and represented in the
24
+ * synthetic `folded` row instead.
25
+ */
5
26
  function createNavNode(entries, foldRoot, parentPath) {
6
27
  const visibleEntries = [];
7
28
  const foldedEntries = [];
8
- const foldedEntryIds = foldRoot === undefined
9
- ? undefined
10
- : foldNodeService.foldedEntriesAtPath(foldRoot, parentPath);
11
- for (const entry of entries) {
12
- const entryPath = [...parentPath, entry.id];
13
- const isFolded = foldRoot !== undefined &&
14
- foldNodeService.getIfEntryFoldedAtPath(foldRoot, parentPath, entry.id);
29
+ /*
30
+ * Navigation owns presentation order, so materialize and sort the child
31
+ * iterable before projecting it.
32
+ */
33
+ const orderedEntries = [...entries].sort(compareTreeNodes);
34
+ for (const entry of orderedEntries) {
35
+ const entryId = treeNodeApi.id(entry);
36
+ const entryPath = [...parentPath, entryId];
37
+ const isFolded = foldsApi.isEntryHiddenAtPath(foldRoot, parentPath, entryId);
15
38
  const navigationEntry = createNavEntry(entry, foldRoot, entryPath);
16
39
  if (isFolded) {
17
40
  foldedEntries.push(navigationEntry);
@@ -22,7 +45,11 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
22
45
  }
23
46
  return {
24
47
  entries: visibleEntries,
25
- folded: foldedEntryIds === undefined || foldedEntryIds.length === 0
48
+ /*
49
+ * Fold state may contain entries that are not currently available in the
50
+ * loaded source tree. Do not render an empty synthetic row for them.
51
+ */
52
+ folded: foldedEntries.length === 0
26
53
  ? null
27
54
  : {
28
55
  entries: foldedEntries,
@@ -30,23 +57,32 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
30
57
  };
31
58
  }
32
59
  function createNavEntry(entry, foldRoot, entryPath) {
33
- if (treeNodeApi.isLeaf(entry)) {
34
- return {
35
- id: entry.id,
36
- };
37
- }
38
- return createNavBranch(entry, foldRoot, entryPath);
60
+ return treeNodeApi.match(entry, {
61
+ leaf: ({ id }) => ({
62
+ id,
63
+ }),
64
+ unloadedBranch: ({ id }) => ({
65
+ id,
66
+ children: null,
67
+ }),
68
+ loadedBranch: ({ id, children }) => ({
69
+ id,
70
+ children: createNavNode(children, foldRoot, entryPath),
71
+ }),
72
+ });
39
73
  }
40
- function createNavBranch(entry, foldRoot, entryPath) {
41
- if (!treeNodeApi.isBranch(entry)) {
42
- throw new Error('Navigation root must be a branch');
43
- }
44
- return {
45
- id: entry.id,
46
- children: entry.children === null
47
- ? null
48
- : createNavNode(entry.children, foldRoot, entryPath),
49
- };
74
+ function createRootNavBranch(root, foldRoot) {
75
+ return treeNodeApi.match(root, {
76
+ leaf: () => undefined,
77
+ unloadedBranch: ({ id }) => ({
78
+ id,
79
+ children: null,
80
+ }),
81
+ loadedBranch: ({ id, children }) => ({
82
+ id,
83
+ children: createNavNode(children, foldRoot, []),
84
+ }),
85
+ });
50
86
  }
51
87
  function rootCursors(rootNode) {
52
88
  if (rootNode.children === null) {
@@ -68,24 +104,24 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
68
104
  }
69
105
  const navNodeApi = {
70
106
  entryIsBranch,
71
- // Return a nav node from the TreeNode and FoldNode trees.
72
107
  from(root, foldRoot) {
73
- return createNavBranch(root, foldRoot, []);
108
+ return createRootNavBranch(root, foldRoot);
74
109
  },
75
110
  getNodeAtPath(navigation, path) {
76
111
  const [currentId, ...remainingPath] = path;
77
- // An empty path identifies the current node.
112
+ /*
113
+ * An empty path identifies the current navigation node.
114
+ */
78
115
  if (currentId === undefined) {
79
116
  return navigation;
80
117
  }
81
118
  const entry = navigation.entries.find((candidate) => candidate.id === currentId);
82
- if (entry === undefined) {
83
- return undefined;
84
- }
85
- if (!entryIsBranch(entry)) {
119
+ if (entry === undefined || !entryIsBranch(entry)) {
86
120
  return undefined;
87
121
  }
88
- // The directory has not been loaded/opened.
122
+ /*
123
+ * A null value represents a source branch whose children are not loaded.
124
+ */
89
125
  if (entry.children === null) {
90
126
  return undefined;
91
127
  }
@@ -93,6 +129,10 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
93
129
  },
94
130
  getEntryAtPath(navigation, path) {
95
131
  const [currentId, ...remainingPath] = path;
132
+ /*
133
+ * A NavNode does not itself correspond to a NavEntry. Therefore [] does
134
+ * not resolve to an entry.
135
+ */
96
136
  if (currentId === undefined) {
97
137
  return undefined;
98
138
  }
@@ -125,6 +165,7 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
125
165
  return cursors[currentIndex - 1];
126
166
  },
127
167
  cursorAfterFold(rootNode, cursor) {
168
+ // Folding root disallowed
128
169
  if (cursor.length === 0) {
129
170
  return undefined;
130
171
  }
@@ -133,18 +174,22 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
133
174
  if (currentIndex === -1) {
134
175
  return undefined;
135
176
  }
177
+ // If the last entry, then cursor should go to previous entry
178
+ // This works to go to the root when the last entry in the root is folded.
179
+ if (currentIndex + 1 === cursors.length) {
180
+ return cursors[currentIndex - 1];
181
+ }
136
182
  for (let index = currentIndex + 1; index < cursors.length; index += 1) {
137
183
  const candidate = cursors[index];
138
184
  if (candidate === undefined) {
139
185
  continue;
140
186
  }
187
+ // Skip any entries that are children of the entry about to be folded
141
188
  if (cursorApi.cursorBelongsToSubtree(candidate, cursor)) {
142
189
  continue;
143
190
  }
144
191
  return candidate;
145
192
  }
146
- // The fold row will be created at the end of this directory.
147
- return [...cursor];
148
193
  },
149
194
  parentCursor(_navigation, cursor) {
150
195
  if (cursor.length === 0) {
@@ -159,15 +204,17 @@ export function createNavNodeApi(treeNodeApi, foldNodeService, cursorApi) {
159
204
  const paths = [];
160
205
  for (const entry of navigation.entries) {
161
206
  const entryPath = [...parentPath, entry.id];
162
- if (entryIsBranch(entry)) {
163
- // A null children value means that the directory has not been
164
- // loaded/opened, so there are no visible descendant files.
165
- if (entry.children !== null) {
166
- paths.push(...navNodeApi.visibleLeavesPaths(entry.children, entryPath));
167
- }
207
+ if (!entryIsBranch(entry)) {
208
+ paths.push(entryPath);
168
209
  continue;
169
210
  }
170
- paths.push(entryPath);
211
+ /*
212
+ * A null value means the source branch is not loaded/opened. It has no
213
+ * currently visible descendants.
214
+ */
215
+ if (entry.children !== null) {
216
+ paths.push(...navNodeApi.visibleLeavesPaths(entry.children, entryPath));
217
+ }
171
218
  }
172
219
  return paths;
173
220
  },
@@ -0,0 +1,103 @@
1
+ import type { SerializableKey, TreeNode } from '../tree-node/index.js';
2
+ import type { Cursor } from '../cursor.js';
3
+ import type { Folds } from '../fold-node/index.js';
4
+ export type NavNode<Id extends SerializableKey> = {
5
+ /**
6
+ * Synthetic UI entry representing folded children.
7
+ *
8
+ * It is absent when this directory has no folded children.
9
+ */
10
+ folded: NavFoldEntry<Id> | null;
11
+ /**
12
+ * Loaded entries that are not folded at this directory, corresponding to
13
+ * navigable rows.
14
+ *
15
+ * Their order is the sibling iteration order supplied by the TreeNode API.
16
+ */
17
+ entries: NavEntry<Id>[];
18
+ };
19
+ export type NavFoldEntry<Id extends SerializableKey> = {
20
+ /**
21
+ * Folded entries that are present in the loaded TreeNode.
22
+ *
23
+ * This is information for rendering the folded row.
24
+ */
25
+ entries: NavEntry<Id>[];
26
+ };
27
+ export type NavEntry<Id extends SerializableKey> = NavLeaf<Id> | NavBranch<Id>;
28
+ export type NavLeaf<Id extends SerializableKey> = {
29
+ id: Id;
30
+ };
31
+ export type NavBranch<Id extends SerializableKey> = {
32
+ id: Id;
33
+ /**
34
+ * `null` means this branch's children have not been loaded or opened.
35
+ */
36
+ children: NavNode<Id> | null;
37
+ };
38
+ /**
39
+ * Operations for creating and navigating a UI-oriented projection of a tree.
40
+ *
41
+ * @typeParam Id - The type identifying a node among its direct siblings.
42
+ * @typeParam Value - Application-owned data stored in each source TreeNode.
43
+ */
44
+ export type NavNodeApi<Id extends SerializableKey, Value> = {
45
+ /**
46
+ * Tests whether a navigation entry represents a branch.
47
+ *
48
+ * A branch is an entry with a `children` property. Its `children` value is
49
+ * `null` when the corresponding source-tree branch has not been loaded or
50
+ * opened.
51
+ */
52
+ entryIsBranch(entry: NavEntry<Id>): entry is NavBranch<Id>;
53
+ /**
54
+ * Creates a navigation projection rooted at `root`.
55
+ *
56
+ * The source TreeNode is authoritative for:
57
+ *
58
+ * - entry identity;
59
+ * - whether an entry is a leaf, closed branch, or open branch;
60
+ * - the loaded direct child entries; and
61
+ * - sibling iteration order, where guaranteed by TreeNodeApi.
62
+ *
63
+ * `foldRoot` is authoritative for folding. It contains multiple independently
64
+ * active fold trees. An entry is folded in the projection when at least one
65
+ * active fold tree hides that entry at its parent path.
66
+ *
67
+ * A folded entry is omitted from its parent's navigable entries and is
68
+ * represented by that parent's synthetic `folded` entry instead.
69
+ *
70
+ * The root must be a branch node. Since TreeNode is opaque, callers cannot
71
+ * express that fact statically. This method returns `undefined` if `root`
72
+ * is a leaf.
73
+ *
74
+ * A closed root branch produces a NavBranch whose `children` is `null`.
75
+ *
76
+ * @param root - Source tree node from which to create navigation.
77
+ * @param folds - Fold definitions corresponding to `root`. All active fold
78
+ * trees contribute to whether a source entry is represented by its parent’s
79
+ * synthetic `folded` entry.
80
+ * @returns The projected root branch, or `undefined` when `root` is a leaf.
81
+ */
82
+ from(root: TreeNode<Id, Value>, folds: Folds<Id>): NavBranch<Id> | undefined;
83
+ /**
84
+ * Finds the navigation node represented by a path relative to `navigation`.
85
+ *
86
+ * An empty path selects `navigation` itself. Paths cannot pass through leaf
87
+ * entries or branches whose children are currently `null`.
88
+ */
89
+ getNodeAtPath(navigation: NavNode<Id>, path: readonly Id[]): NavNode<Id> | undefined;
90
+ /**
91
+ * Finds the navigation entry represented by a path relative to `navigation`.
92
+ *
93
+ * An empty path does not identify an entry and returns `undefined`.
94
+ */
95
+ getEntryAtPath(navigation: NavNode<Id>, path: readonly Id[]): NavEntry<Id> | undefined;
96
+ nextCursor(rootNode: NavBranch<Id>, cursor: Cursor<Id>): Cursor<Id> | undefined;
97
+ previousCursor(rootNode: NavBranch<Id>, cursor: Cursor<Id>): Cursor<Id> | undefined;
98
+ cursorAfterFold(rootNode: NavBranch<Id>, cursor: Cursor<Id>): Cursor<Id> | undefined;
99
+ parentCursor(navigation: NavNode<Id>, cursor: Cursor<Id>): Cursor<Id> | undefined;
100
+ cursors(navigation: NavNode<Id>, parentPath?: readonly Id[]): Cursor<Id>[];
101
+ visibleLeavesPaths(navigation: NavNode<Id>, parentPath?: readonly Id[]): Id[][];
102
+ };
103
+ //# sourceMappingURL=nav-node.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav-node.types.d.ts","sourceRoot":"","sources":["../../../src/trees/nav-node/nav-node.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { SerializableKey, TreeNodeApi } from '../tree-node/index.js';
2
+ import type { CursorApi } from '../cursor.js';
3
+ import type { StateApi } from './state.types.js';
4
+ /**
5
+ * Creates operations for navigating and resynchronizing tree-surfer state.
6
+ */
7
+ export declare function createStateApi<Id extends SerializableKey, Value>(treeNodeApi: TreeNodeApi<Id, Value>, cursorApi: CursorApi<Id>): StateApi<Id, Value>;
8
+ //# sourceMappingURL=state.impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.impl.d.ts","sourceRoot":"","sources":["../../../src/trees/state/state.impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAY,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpF,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAS,MAAM,kBAAkB,CAAC;AAMxD;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAC9D,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,EACnC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,GACvB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAuLrB"}