Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/build-dist.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build dist

on:
push:
branches: [master]
pull_request:
branches: [master]

# Avoid two auto-commit runs racing on the same branch.
concurrency:
group: build-dist-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
# Skip the commit this workflow itself makes, to avoid triggering an infinite loop.
if: github.event_name == 'pull_request' || !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
# Needed so we can push the dist/ update back to the branch.
persist-credentials: true

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- run: npm ci

- run: npm run test:run

- run: npm run build

- name: Commit updated dist/ on push to master
if: github.event_name == 'push'
run: |
if [ -n "$(git status --porcelain dist)" ]; then
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add dist
git commit -m "chore: rebuild dist [skip ci]"
git push
else
echo "dist/ already up to date"
fi
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ node_modules
dist-ssr
*.local

# Test coverage
coverage/
.nyc_output/

# Test results
test-results/

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand All @@ -21,3 +28,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.claude/settings.local.json
144 changes: 141 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,76 @@ This javascript module aims at providing an easy interface in order to represent

## Installation

With npm :
With npm :

```Bash
npm install treeviz
```

and then you can use it with :
and then you can use it with :

```JavaScript
import {Treeviz} from 'treeviz';
```

Or download this zip repository in the Github Release section and link the dist/treeviz.js file in your page directly : `<script src="./dist/index.js><script>`

## Usage
## Development


```bash
npm run dev
```


#### Vanilla JavaScript NEW

To build .js bundles for vanilla JavaScript usage:

```bash
npm run build
```

This generates:
- `dist/treeviz.js` - ES module format
- `dist/treeviz.iife.js` - Vanilla JS bundle for `<script>` tag usage

1. Link in your HTML

```html
<script src="dist/treeviz.iife.js"></script>
```

2. Use in your JavaScript

```html
<div id="tree" style="height:700px; width:900px"></div>

<script>
var data = [
{ id: 1, text_1: "Father", father: null },
{ id: 2, text_1: "Child A", father: 1 },
];

var myTree = Treeviz.create({
htmlId: "tree",
idKey: "id",
hasFlatData: true,
relationnalField: "father",
});

myTree.refresh(data);
</script>
```

#### Alternative: esbuild

If you prefer using esbuild directly:

```bash
npx esbuild src/index.ts --bundle --outfile=dist/bundle.js --platform=browser --format=iife --global-name=Treeviz --keep-names
```


#### Vanilla JavaScript

Expand Down Expand Up @@ -110,7 +165,9 @@ The table below lists all the avalaible key that the config object can have
| `nodeHeight` | number | 100 | Height of a node in px |
| `linkColor` | function | (node: NodeData) => "#ffcc80" | Color of the link |
| `linkWidth` | function | (node: NodeData) => 10 | Width of the link |
| `linkStyle` | function | (node: NodeData) => "solid" | Stroke pattern of the link. Return "solid", "dashed", "dotted", or "dashdot" |
| `linkShape` | "quadraticBeziers" \| "orthogonal" \| "curve" | "quadraticBeziers" | Shape of the link |
| `linkLabel` | ILinkLabel<T> | undefined | Configuration for labels displayed on connection lines. Contains `render` function, `color`, and `fontSize` properties |
| `renderNode` | function | (node: NodeData) => null | HTML template for every node |
| `isHorizontal` | boolean | true | Direction of the tree. If true, the tree expands from left to right. If false, it goes from top to bottom |
| `onNodeClick` | function | (node: NodeData) => null | Function handling the event when someone click on it |
Expand All @@ -133,11 +190,92 @@ type NodeData {
}
`

### Link Styling

You can control the stroke pattern of the connection lines using `linkStyle`, a per-link callback like `linkColor`/`linkWidth`:

```js
var myTree = Treeviz.create({
htmlId: "tree",
idKey: "id",
hasFlatData: true,
relationnalField: "father",
linkStyle: (node) => {
// Return "solid", "dashed", "dotted", or "dashdot"
// Can vary per link based on node data:
return node.data.isOptional ? "dashed" : "solid";
},
});
```

### Link Labels Configuration

You can display labels on the connection lines between nodes using the `linkLabel` configuration:

```js
var myTree = Treeviz.create({
htmlId: "tree",
idKey: "id",
hasFlatData: true,
relationnalField: "father",
linkLabel: {
render: (parent, child) => {
// Return plain text to display on the connection line
return "is child";
// You can use parent and child data for dynamic labels:
// return child.data.name + " is child";
},
color: "#455A64", // Label text color (optional)
fontSize: 11 // Label font size in px (optional)
}
});
```

The `render` function receives parent and child `NodeData` objects, allowing you to create dynamic labels based on node properties. Returns plain text only (HTML is not supported in SVG text elements).

## Testing

The project uses [Vitest](https://vitest.dev/) for unit and integration testing with jsdom for DOM simulation and coverage reporting.

### Running Tests

```bash
# Run tests in watch mode
npm test

# Run tests once
npm run test:run

# Run tests with coverage report
npm run test:coverage

# Open Vitest UI dashboard (interactive)
npm run test:ui
```

### Test Structure

Tests are organized in `tests/` folder:

- **`tests/unit/`** - Unit tests for individual functions and utilities
- `utils.test.ts` - Tests for `setNodeLocation()` function
- `core-utils.test.ts` - Tests for `getAreaSize()` and `RefreshQueue` class
- `node-ancestors.test.ts` - Tests for `getFirstDisplayedAncestor()` hierarchy traversal
- `prepare-data.test.ts` - Tests for data preparation and configuration validation

- **`tests/integration/`** - Integration tests for API and configuration
- `treeviz-api.test.ts` - Tests for configuration validation, data variations, and layout configurations

### Test Coverage

Coverage reports are generated in the `coverage/` directory after running `npm run test:coverage`. The HTML report provides detailed coverage information for all source files.

## Contributing

- Clone the repo.
- Run `npm install`.
- Run `npm run dev`, then you can edit the files in the `./src` folder and the `./example/index.html` file.
- **Run `npm test` to verify your changes pass all tests** before submitting a pull request.
- To publish (admin rights), run `npm run build && npm publish`.

## Credits
Expand Down
Loading