Skip to content

Commit f295613

Browse files
committed
perf: generate smaller bundle
Signed-off-by: Andres Correa Casablanca <castarco@coderspirit.xyz>
1 parent 9634329 commit f295613

File tree

3 files changed

+95
-97
lines changed

3 files changed

+95
-97
lines changed

src/BeautifulTree.tsx

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,8 @@ function runClassesGetter(
2626
classesGetter?: CssClassesGetter | undefined,
2727
data?: Readonly<Record<string, unknown>> | undefined,
2828
): string {
29-
if (classesGetter === undefined) {
30-
return ''
31-
}
32-
const cssClasses = classesGetter(data)
33-
if (cssClasses.length === 0) {
34-
return ''
35-
}
36-
return ` ${cssClasses.join(' ')}`
29+
const cssClasses = classesGetter?.(data) ?? []
30+
return cssClasses.length === 0 ? '' : ` ${cssClasses.join(' ')}`
3731
}
3832

3933
export function BeautifulTree({
@@ -44,11 +38,11 @@ export function BeautifulTree({
4438
getNodeClass: nodeClassesInferrer,
4539
getEdgeClass: edgeClassesInferrer,
4640
}: Readonly<BeautifulTreeProps>): JSX.Element {
47-
const { tree: treeWithLayout, maxX, maxY } = computeLayout(tree)
41+
const { tree: treeWithLayout, mX, mY } = computeLayout(tree)
4842
const { width, height, sizeUnit = 'px' } = svgProps
4943

50-
const xCoef = width / (maxX + 2)
51-
const yCoef = height / (maxY + 2)
44+
const xCoef = width / (mX + 2)
45+
const yCoef = height / (mY + 2)
5246
const maxNodeWidth = xCoef * 0.25
5347
const maxNodeHeight = yCoef * 0.25
5448
const maxNodeRadius = Math.min(maxNodeWidth, maxNodeHeight)
@@ -64,10 +58,9 @@ export function BeautifulTree({
6458
}}
6559
className={'beautiful-tree-react'}
6660
>
67-
<style>{`
68-
line { stroke: black; }
69-
circle { stroke: black; fill: white; }
70-
`}</style>
61+
<style>
62+
{'line { stroke: black; } circle { stroke: black; fill: white; }'}
63+
</style>
7164
{Array.from(edgesIterator(treeWithLayout), (edge, idx) => {
7265
return (
7366
<line

src/layouts.ts

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,33 @@ import type { Tree, TreeChild, TreeWithLayout } from './types'
22

33
export interface WrappedTreeWithLayout {
44
readonly tree: Readonly<TreeWithLayout>
5-
readonly maxX: number
6-
readonly maxY: number
5+
readonly mX: number
6+
readonly mY: number
77
}
88

9-
const _computeLeftShiftLayout = (
9+
const M = Math.max
10+
11+
const _computeNaiveLayout = (
1012
tree: Tree,
1113
depth = 0,
1214
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
13-
counters: { layers: number[]; maxX: number },
15+
counters: { l: number[]; mX: number },
1416
): Readonly<TreeWithLayout> => {
15-
const layers = counters.layers
16-
17-
const x = (layers[depth] ?? -1) + 1
18-
layers[depth] = x
19-
counters.maxX = Math.max(counters.maxX, x)
17+
const l = counters.l
18+
const x = (l[depth] ?? -1) + 1
19+
l[depth] = x
20+
counters.mX = M(counters.mX, x)
2021

22+
const tc = tree.children
2123
return {
2224
data: tree.data,
23-
children: tree.children?.map((child: Readonly<TreeChild>) => ({
25+
children: tc?.map((child: Readonly<TreeChild>) => ({
2426
edgeData: child.edgeData,
25-
node: _computeLeftShiftLayout(child.node, depth + 1, counters),
27+
node: _computeNaiveLayout(child.node, depth + 1, counters),
2628
})),
2729
meta: {
2830
isRoot: depth === 0,
29-
isLeaf: tree.children === undefined || tree.children.length === 0,
31+
isLeaf: tc === undefined || tc.length === 0,
3032
pos: { x, y: depth },
3133
},
3234
} satisfies Readonly<TreeWithLayout>
@@ -35,11 +37,11 @@ const _computeLeftShiftLayout = (
3537
export const computeNaiveLayout = (
3638
tree: Readonly<Tree>,
3739
): Readonly<WrappedTreeWithLayout> => {
38-
const counters = { layers: [], maxX: 0 }
40+
const counters = { l: [], mX: 0 }
3941
return {
40-
tree: _computeLeftShiftLayout(tree, 0, counters),
41-
maxX: counters.maxX,
42-
maxY: counters.layers.length - 1,
42+
tree: _computeNaiveLayout(tree, 0, counters),
43+
mX: counters.mX,
44+
mY: counters.l.length - 1,
4345
}
4446
}
4547

@@ -50,10 +52,10 @@ const _addMods = (
5052
tree: DeepWriteable<TreeWithLayout>,
5153
modsum = 0,
5254
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
53-
tracer: { maxX: number },
55+
tracer: { mX: number },
5456
): void => {
5557
tree.meta.pos.x += modsum
56-
tracer.maxX = Math.max(tracer.maxX, tree.meta.pos.x)
58+
tracer.mX = M(tracer.mX, tree.meta.pos.x)
5759
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
5860
modsum += tree.meta.m! // We know it's defined because we control when it's called
5961
for (const child of tree.children ?? []) {
@@ -67,16 +69,17 @@ const _computeCenter2Layout = (
6769
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
6870
offsets: number[],
6971
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
70-
tracer: { maxX: number },
72+
tracer: { mX: number },
7173
): DeepWriteable<TreeWithLayout> => {
72-
const children = tree.children?.map((child) => ({
74+
const tc = tree.children
75+
const children = tc?.map((child) => ({
7376
edgeData: child.edgeData,
7477
node: _computeCenter2Layout(child.node, depth + 1, offsets, tracer),
7578
}))
7679

7780
let x: number
7881
let m = 0
79-
const numChildren = tree.children?.length ?? 0
82+
const numChildren = tc?.length ?? 0
8083
if (numChildren === 0) {
8184
x = offsets[depth] ?? 0
8285
} else if (numChildren === 1) {
@@ -88,18 +91,18 @@ const _computeCenter2Layout = (
8891
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
8992
children![numChildren - 1]!.node.meta.pos.x) *
9093
0.5
91-
x = Math.max(offsets[depth] ?? 0, c)
94+
x = M(offsets[depth] ?? 0, c)
9295
m = x - c
9396
}
94-
tracer.maxX = Math.max(tracer.maxX, x)
97+
tracer.mX = M(tracer.mX, x)
9598
offsets[depth] = 1 + x
9699

97100
return {
98101
data: tree.data,
99102
children,
100103
meta: {
101104
isRoot: depth === 0,
102-
isLeaf: tree.children === undefined || tree.children.length === 0,
105+
isLeaf: tc === undefined || tc.length === 0,
103106
pos: { x, y: depth },
104107
m,
105108
},
@@ -115,24 +118,26 @@ const _inPlaceEvenSpacingUpdate = (
115118
offsets: number[],
116119
depth: number,
117120
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
118-
tracer: { maxX: number },
121+
tracer: { mX: number },
119122
): void => {
123+
const tm = tree.meta
124+
const tmp = tm.pos
120125
if (numChildren === 0) {
121-
tree.meta.pos.x += shift
126+
tmp.x += shift
122127
} else if (numChildren === 1) {
123128
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
124-
tree.meta.pos.x = tree.children![0]!.node.meta.pos.x
129+
tmp.x = tree.children![0]!.node.meta.pos.x
125130
} else {
126131
const c = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
127132
(tree.children![0]!.node.meta.pos.x +
128133
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
129134
tree.children![numChildren - 1]!.node.meta.pos.x) *
130135
0.5
131-
tree.meta.pos.x = Math.max(offsets[depth] ?? 0, c)
136+
tmp.x = M(offsets[depth] ?? 0, c)
132137
}
133-
delete tree.meta.m
134-
tracer.maxX = Math.max(tracer.maxX, tree.meta.pos.x)
135-
offsets[depth] = 1 + tree.meta.pos.x
138+
delete tm.m
139+
tracer.mX = M(tracer.mX, tmp.x)
140+
offsets[depth] = 1 + tmp.x
136141
}
137142

138143
const _siblingsEvenSpacing = (
@@ -141,54 +146,53 @@ const _siblingsEvenSpacing = (
141146
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
142147
offsets: number[],
143148
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
144-
tracer: { maxX: number },
149+
tracer: { mX: number },
145150
depth = 0,
146151
shift = 0,
147152
// eslint-disable-next-line sonarjs/cognitive-complexity
148153
): void => {
149-
const numChildren = tree.children?.length ?? 0
154+
const tc = tree.children
155+
const numChildren = tc?.length ?? 0
150156
let lastFixedIdx: number | undefined
151157
let maxSpacing = 1
152-
for (const [idx, child] of (tree.children ?? []).entries()) {
153-
const isFixed = (child.node.children?.length ?? 0) > 0
158+
for (const [idx, { node }] of (tc ?? []).entries()) {
159+
const isFixed = (node.children?.length ?? 0) > 0
154160
if (isFixed) {
155161
if (lastFixedIdx !== undefined) {
156162
const spacing =
157-
(child.node.meta.pos.x -
163+
(node.meta.pos.x -
158164
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
159-
tree.children![lastFixedIdx]!.node.meta.pos.x) /
165+
tc![lastFixedIdx]!.node.meta.pos.x) /
160166
(idx - lastFixedIdx)
161-
maxSpacing = Math.max(maxSpacing, spacing)
167+
maxSpacing = M(maxSpacing, spacing)
162168
}
163169
lastFixedIdx = idx
164170
}
165171
}
166172

167173
let accShift = shift
168-
for (const [idx, child] of (tree.children ?? []).entries()) {
174+
for (const [idx, { node }] of (tc ?? []).entries()) {
169175
if (idx === 0) {
170176
if (numChildren > 1) {
171-
accShift = Math.max(
177+
accShift = M(
172178
0,
173179
shift +
174180
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
175-
tree.children![1]!.node.meta.pos.x -
181+
tc![1]!.node.meta.pos.x -
176182
maxSpacing -
177-
child.node.meta.pos.x,
183+
node.meta.pos.x,
178184
)
179185
}
180186
} else {
181187
accShift =
182188
shift +
183-
Math.max(
189+
M(
184190
0,
185191
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
186-
tree.children![idx - 1]!.node.meta.pos.x +
187-
maxSpacing -
188-
child.node.meta.pos.x,
192+
tc![idx - 1]!.node.meta.pos.x + maxSpacing - node.meta.pos.x,
189193
)
190194
}
191-
_siblingsEvenSpacing(child.node, offsets, tracer, depth + 1, accShift)
195+
_siblingsEvenSpacing(node, offsets, tracer, depth + 1, accShift)
192196
}
193197

194198
_inPlaceEvenSpacingUpdate(numChildren, tree, shift, offsets, depth, tracer)
@@ -200,31 +204,32 @@ const _cousinsEvenSpacing = (
200204
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
201205
offsets: number[],
202206
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
203-
tracer: { maxX: number },
207+
tracer: { mX: number },
204208
depth = 0,
205209
shift = 0,
206210
): void => {
207-
const numChildren = tree.children?.length ?? 0
211+
const tc = tree.children
212+
const numChildren = tc?.length ?? 0
208213

209214
const nextOffset = offsets[depth + 1]
210215
let accShift = shift
211216
if (
212217
numChildren >= 2 &&
213218
nextOffset !== undefined &&
214219
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
215-
(tree.children![0]!.node.children?.length ?? 0) === 0
220+
(tc![0]!.node.children?.length ?? 0) === 0
216221
) {
217222
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
218-
const mid = tree.children![1]!.node.meta.pos.x - 1
223+
const mid = tc![1]!.node.meta.pos.x - 1
219224
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
220-
accShift = shift + Math.max(0, mid - tree.children![0]!.node.meta.pos.x)
225+
accShift = shift + M(0, mid - tc![0]!.node.meta.pos.x)
221226
}
222227

223-
for (const [idx, child] of (tree.children ?? []).entries()) {
228+
for (const [idx, { node }] of (tc ?? []).entries()) {
224229
if (idx === 0) {
225-
_cousinsEvenSpacing(child.node, offsets, tracer, depth + 1, accShift)
230+
_cousinsEvenSpacing(node, offsets, tracer, depth + 1, accShift)
226231
} else {
227-
_cousinsEvenSpacing(child.node, offsets, tracer, depth + 1, shift)
232+
_cousinsEvenSpacing(node, offsets, tracer, depth + 1, shift)
228233
}
229234
}
230235

@@ -235,7 +240,7 @@ export const computeSmartLayout = (
235240
tree: Readonly<Tree>,
236241
): Readonly<WrappedTreeWithLayout> => {
237242
const offsets: number[] = []
238-
const tracer = { maxX: 0 }
243+
const tracer = { mX: 0 }
239244

240245
const t = _computeCenter2Layout(tree, 0, offsets, tracer)
241246
_addMods(t, 0, tracer)
@@ -245,7 +250,7 @@ export const computeSmartLayout = (
245250

246251
return {
247252
tree: t,
248-
maxY: offsets.length - 1,
249-
maxX: tracer.maxX,
253+
mY: offsets.length - 1,
254+
mX: tracer.mX,
250255
}
251256
}

0 commit comments

Comments
 (0)