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

@ganttkit/plugin-scheduler

v0.1.2

Published

Resource↔task assignment scheduling for GanttKit: resource lanes, cross-chart drag-to-assign, and synced timelines.

Readme

@ganttkit/plugin-scheduler

Resource↔task assignment scheduling for GanttKit. Turns a task-oriented Gantt into a resource-scheduling view and wires up drag-to-assign between two stacked charts — the pattern used by MS Project's Team Planner, Float, Ganttic and friends.

The whole feature is a plugin: the core engine is untouched. It already allows many bars per row, which is exactly what a resource lane is.

The model

One source of truth — an Assignment linking a task to a resource over an inclusive date window:

interface Assignment { id: string; taskId: string; resourceId: string; start: DateInput; end: DateInput }

From it the plugin derives resource lanes (one row per resource; each assignment → a bar). Because a lane holds many bars, this models both hard cases for free:

  • A task with multiple resources — the same taskId appears in several lanes.
  • A resource split across tasks (day 1 on task A, day 2 on task B) — two bars in one lane.

Availability

Each resource carries an availability calendar — a working-day pattern and a list of disabled dates:

interface Resource {
  id: string; name: string
  workingDays?: Weekday[]        // e.g. ['Mo','Tu','We','Th','Fr'] (default Mon–Fri)
  unavailableDates?: DateInput[] // holidays / PTO — off even on a working weekday
}

Non-working weekdays and disabled dates are shaded in the lane (style .gantt-unavailable, e.g. light red) and cannot begin a slot selection. Query it directly with isResourceAvailable(resource, date).

Pieces

| Export | Role | | --- | --- | | createScheduler(opts) | Assignment store + resourcePlugin (feeds resource lanes via the rows hook, draws the drop-hint via the scene hook). | | createSchedulerDnd(opts) | Cross-chart drag-to-assign coordinator. Renderer-agnostic (uses the published viewport port). | | linkTimelines(opts) | Keep two+ engines' view-mode and horizontal scroll in lockstep. |

Usage

import { createGantt } from '@ganttkit/svg'
import { createColumns } from '@ganttkit/plugin-columns'
import { createScheduler, createSchedulerDnd, linkTimelines } from '@ganttkit/plugin-scheduler'

const scheduler = createScheduler({ resources, tasks, assignments })

// Top chart: resources. Rows come from the plugin; bar-drag is disabled so the
// DnD coordinator owns the gesture. Same explicit date range as the task chart.
const resourceEngine = createGantt({ target: '#resources', rows: [], startDate, endDate, draggable: false })
resourceEngine.use(createColumns({ columns: [{ key: 'name', label: 'Resource' }] }).plugin)
resourceEngine.use(scheduler.resourcePlugin)

// Bottom chart: tasks — the drag source.
const taskEngine = createGantt({ target: '#tasks', rows: taskRows, startDate, endDate, draggable: false })
taskEngine.use(createColumns({ columns: [{ key: 'name', label: 'Task' }] }).plugin)

createSchedulerDnd({
  scheduler,
  task: { engine: taskEngine, root: document.querySelector('#tasks')! },
  resource: { engine: resourceEngine, root: document.querySelector('#resources')! },
  onChange: c => console.log(c.type, c.assignment),
})

linkTimelines({
  engines: [resourceEngine, taskEngine],
  roots: [document.querySelector('#resources')!, document.querySelector('#tasks')!],
})

Interaction

  • Assign — drag a task bar (bottom) onto a resource lane (top). Drops the same task on several lanes for multi-resource work.
  • Select slotsrubber-band drag free days in resource lanes (plain = replace, Ctrl/⌘ = add), Ctrl/⌘-click to toggle individual cells across lanes, Esc to clear. Only available, unbooked days are selectable.
  • Slots → task — drag the selection onto a task to book every selected slot to it. Contiguous days per resource collapse into one assignment.
  • Retime — drag an assignment bar within its lane.
  • Reassign — drag an assignment bar to a different lane.
  • Unassign — drag an assignment bar off the resource chart.

A drop-hint (drawn into the scene, so it's pixel-perfect on every renderer) previews where the bar will land — blue for assign, green for slot selection.

Styling

Add a taskClassName in createScheduler to colour assignment bars per task, and provide these classes (see the SVG resources example for a full set):

.gantt-unavailable { fill: rgba(239, 68, 68, 0.14); }              /* light-red off days */
.gantt-drop-hint   { fill: none; stroke: var(--gk-accent); stroke-dasharray: 4 3; }
.gantt-slot-hint   { fill: rgba(16,185,129,.22); stroke: #10b981; } /* slot selection */
.gantt-drag-ghost  { position: fixed; z-index: 1000; pointer-events: none; /* … */ }

License

MIT