npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jm_vertical_timeline

v0.1.3

Published

This component provides a flexible and customizable vertical timeline visualization for displaying versions, events, or any other time-based data. It is designed to be easily integrated into other React applications as an npm package.

Readme

React Vertical Timeline Component

This component provides a flexible and customizable vertical timeline visualization for displaying versions, events, or any other time-based data. It is designed to be easily integrated into other React applications as an npm package.

## Installation

```bash
npm install jm_vertical_timeline
```

## Usage

Import the `Timeline` component and the `TimelineVersion` type:

```jsx
import { Timeline, TimelineVersion } from 'jm_vertical_timeline';
```

In addition to importing the component, you also need to import the component's CSS file to apply the styles:

```jsx
import 'jm_vertical_timeline/dist/style.css';
```

To ensure the component is styled correctly, your parent application needs to be set up to process Tailwind CSS. This is because the component uses Tailwind CSS classes for its layout and styling.

**Steps to set up Tailwind CSS in your parent application:**

1.  **Install Tailwind CSS and its peer dependencies:**

    ```bash
    npm install -D tailwindcss postcss autoprefixer
    ```

2.  **Create a `tailwind.config.js` file** in the root of your parent application:

    ```javascript
    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        './src/**/*.{js,jsx,ts,tsx}',
        './node_modules/jm_vertical_timeline/dist/**/*.js',
      ],
      theme: {
        extend: {},
      },
      plugins: [],
    };
    ```

    **Important:** Make sure to include the path to the component's files in the `content` array. This allows Tailwind to scan the component's files for used classes.

3.  **Create a CSS file** (e.g., `index.css` or `main.css`) in your parent application and add the following Tailwind directives:

    ```css
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    ```

4.  **Import the CSS file** in your parent application's entry point (e.g., `index.js` or `App.js`):

    ```javascript
    import './index.css';
    ```

Pass the required props to the `Timeline` component:

```jsx
import React, { useState } from 'react';
import { Timeline, TimelineVersion } from 'jm_vertical_timeline';
import 'jm_vertical_timeline/dist/style.css';

function ParentApp() {
  const [versions, setVersions] = useState([
    {
      id: 1,
      name: "Version 1.0",
      startDate: "2024-01-01",
      endDate: "2024-03-31",
      variationId: "default",
    },
    {
      id: 2,
      name: "Version 2.0",
      startDate: "2024-04-01",
      endDate: "2024-06-30",
      variationId: "beta",
      isActive: true,
    },
  ]);

  const [variations, setVariations] = useState([
    {
      id: "default",
      name: "Default Track",
      color: "#3b82f6",
    },
    {
      id: "beta",
      name: "Beta Track",
      color: "#8b5cf6",
    },
  ]);

  const handleEditVersion = (version: TimelineVersion) => {
    console.log('Edit version clicked:', version.id, version);
    // Handle the edit action, e.g., open a modal
  };

  const handleDeleteVersion = (version: TimelineVersion) => {
    console.log('Delete version clicked:', version.id, version);
    // Handle the delete action, e.g., remove the version
  };

  const handleAddVersion = (data) => {
    console.log('Add version requested:', data);
    // Handle the add action, e.g., open a modal
  };

  return (
    <Timeline
      versions={versions}
      variations={variations}
      onEditVersion={handleEditVersion}
      onDeleteVersion={handleDeleteVersion}
      onAddVersion={handleAddVersion}
      showEditButton={true}
      showDeleteButton={true}
      timelineTitle="My Custom Timeline Title"
      showTimelineTitle={true}
      dateFormat="en-GB"
    />
  );
}
```

### Props

*   `versions`: An array of `TimelineVersion` objects. Each object should have the following properties:
    *   `id` (number, required): A unique identifier for the version.
    *   `name` (string, required): The name of the version.
    *   `startDate` (string, required): The start date of the version in `YYYY-MM-DD` format.
    *   `endDate` (string, required): The end date of the version in `YYYY-MM-DD` format.
    *   `variationId` (string, required): The ID of the variation this version belongs to.
    *   `isActive` (boolean, optional): A boolean indicating if the version is currently active. Defaults to `false`.
*   `variations`: An array of `TimelineVariation` objects. Each object should have the following properties:
    *   `id` (string, required): A unique identifier for the variation.
    *   `name` (string, required): The name of the variation.
    *   `color` (string, optional): The color to use for the variation. Defaults to `#3b82f6`.
