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 🙏

© 2024 – Pkg Stats / Ryan Hefner

ts-gantt

v0.7.0

Published

simple gantt chart written using typescript

Downloads

509

Readme

TsGantt

Simple library for creating gantt chart combined with task grid.

Current features

Getting started

Install and initialize

With npm

npm install ts-gantt
import { TsGantt } from "ts-gantt";

const chart = new TsGantt("#container-selector");

include stylesheet ('ts-gantt/dist/styles.min.css') in any suitable way

Or using CDN

<link rel="stylesheet" href="https://unpkg.com/ts-gantt/dist/styles.min.css">
<script src="https://unpkg.com/ts-gantt/dist/ts-gantt.umd.min.js"></script>
const chart = new tsGantt.TsGantt("#container-selector");

⚠️for chart to function properly its container element must have relative, absolute or fixed position!

⚠️if you use the shadow DOM mode for the chart, including the stylesheet is not needed, the styles bundled inside the main file will be used.

Set your task list

your tasks must implement following interface

interface TsGanttTaskModel {
  id: string; // to avoid incorrect behaviour please use unique ids within array
  parentId: string | null | undefined; // use if you need tree-like structure

  name: string;  
  progress: number; // percentage from 0 to 100. higher or lower values will be truncated

  datePlannedStart: Date | null | undefined;
  datePlannedEnd: Date | null | undefined;  
  dateActualStart: Date | null | undefined;
  dateActualEnd: Date | null | undefined;
  
  localizedNames: {[key: string]: string} | null | undefined; // eg {"en": "Name", "uk": "Ім'я", "ru": "Имя"}
}

to pass your task array to chart use 'tasks' property setter

chart.tasks = yourTaskArray;

task are updated in the same way. you should just pass actual task array when any change happens. change detection will find tasks that have been changed/added/removed and will replace/add/remove them in chart.

Switch modes

Language

you can instantly switch chart language

chart.locale = locale; // "en" | "uk" | "ru" | "ja" or any custom locale you provided in chart options

Timeline scale

you can instantly switch chart timeline scale

chart.chartScale = scale; // "day" | "week" | "month" | "year"

Display mode (chart bars)

you can instantly switch chart bar display mode

chart.chartDisplayMode = mode; // "planned" | "actual" | "both"

"planned" - show only planned dates bar on timeline "actual" - show only actual dates bar on timeline

Select tasks

select task rows programmatically

chart.selectedTasks = [{id: "taskIdString"}];

get selected tasks

const selectedTasks = chart.selectedTasks;

Customize chart

you can customize chart in two ways:

Css

preffered way to customize styling is to change css variable values. It'll work for both regular DOM and shadow DOM modes

:root {
  --tsg-table-min-width: 100px;
  --tsg-chart-min-width: 100px;
  --tsg-nesting-indent: 20px; /* indent width per nesting level */
  
  --tsg-background-color: white;
  --tsg-foreground-color: black;
  --tsg-separator-color: rgb(80, 80, 80); /* color of movable vertical line between parts */
  --tsg-header-color: rgb(210, 210, 210); /* header background color */
  --tsg-border-color: rgb(190, 190, 190);
  --tsg-symbol-color: rgb(80, 80, 80); /* color of row special symbols */
  --tsg-selection-color: rgb(230, 230, 230); /* background color of selected row */  
  --tsg-scrollbar-track-color: #eeeeee; /* webkit browsers only */  
  --tsg-scrollbar-thumb-color: #b0b0b0; /* webkit browsers only */  

  --tsg-not-started-fg-color: dimgray; /* color of task row text depending on task state */
  --tsg-in-progress-fg-color: black;
  --tsg-overdue-fg-color: darkred;
  --tsg-completed-fg-color: darkgreen;
  --tsg-completed-late-fg-color: sienna;

  --tsg-today-line-color: orangered; /* color of vertical line on chart that represents today */  
  --tsg-chart-bar-color-1: skyblue; /* chart bars colors */
  --tsg-chart-bar-color-2: lightcoral;
  --tsg-chart-bar-accent-1: darkcyan;
  --tsg-chart-bar-accent-2: darkred;  
  
  --tsg-font-family: 'Calibri', sans-serif;
  --tsg-font-size: 14px;
  --tsg-line-height: 16px;
  --tsg-max-cell-text-lines: 2; /* max lines of multiline text */
}

Options

you can apply your custom options by passing options object as second parameter to 'TsGantt' constructor

const options = new TsGanttOptions({
    multilineSelection: false,
    enableChartEdit = true;
    // other options you want to change
});
// or you can use assignment expressions (come in handy for getters and formatters that refence options object itself)
options.columnValueGetters[0] = task => 
    task.localizedNames && task.localizedNames[options.locale] || task.name; // value getter implementation for first column

// esm chart init with options
const chart = new TsGantt("#container-selector", options); 
// umd chart init with options
const chart = new tsGantt.TsGantt("#container-selector", options);

