|
| 1 | +import type { VisibleTree } from '../model' |
| 2 | + |
| 3 | +type StyleMap = Map<string, Record<string, string>> |
| 4 | + |
| 5 | +export function applyAbsoluteStackingOrder(tree: VisibleTree, styles: StyleMap): void { |
| 6 | + tree.rootIds.forEach((rootId) => visit(rootId, tree, styles)) |
| 7 | +} |
| 8 | + |
| 9 | +function visit(nodeId: string, tree: VisibleTree, styles: StyleMap): void { |
| 10 | + const node = tree.nodes.get(nodeId) |
| 11 | + if (!node) return |
| 12 | + |
| 13 | + const children = node.children ?? [] |
| 14 | + if (children.length) { |
| 15 | + const needsIsolation = new Set<string>() |
| 16 | + |
| 17 | + for (let i = 0; i < children.length; i += 1) { |
| 18 | + const childId = children[i] |
| 19 | + const childStyle = styles.get(childId) |
| 20 | + if (!isAbsolute(childStyle)) continue |
| 21 | + |
| 22 | + const hasLaterInFlow = children |
| 23 | + .slice(i + 1) |
| 24 | + .some((siblingId) => !isAbsolute(styles.get(siblingId))) |
| 25 | + |
| 26 | + if (!hasLaterInFlow) continue |
| 27 | + |
| 28 | + if (!childStyle?.['z-index']) { |
| 29 | + styles.set(childId, { ...(childStyle ?? {}), 'z-index': '-1' }) |
| 30 | + } |
| 31 | + needsIsolation.add(nodeId) |
| 32 | + } |
| 33 | + |
| 34 | + needsIsolation.forEach((parentId) => { |
| 35 | + const style = styles.get(parentId) ?? {} |
| 36 | + if (style.isolation) return |
| 37 | + styles.set(parentId, { ...style, isolation: 'isolate' }) |
| 38 | + }) |
| 39 | + } |
| 40 | + |
| 41 | + children.forEach((childId) => visit(childId, tree, styles)) |
| 42 | +} |
| 43 | + |
| 44 | +function isAbsolute(style?: Record<string, string>): boolean { |
| 45 | + return style?.position?.toLowerCase() === 'absolute' |
| 46 | +} |
0 commit comments