Skip to content

Commit 13333f6

Browse files
committed
feat: naive layout computation
Signed-off-by: Andres Correa Casablanca <castarco@coderspirit.xyz>
1 parent 05d9bed commit 13333f6

File tree

7 files changed

+108
-15
lines changed

7 files changed

+108
-15
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ jobs:
3939
run: pnpm lint
4040
- name: Build Library
4141
run: pnpm build
42-
# - run: pnpm test
42+
- name: Run Tests
43+
run: pnpm test

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Caches & Artifacts
2+
coverage/
23
dist/
34
node_modules/
5+
storybook-static/
46

57
# Lockfiles
68
pnpm-lock.yaml

.hooks/pre-push

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ set -o pipefail
55

66
pnpm run lint
77
pnpm publint
8+
pnpm test

.prettierrc.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const config = {
2-
semi: false,
3-
singleQuote: true,
4-
parser: 'typescript',
5-
trailingComma: 'all',
6-
options: {
7-
editorconfig: true
8-
},
2+
semi: false,
3+
singleQuote: true,
4+
parser: 'typescript',
5+
trailingComma: 'all',
6+
options: {
7+
editorconfig: true
8+
},
99
}
1010

1111
export default config

src/BeautifulTree.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
export type Tree = {
2-
data: Record<string, unknown>,
3-
children: {
4-
edgeData: Record<string, unknown>,
5-
node: Tree
6-
}[]
7-
}
1+
import type { Tree } from './core'
82

93
export interface BeautifulTreeProps {
104
id: string,

src/core.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
export type TreeChild<T extends Tree = Tree> = {
2+
node: T,
3+
edgeData: Record<string, unknown>,
4+
}
5+
6+
export type Node = {
7+
data: Record<string, unknown>,
8+
}
9+
10+
export type Tree = Node & {
11+
children?: TreeChild[]
12+
}
13+
14+
export type TreeWithLayout = Node & {
15+
children?: Required<TreeChild<TreeWithLayout>>[]
16+
layout: {
17+
plan: { x: number, y: number },
18+
}
19+
}
20+
21+
type InternalTreeLayout = number[][]
22+
23+
const _computeLeftShiftLayout = (tree: Tree, depth: number = 0, layout?: InternalTreeLayout): TreeWithLayout => {
24+
layout ??= []
25+
26+
if (layout[depth] === undefined) {
27+
layout[depth] = []
28+
}
29+
const x = (layout[depth]?.at(-1) ?? -1) + 1
30+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
31+
layout[depth]!.push(x)
32+
33+
const treeWithLayout = {
34+
data: tree.data,
35+
children: tree.children?.map(child => ({
36+
edgeData: child.edgeData,
37+
node: _computeLeftShiftLayout(child.node, depth + 1, layout),
38+
})) ?? [],
39+
layout: { plan: { x, y: depth } },
40+
} satisfies TreeWithLayout
41+
42+
return treeWithLayout
43+
}
44+
45+
export const computeLeftShiftLayout: ((tree: Tree) => TreeWithLayout) = _computeLeftShiftLayout

src/tests/core.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, it, expect } from 'vitest'
2+
import { computeLeftShiftLayout } from '../core'
3+
4+
describe('computeLeftShiftLayout', () => {
5+
it('sets x=0,y=0 for a single-node tree, and data is preserved', () => {
6+
const resultWithoutChildren = computeLeftShiftLayout({
7+
data: { v: 42 },
8+
})
9+
expect(resultWithoutChildren).toMatchObject({
10+
data: { v: 42 },
11+
layout: { plan: { x: 0, y: 0 } },
12+
})
13+
14+
const resultWithEmptyChildren = computeLeftShiftLayout({
15+
data: { v: 42 },
16+
children: [],
17+
})
18+
expect(resultWithEmptyChildren).toMatchObject({
19+
data: { v: 42 },
20+
children: [],
21+
layout: { plan: { x: 0, y: 0 } },
22+
})
23+
})
24+
25+
it('sets x=0,y=0 & x=0,y=1 for tree with single child', () => {
26+
const result = computeLeftShiftLayout({
27+
data: { v: 42 },
28+
children: [
29+
{
30+
edgeData: {},
31+
node: { data: { v: 43 } },
32+
}
33+
],
34+
})
35+
36+
expect(result).toMatchObject({
37+
data: { v: 42 },
38+
children: [
39+
{
40+
edgeData: {},
41+
node: {
42+
data: { v: 43 },
43+
layout: { plan: { x: 0, y: 1 } },
44+
},
45+
}
46+
],
47+
layout: { plan: { x: 0, y: 0 } },
48+
})
49+
})
50+
})

0 commit comments

Comments
 (0)