(path, opts = {})
| 4157 | Expand path helper |
| 4158 | ----------------------*/ |
| 4159 | export function expandTreePath(path, opts = {}) { |
| 4160 | const { force = false, persist = false, includeLeaf = false } = opts; |
| 4161 | const state = loadFolderTreeState(); |
| 4162 | const parts = (path || '').split('/').filter(Boolean); |
| 4163 | let cumulative = ''; |
| 4164 | const lastIndex = includeLeaf ? parts.length - 1 : Math.max(0, parts.length - 2); |
| 4165 | parts.forEach((part, i) => { |
| 4166 | cumulative = i === 0 ? part : `${cumulative}/${part}`; |
| 4167 | if (i > lastIndex) return; |
| 4168 | const option = document.querySelector(`.folder-option[data-folder="${CSS.escape(cumulative)}"]`); |
| 4169 | if (!option) return; |
| 4170 | const li = option.closest('li[role="treeitem"]'); |
| 4171 | const nestedUl = li ? li.querySelector(':scope > ul') : null; |
| 4172 | if (!nestedUl) return; |
| 4173 | const shouldExpand = force || state[cumulative] === 'block'; |
| 4174 | nestedUl.classList.toggle('expanded', shouldExpand); |
| 4175 | nestedUl.classList.toggle('collapsed', !shouldExpand); |
| 4176 | li.setAttribute('aria-expanded', String(!!shouldExpand)); |
| 4177 | if (persist && shouldExpand) state[cumulative] = 'block'; |
| 4178 | }); |
| 4179 | if (persist) saveFolderTreeState(state); |
| 4180 | } |
| 4181 | |
| 4182 | // Async variant that loads children as it expands so deep paths become visible. |
| 4183 | export async function expandTreePathAsync(path, opts = {}) { |
no test coverage detected