// ⚠️chart class in not designed to allow changes in options instance after the chart initialization.
// such changes can lead to unpredictable behavior.
// to change locale, scale and display mode use appropriate TsGantt instance methods.
// if it's very necessary to change other options after chart init then you should destroy old chart instance and create new one.
this.chart.destroy();
this.chart = new TsGantt("#container-selector", options);
   // some default values ommited for brevity. you can always see them in 'TsGanttOptions' source code

  useShadowDom = false; // render chart using shadow DOM

  multilineSelection = true; // allow multiple rows to be selected at the same time
  useCtrlKeyForMultilineSelection = false; // enable using ctrl key to select multiple rows

  drawTodayLine = true; // draw a vertical line on chart that represents today  
  highlightRowsDependingOnTaskState = true; // change row text color depending on task state

  separatorWidthPx = 5; // vertical central line width
  headerHeightPx = 90; // lower values are not recommended, but you can still try
  rowHeightPx = 40; // lower values are not recommended, but you can still try
  borderWidthPx = 1;
  barStrokeWidthPx = 2;
  barMarginPx = 2;
  barCornerRadiusPx = 6;

  // special row symbols. you can also use some HTML code
  rowSymbols: TsGanttRowSymbols = {childless: "◆", collapsed: "⬘", expanded: "⬙"};

  chartShowProgress = true; // indicating progress percentage on chart bar using different color
  chartDisplayMode: "planned" | "actual" | "both";
  chartScale: "day" | "week" | "month" | "year";
  
  // optimal spare space on timeline edges in days
  chartDateOffsetDays: {[key: string]: number} = {"day": 14, "week": 60, "month": 240, "year": 730};
  // minimal spare space on timeline edges in days
  // chart timeline is redrawn only when trespassing minimal distance to chart edge to nearest bar
  chartDateOffsetDaysMin: {[key: string]: number} = {"day": 7, "week": 30, "month": 120, "year": 365};
  // width of 1 day on timeline. not recommended to use lower values than default
  chartDayWidthPx: {[key: string]: number} = {"day": 60, "week": 20, "month": 3, "year": 1};

  locale = "en"; // default locale
  localeDecimalSeparator: {[key: string]: string} = {en: ".", uk: ",", ru: ",", ja: "."};
  // you can provide any format strings that are supported by dayjs
  localeDateFormat: {[key: string]: string} = {en: "MM/DD/YYYY", uk: "DD.MM.YYYY", ru: "DD.MM.YYYY", ja: "YYYY/MM/DD"};
  localeFirstWeekDay: {[key: string]: number} = {en: 0, uk: 1, ru: 1, ja: 0}; // Sunday is 0
  localeDateMonths: {[key: string]: string[]}; // array of 12 string values for each locale. eg ["January", "February", ...etc]  
  localeDateDays: {[key: string]: string[]}; // array of 7 string values for each locale. eg ["Sunday", "Monday", ...etc]
  localeDateDaysShort: {[key: string]: string[]}; // array of 7 string values for each locale. eg ["Su", "Mo", ...etc]
  localeDateScale: {[key: string]: string[]}; // array of 3 string values for each locale. eg ["Weeks", "Months", "Years"]
  localeDurationFormatters: {[key: string]: (duration: number) => string}; // duration formatter function for each locale

  // Data columns setup.
  // there are default 8 columns: "Name", "Progress", "Start date planned", "End date planned",
  // "Start date actual", "End date actual", "Duration planned", "Duration actual".
  // You can remove the columns or add your own ones, but you need too make sure to edit all of the following arrays respectively:
  // you should provide a width, an alignment, a value getter, and localized headers.
  // !!!the length of each column-related array should be equal to the columns count!!!
  columnsMinWidthPx: number[]; // array of numeric values, one for each of the columns. 0 to disable column
  columnsContentAlign: ("start" | "center" | "end")[]; // array of values, one for each of the columns
  // default column value getters return localized values by taking into account all the properties assigned above
  // but you can provide your own ones if you need more complex output 
  // returned value is assigned to cell's innerHTML property. so you can use html tags
  columnValueGetters: ((a: TsGanttTask) => string)[]; // array of string value getters for each locale
  // column header locales should be provided for all the locales intended for use
  localeHeaders: {[key: string]: string[]}; // array of string values for each locale
  //
  
  taskComparer: (taskA: TsGanttTask, taskB: TsGanttTask) => number; // you can provide here your custom task comparer
     
  enableChartEdit = false; // (experimental) allows making changes to tasks by dragging chart bar handles
  // all the task models including the changed ones can be returned to your code using the TsGantt.tasks property getter

Event callbacks

you can pass callbacks for chart row events using TsGantt properties shown below

onRowClickCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
onRowDoubleClickCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
onRowContextMenuCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
onSelectionChangeCb: (models: TsGanttTaskModel[]) => void;

context menu implementation is not provided, but you can implement your own using callback

Adding a custom column to the end of the column list example

const options = new tsGantt.TsGanttOptions();
options.columnsMinWidthPx.push(100);
options.columnsContentAlign.push("center");
// the "customColumnKey" below is the property of the model object
// which contains the value needed to be shown
options.columnValueGetters.push(task => (task["customColumnKey"] ?? ""));
options.localeHeaders.en.push("User column");

const ganttChart = new tsGantt.TsGantt("#gantt-container", options);

TODO list