Skip to content

Commit 88d0edc

Browse files
committed
fix: propagate partial modsum
Signed-off-by: Andres Correa Casablanca <castarco@coderspirit.xyz>
1 parent 4a6aaba commit 88d0edc

File tree

5 files changed

+3979
-8
lines changed

5 files changed

+3979
-8
lines changed

src/layouts.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,29 @@ const _inPlaceEvenSpacingUpdate = (
150150
offsets[depth + 1] = M(
151151
offsets[depth + 1] ?? 0,
152152
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
153-
tree[C]![numChildren - 1]!.node.meta.pos.x + 1 + (tm.m ?? 0),
153+
tree[C]![numChildren - 1]!.node.meta.pos.x + 1,
154154
)
155+
156+
if ((tm.m ?? 0) > 0) {
157+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
158+
_propagatePartialMod(tree[C], depth + 1, tm.m!, offsets)
159+
}
160+
}
161+
}
162+
163+
const _propagatePartialMod = (
164+
tc: Readonly<Required<TreeChild<TreeWithLayout>>[]> | undefined,
165+
depth: number,
166+
mod: number,
167+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
168+
offsets: number[],
169+
): void => {
170+
while ((tc?.length ?? 0) > 0) {
171+
offsets[depth] = (offsets[depth] ?? 0) + mod
172+
173+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
174+
tc = tc![tc!.length - 1]?.node[C]
175+
depth += 1
155176
}
156177
}
157178

@@ -167,6 +188,7 @@ const _siblingsEvenSpacing = (
167188
): void => {
168189
const tc = tree[C]
169190
const numChildren = tc?.length ?? 0
191+
const oldNextOffset = offsets[depth + 1] ?? 0
170192

171193
for (const { node } of tc ?? []) {
172194
_siblingsEvenSpacing(node, offsets, tracer, depth + 1)
@@ -192,20 +214,26 @@ const _siblingsEvenSpacing = (
192214
let accShift = 0
193215
for (const [idx, { node }] of (tc ?? []).entries()) {
194216
if (idx === 0) {
195-
if (numChildren > 1) {
196-
accShift = M(
197-
0,
198-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
199-
_getPosX(tc![1]!) - maxSpacing - node.meta.pos.x,
200-
)
201-
}
217+
accShift =
218+
numChildren > 1
219+
? M(
220+
0,
221+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
222+
_getPosX(tc![1]!) - maxSpacing - node.meta.pos.x,
223+
oldNextOffset - node.meta.pos.x,
224+
)
225+
: M(0, oldNextOffset - node.meta.pos.x)
202226
} else {
203227
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
204228
accShift = _getPosX(tc![idx - 1]!) + maxSpacing - node.meta.pos.x
205229
}
206230

207231
node.meta.pos.x += accShift
208232
node.meta.m = (node.meta.m ?? 0) + accShift
233+
234+
if (accShift > 0) {
235+
_propagatePartialMod(node[C], depth + 2, accShift, offsets)
236+
}
209237
}
210238

211239
_inPlaceEvenSpacingUpdate(numChildren, tree, offsets, depth, tracer)

src/stories/BeautifulTree.stories.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
wideTree_C,
1616
wideTree_D,
1717
wideTree_E,
18+
wideTree_M,
1819
} from './treeFixtures'
1920
import type { Tree } from '../types'
2021

@@ -172,6 +173,20 @@ export const Centered3_Wide_Tree_E: Story = {
172173
},
173174
}
174175

176+
export const Centered3_Wide_Tree_M: Story = {
177+
args: {
178+
id: 'centered3-wide-tree-m',
179+
svgProps: {
180+
width: 400,
181+
height: 400,
182+
},
183+
tree: wideTree_M,
184+
computeLayout: computeSmartLayout,
185+
getNodeClass: getCssFromNodeData,
186+
getEdgeClass: getCssFromEdgeData,
187+
},
188+
}
189+
175190
const buildRandomTree = (maxDepth = 4): Readonly<Tree> => {
176191
const numChildren = maxDepth > 0 ? Math.floor(Math.random() * 4) : 0
177192
const tree: Tree = {

src/stories/treeFixtures.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,49 @@ export const wideTree_E: Tree = {
304304
{ node: {} },
305305
],
306306
}
307+
308+
export const wideTree_M: Tree = {
309+
children: [
310+
{
311+
node: {
312+
children: [
313+
{ node: {} },
314+
{
315+
node: {
316+
children: [{ node: { children: [{ node: {} }] } }, { node: {} }],
317+
},
318+
},
319+
{
320+
node: {
321+
children: [
322+
{
323+
node: {
324+
children: [{ node: {} }, { node: {} }, { node: {} }],
325+
},
326+
},
327+
],
328+
},
329+
},
330+
],
331+
},
332+
},
333+
{
334+
node: {
335+
children: [
336+
{
337+
node: {
338+
children: [
339+
{
340+
node: {
341+
children: [{ node: {} }, { node: {} }, { node: {} }],
342+
},
343+
},
344+
],
345+
},
346+
},
347+
],
348+
},
349+
},
350+
{ node: { children: [{ node: {} }, { node: {} }] } },
351+
],
352+
}

src/tests/BeautifulTree.test.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
wideTree_C,
1515
wideTree_D,
1616
wideTree_E,
17+
wideTree_M,
1718
} from '../stories/treeFixtures'
1819
import { describe, expect, it } from 'vitest'
1920
import { render } from '@testing-library/react'
@@ -204,4 +205,24 @@ describe('BeautifulTree : Smart Layout', () => {
204205

205206
expect(rendered).toMatchSnapshot()
206207
})
208+
209+
it('renders wide tree M, with rect shape, node content display, and dynamic css classes', () => {
210+
const rendered = render(
211+
<BeautifulTree
212+
id="smart-wide-m-tree"
213+
svgProps={{
214+
width: 400,
215+
height: 400,
216+
}}
217+
tree={wideTree_M}
218+
computeLayout={computeSmartLayout}
219+
nodeShape="rect"
220+
getNodeContent={(data): string => data?.['v']?.toString() ?? ''}
221+
getNodeClass={getCssFromNodeData}
222+
getEdgeClass={getCssFromEdgeData}
223+
/>,
224+
)
225+
226+
expect(rendered).toMatchSnapshot()
227+
})
207228
})

0 commit comments

Comments
 (0)