Skip to content

Commit 10b4bda

Browse files
committed
feat: obtain css classes from metadata
Signed-off-by: Andres Correa Casablanca <castarco@coderspirit.xyz>
1 parent b8cf6cb commit 10b4bda

File tree

7 files changed

+77
-32
lines changed

7 files changed

+77
-32
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ root = true
44
end_of_line = lf
55
insert_final_newline = true
66

7-
[*.{js,cjs,mjs,json,ts,cjs,mts,jsx,tsx}]
7+
[*.{css,js,cjs,mjs,json,ts,cjs,mts,jsx,tsx}]
88
charset = utf-8
99
indent_style = tab
1010
indent_size = 2

.storybook/preview.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { Preview } from "@storybook/react";
22

3+
import './stories.css'
4+
35
const preview: Preview = {
46
parameters: {
57
actions: { argTypesRegex: "^on[A-Z].*" },

.storybook/stories.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.even {
2+
fill: red;
3+
}

src/BeautifulTree.tsx

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { edgesIterator, postOrderIterator } from './traversal'
22
import type { Tree } from './types'
33
import type { WrappedTreeWithLayout } from './layouts'
4-
export { computeLeftShiftLayout, computeCenter3Layout } from './layouts'
4+
export { computeNaiveLayout, computeSmartLayout } from './layouts'
5+
6+
export type CssClassesInferrer = (
7+
data?: Readonly<Record<string, unknown>> | undefined,
8+
) => string[]
59

610
export interface BeautifulTreeProps {
711
readonly id: string
@@ -14,13 +18,31 @@ export interface BeautifulTreeProps {
1418
readonly computeLayout: (
1519
tree: Readonly<Tree>,
1620
) => Readonly<WrappedTreeWithLayout>
21+
readonly nodeClassesInferrer?: CssClassesInferrer | undefined
22+
readonly edgeClassesInferrer?: CssClassesInferrer | undefined
23+
}
24+
25+
function runClassesInferrer(
26+
classesInferrer?: CssClassesInferrer | undefined,
27+
data?: Readonly<Record<string, unknown>> | undefined,
28+
): string {
29+
if (classesInferrer === undefined) {
30+
return ''
31+
}
32+
const cssClasses = classesInferrer(data)
33+
if (cssClasses.length === 0) {
34+
return ''
35+
}
36+
return ` ${cssClasses.join(' ')}`
1737
}
1838

1939
export function BeautifulTree({
2040
id,
2141
svgProps,
2242
tree,
2343
computeLayout,
44+
nodeClassesInferrer,
45+
edgeClassesInferrer,
2446
}: Readonly<BeautifulTreeProps>): JSX.Element {
2547
const { tree: treeWithLayout, maxX, maxY } = computeLayout(tree)
2648
const { width, height, sizeUnit = 'px' } = svgProps
@@ -51,7 +73,10 @@ export function BeautifulTree({
5173
return (
5274
<line
5375
key={`${id}-edge-${idx}`}
54-
className={'beautiful-tree-edge'}
76+
className={`beautiful-tree-edge${runClassesInferrer(
77+
edgeClassesInferrer,
78+
edge.edgeData,
79+
)}`}
5580
x1={(edge.start.x + 1) * xCoef}
5681
y1={(edge.start.y + 1) * yCoef}
5782
x2={(edge.end.x + 1) * xCoef}
@@ -67,7 +92,9 @@ export function BeautifulTree({
6792
key={`${id}-node-${idx}`}
6893
className={`beautiful-tree-node${
6994
node.meta.isRoot ? ' beautiful-tree-root' : ''
70-
}${node.meta.isLeaf ? ' beautiful-tree-leaf' : ''}`}
95+
}${
96+
node.meta.isLeaf ? ' beautiful-tree-leaf' : ''
97+
}${runClassesInferrer(nodeClassesInferrer, node.data)}`}
7198
cx={(aX + 1) * xCoef}
7299
cy={(aY + 1) * yCoef}
73100
r={maxNodeRadius}

src/layouts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const _computeLeftShiftLayout = (
3232
} satisfies Readonly<TreeWithLayout>
3333
}
3434

35-
export const computeLeftShiftLayout = (
35+
export const computeNaiveLayout = (
3636
tree: Readonly<Tree>,
3737
): Readonly<WrappedTreeWithLayout> => {
3838
const counters = { layers: [], maxX: 0 }
@@ -231,7 +231,7 @@ const _cousinsEvenSpacing = (
231231
_inPlaceEvenSpacingUpdate(numChildren, tree, shift, offsets, depth, tracer)
232232
}
233233

234-
export const computeCenter3Layout = (
234+
export const computeSmartLayout = (
235235
tree: Readonly<Tree>,
236236
): Readonly<WrappedTreeWithLayout> => {
237237
const offsets: number[] = []

src/stories/BeautifulTree.stories.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
BeautifulTree,
3-
computeCenter3Layout,
4-
computeLeftShiftLayout,
3+
computeNaiveLayout,
4+
computeSmartLayout,
55
} from '../BeautifulTree'
66
import type { Meta, StoryObj } from '@storybook/react'
77
import type { Tree } from '../types'
@@ -287,6 +287,12 @@ const wideTree_D: Tree = {
287287
],
288288
}
289289

290+
const getCssFromNodeData = (
291+
data?: Readonly<Record<string, unknown>>,
292+
): string[] => {
293+
return typeof data?.['v'] === 'number' && data['v'] % 2 === 0 ? ['even'] : []
294+
}
295+
290296
export const LeftShifted_Tree: Story = {
291297
args: {
292298
id: 'leftshifted-small-tree',
@@ -295,7 +301,7 @@ export const LeftShifted_Tree: Story = {
295301
height: 100,
296302
},
297303
tree: smallTree,
298-
computeLayout: computeLeftShiftLayout,
304+
computeLayout: computeNaiveLayout,
299305
},
300306
}
301307

@@ -307,7 +313,7 @@ export const LeftShifted_Big_Tree: Story = {
307313
height: 100,
308314
},
309315
tree: bigTree,
310-
computeLayout: computeLeftShiftLayout,
316+
computeLayout: computeNaiveLayout,
311317
},
312318
}
313319

@@ -319,7 +325,8 @@ export const Centered3_Tree: Story = {
319325
height: 100,
320326
},
321327
tree: smallTree,
322-
computeLayout: computeCenter3Layout,
328+
computeLayout: computeSmartLayout,
329+
nodeClassesInferrer: getCssFromNodeData,
323330
},
324331
}
325332

@@ -331,7 +338,8 @@ export const Centered3_Big_Tree: Story = {
331338
height: 100,
332339
},
333340
tree: bigTree,
334-
computeLayout: computeCenter3Layout,
341+
computeLayout: computeSmartLayout,
342+
nodeClassesInferrer: getCssFromNodeData,
335343
},
336344
}
337345

@@ -343,7 +351,8 @@ export const Centered3_Wide_Tree_A: Story = {
343351
height: 100,
344352
},
345353
tree: wideTree_A,
346-
computeLayout: computeCenter3Layout,
354+
computeLayout: computeSmartLayout,
355+
nodeClassesInferrer: getCssFromNodeData,
347356
},
348357
}
349358

@@ -355,7 +364,8 @@ export const Centered3_Wide_Tree_B: Story = {
355364
height: 100,
356365
},
357366
tree: wideTree_B,
358-
computeLayout: computeCenter3Layout,
367+
computeLayout: computeSmartLayout,
368+
nodeClassesInferrer: getCssFromNodeData,
359369
},
360370
}
361371

@@ -367,7 +377,8 @@ export const Centered3_Wide_Tree_Bm: Story = {
367377
height: 100,
368378
},
369379
tree: wideTree_Bm,
370-
computeLayout: computeCenter3Layout,
380+
computeLayout: computeSmartLayout,
381+
nodeClassesInferrer: getCssFromNodeData,
371382
},
372383
}
373384

@@ -379,7 +390,8 @@ export const Centered3_Wide_Tree_C: Story = {
379390
height: 100,
380391
},
381392
tree: wideTree_C,
382-
computeLayout: computeCenter3Layout,
393+
computeLayout: computeSmartLayout,
394+
nodeClassesInferrer: getCssFromNodeData,
383395
},
384396
}
385397

@@ -391,6 +403,7 @@ export const Centered3_Wide_Tree_D: Story = {
391403
height: 100,
392404
},
393405
tree: wideTree_D,
394-
computeLayout: computeCenter3Layout,
406+
computeLayout: computeSmartLayout,
407+
nodeClassesInferrer: getCssFromNodeData,
395408
},
396409
}

src/tests/layouts.test.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { computeCenter3Layout, computeLeftShiftLayout } from '../layouts'
1+
import { computeNaiveLayout, computeSmartLayout } from '../layouts'
22
import { describe, expect, it } from 'vitest'
33

4-
describe('computeLeftShiftLayout', () => {
4+
describe('computeNaiveLayout', () => {
55
it('sets x=0,y=0 for a single-node tree, and data is preserved', () => {
6-
const resultWithoutChildren = computeLeftShiftLayout({
6+
const resultWithoutChildren = computeNaiveLayout({
77
data: { v: 42 },
88
})
99
expect(resultWithoutChildren).toEqual({
@@ -19,7 +19,7 @@ describe('computeLeftShiftLayout', () => {
1919
},
2020
})
2121

22-
const resultWithEmptyChildren = computeLeftShiftLayout({
22+
const resultWithEmptyChildren = computeNaiveLayout({
2323
data: { v: 42 },
2424
children: [],
2525
})
@@ -39,7 +39,7 @@ describe('computeLeftShiftLayout', () => {
3939
})
4040

4141
it('sets x=0,y=0 & x=0,y=1 for tree with single child', () => {
42-
const result = computeLeftShiftLayout({
42+
const result = computeNaiveLayout({
4343
data: { v: 42 },
4444
children: [
4545
{
@@ -77,7 +77,7 @@ describe('computeLeftShiftLayout', () => {
7777
})
7878

7979
it('sets x=0,y=0 & x=0,y=1 & x=1,y=1 for tree with two children', () => {
80-
const result = computeLeftShiftLayout({
80+
const result = computeNaiveLayout({
8181
data: { v: 42 },
8282
children: [
8383
{
@@ -130,7 +130,7 @@ describe('computeLeftShiftLayout', () => {
130130
})
131131

132132
it('sets x for ((.,.),(.))', () => {
133-
const result = computeLeftShiftLayout({
133+
const result = computeNaiveLayout({
134134
data: { v: 42 },
135135
children: [
136136
{
@@ -240,7 +240,7 @@ describe('computeLeftShiftLayout', () => {
240240
})
241241

242242
it('sets x for ((.),(.,.))', () => {
243-
const result = computeLeftShiftLayout({
243+
const result = computeNaiveLayout({
244244
data: { v: 42 },
245245
children: [
246246
{
@@ -350,9 +350,9 @@ describe('computeLeftShiftLayout', () => {
350350
})
351351
})
352352

353-
describe('computeCenter3Layout', () => {
353+
describe('computeSmartLayout', () => {
354354
it('sets x=0,y=0 for a single-node tree, and data is preserved', () => {
355-
const resultWithoutChildren = computeCenter3Layout({
355+
const resultWithoutChildren = computeSmartLayout({
356356
data: { v: 42 },
357357
})
358358
expect(resultWithoutChildren).toEqual({
@@ -368,7 +368,7 @@ describe('computeCenter3Layout', () => {
368368
},
369369
})
370370

371-
const resultWithEmptyChildren = computeCenter3Layout({
371+
const resultWithEmptyChildren = computeSmartLayout({
372372
data: { v: 42 },
373373
children: [],
374374
})
@@ -388,7 +388,7 @@ describe('computeCenter3Layout', () => {
388388
})
389389

390390
it('sets x=0,y=0 & x=0,y=1 for tree with single child', () => {
391-
const result = computeCenter3Layout({
391+
const result = computeSmartLayout({
392392
data: { v: 42 },
393393
children: [
394394
{
@@ -426,7 +426,7 @@ describe('computeCenter3Layout', () => {
426426
})
427427

428428
it('sets x=0.5,y=0 & x=0,y=1 & x=1,y=1 for tree with two children', () => {
429-
const result = computeCenter3Layout({
429+
const result = computeSmartLayout({
430430
data: { v: 42 },
431431
children: [
432432
{
@@ -479,7 +479,7 @@ describe('computeCenter3Layout', () => {
479479
})
480480

481481
it('sets x for ((.,.),(.))', () => {
482-
const result = computeCenter3Layout({
482+
const result = computeSmartLayout({
483483
data: { v: 42 },
484484
children: [
485485
{
@@ -592,7 +592,7 @@ describe('computeCenter3Layout', () => {
592592
})
593593

594594
it('sets x for ((.),(.,.))', () => {
595-
const result = computeCenter3Layout({
595+
const result = computeSmartLayout({
596596
data: { v: 42 },
597597
children: [
598598
{

0 commit comments

Comments
 (0)