*   `onVersionClick` (function, optional): A callback function that is called when a version is clicked. It receives the clicked `TimelineVersion` object as an argument.
*   `onAddVersion` (function, optional): A callback function that is called when the "Add" button is clicked. It receives an object with `start`, `end`, and `variationId` properties.
*   `onEditVersion` (function, optional): A callback function that is called when the edit button is clicked. It receives the clicked `TimelineVersion` object as an argument.
*   `onDeleteVersion` (function, optional): A callback function that is called when the delete button is clicked. It receives the clicked `TimelineVersion` object as an argument.
*   `showEditButton` (boolean, optional): A boolean indicating whether to show the edit button. Defaults to `true`.
*   `showDeleteButton` (boolean, optional): A boolean indicating whether to show the delete button. Defaults to `true`.
*   `timelineTitle` (string, optional): A string to set the title of the timeline. Defaults to "Timeline Demo".
*   `showTimelineTitle` (boolean, optional): A boolean indicating whether to show the title. Defaults to `true`.
*   `dateFormat` (string, optional): A string to set the date format. Defaults to `en-GB`. This should be a valid locale string (e.g., 'en-US', 'de-DE', etc.).
*   `testMode` (boolean, optional): A boolean indicating whether to show the modal when the add button is clicked. Defaults to `true`.

The `Timeline` component accepts configuration options as props. If these props are not provided, the component will use the default values (which are defined in `testdata.json` when running the component standalone).

Here's how you can pass configuration options from the parent application:

```jsx
<Timeline
  versions={versions}
  variations={variations}
  onEditVersion={handleEditVersion}
  onDeleteVersion={handleDeleteVersion}
  onAddVersion={handleAddVersion}
  showEditButton={false}
  showDeleteButton={true}
  timelineTitle="My Custom Timeline"
  showTimelineTitle={true}
  dateFormat="en-US"
/>
```

In this example:

*   The edit buttons will be hidden (`showEditButton={false}`).
*   The delete buttons will be visible (`showDeleteButton={true}`).
*   The timeline title will be set to "My Custom Timeline" (`timelineTitle="My Custom Timeline"`).
*   The timeline title will be visible (`showTimelineTitle={true}`).
*   The date format will be set to US format (`dateFormat="en-US"`).

If you do not provide these props, the component will use the default values (which are defined in `testdata.json` when running the component standalone).

## Listening for Click Events

The `Timeline` component dispatches custom events on the `window` object when the edit or delete buttons are clicked.

### Edit Button Click

To listen for edit button clicks, add an event listener for the `'edit-version'` event:

```javascript
window.addEventListener('edit-version', (event) => {
  const version = event.detail;
  console.log('Edit version clicked:', version.id, version);
  // Handle the edit action, e.g., open a modal
});
```

The `event.detail` property will contain the full `TimelineVersion` object that was clicked.

### Delete Button Click

To listen for delete button clicks, add an event listener for the `'delete-version'` event:

```javascript
window.addEventListener('delete-version', (event) => {
  const version = event.detail;
  console.log('Delete version clicked:', version.id, version);
  // Handle the delete action, e.g., remove the version
});
```

The `event.detail` property will contain the full `TimelineVersion` object that was clicked.

### Add Button Click

To listen for add button clicks, add an event listener for the `'add-version-requested'` event:

```javascript
window.addEventListener('add-version-requested', (event) => {
  const { start, end, variationId } = event.detail;
  console.log('Add version requested:', start, end, variationId);
  // Handle the add action, e.g., open a modal
});
```

The `event.detail` property will contain an object with the following properties:
    *   `start`: The recommended start date (Date object).
    *   `end`: The recommended end date (Date object).
    *   `variationId`: The ID of the variation where the button was clicked (string).

## Triggering a Reload

To trigger a reload of the timeline component, the parent application should dispatch a custom event called `'reload-timeline'` on the `window` object.

```javascript
window.dispatchEvent(new CustomEvent('reload-timeline'));
```

After dispatching this event, the parent application should update the `versions` and `variations` props of the `Timeline` component with the new data. The component will display a loading animation while waiting for the new data and will re-render automatically when the props are updated.

## Styling

The component uses Tailwind CSS for styling. You can customize the styling by overriding the default Tailwind classes.

To include the default styles, you must import the component's CSS file in your application:

```javascript
import 'jm_vertical_timeline/dist/style.css';
```

**Troubleshooting CSS Issues:**

If the timeline component appears without styles, ensure that:

*   You have correctly imported the CSS file: `import 'jm_vertical_timeline/dist/style.css';`
*   Your bundler is configured to process CSS files.
*   The path to the CSS file is correct.
*   There are no conflicting CSS rules in your parent application.
*   **Your parent application is also set up to use Tailwind CSS and is configured to scan the component's files for Tailwind classes.**

If you are still having issues, try inspecting the page in your browser's developer tools to see if the CSS file is being loaded and if there are any errors.

## Further Customization

More documentation will be added as the component evolves.