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

@adesin-fr/vue-gantt-timeline

v2026.45.1

Published

Composant Vue 3 de planning / gantt : groupes, éléments déplaçables, empilement automatique, rendu personnalisable.

Readme

vue-gantt-timeline

Composant Vue 3 de planning / gantt : une colonne de groupes à gauche, une fenêtre de dates figée à droite, des blocs déplaçables et empilés automatiquement.

  • rendu strictement limité à la fenêtre [start, end] : aucun bloc « fantôme » hors plage ;
  • empilement au plus juste : un bloc est posé sur la première ligne virtuelle libre, une nouvelle ligne n'est créée que si aucune ne peut l'accueillir ;
  • déplacement dans le temps et d'un groupe à l'autre, redimensionnement par les bords, avec évènements émis à chaque fois ;
  • rendu des blocs par slot ou par fonction ;
  • virtualisation verticale : seules les lignes visibles sont montées (centaines de groupes OK) ;
  • aucune dépendance runtime en dehors de Vue.

La fenêtre affichée est pilotée par les props start / end. Deux gestes optionnels la font varier, désactivés par défaut :

  • pannable — clic-glisser dans le vide pour faire défiler la plage de dates (le mouvement vertical fait défiler les groupes en même temps) ;
  • zoomable — pincement (gestes WebKit ou deux doigts) et molette + ctrl (cmd sur macOS), avec zoom centré sur le curseur.

Dans les deux cas le composant émet range-change et update:start / update:end : la fenêtre se pilote donc au choix par v-model:start / v-model:end ou à la main. Une molette sans modificateur conserve son rôle de défilement vertical.

Installation

npm install @adesin-fr/vue-gantt-timeline
import { GanttTimeline } from '@adesin-fr/vue-gantt-timeline'
import '@adesin-fr/vue-gantt-timeline/style.css'

Utilisation

<GanttTimeline
    :groups="[{ id: 1, label: 'Atelier' }]"
    :items="[{ id: 'a', group: 1, start: '2026-09-07 08:00', end: '2026-09-07 12:00', content: 'OT 1234' }]"
    :start="windowStart"
    :end="windowEnd"
    :editable="{ updateTime: true, updateGroup: true }"
    @item-move="onMove"
    @item-resize="onMove"
>
    <template #item="{ item }">
        <strong>{{ item.content }}</strong>
    </template>
</GanttTimeline>

Le composant ne modifie jamais items : à réception de item-move / item-resize, c'est au parent d'appliquer (ou de refuser) le nouveau positionnement. Tant qu'il ne le fait pas, le bloc revient à sa position d'origine.

Props

| Prop | Défaut | Rôle | | --- | --- | --- | | groups | — | lignes du planning ({ id, label?, className?, style?, minHeight? }) | | items | — | blocs ({ id, group, start, end?, content?, title?, className?, style?, type?, editable? }) | | dependencies | [] | flèches entre blocs ({ id?, from, to, className?, style? }), voir ci-dessous | | dependencyKey | id du bloc | (item) => clé : blocs mis en évidence ensemble dans une chaîne de dépendances | | start, end | — | fenêtre affichée (Date, timestamp, ISO ou YYYY-MM-DD HH:mm:ss) | | editable | false | boolean ou { updateTime, updateGroup }, surchargeable par bloc | | snap | 900000 | arrondi pendant un déplacement : ms ou (date, kind) => date | | minDuration | 300000 | durée minimale d'un bloc au redimensionnement | | stack | true | empilement des blocs qui se chevauchent | | order | — | tri des blocs d'un groupe avant empilement | | itemRenderer | — | (item, group) => string (HTML) si le slot item n'est pas utilisé | | groupWidth | 180 | largeur de la colonne des groupes | | laneHeight / laneGap / rowPadding / minRowHeight | 26 / 2 / 4 / 40 | métriques verticales | | minItemWidth / itemMargin | 6 / 2 | largeur minimale d'un bloc, écart de collision | | locale / weekStart | navigateur / 1 | axe temporel | | timeScale | — | impose l'échelle de l'axe, ex. { unit: 'day', step: 1 } (sinon déduite de la largeur) | | hiddenTimeRanges | [] | plages horaires récurrentes retirées de l'axe, ex. [{ start: '18:00', end: '08:00' }] (nuit) ou [{ start: '00:00', end: '24:00', days: [0, 6] }] (week-end). Voir ci-dessous | | showCurrentTime | true | trait de l'heure courante | | overscan | 3 | lignes rendues hors zone visible | | pannable | false | défilement de la plage au clic-glisser dans le vide | | zoomable | false | zoom au pincement et à la molette + ctrl/cmd | | zoomMin / zoomMax | 600000 / 5 ans | amplitude minimale et maximale de la fenêtre au zoom | | minDate / maxDate | — | bornes au-delà desquelles la fenêtre ne peut pas aller |

Évènements

| Évènement | Payload | | --- | --- | | item-drag | position provisoire, émise pendant le déplacement | | item-move | déplacement validé (temps et/ou groupe) | | item-resize | redimensionnement validé | | item-click, item-dblclick, item-contextmenu | { item, group, event } | | background-click, background-dblclick | { group, time, event } — création de bloc | | group-click, group-dblclick | { group, event } | | range-change | { start, end, reason: 'pan' \| 'zoom' } | | update:start, update:end | nouvelle borne (v-model:start / v-model:end) |

item-drag / item-move / item-resize reçoivent { item, kind, start, end, group, previousStart, previousEnd, previousGroup, groupChanged }.

Le composant expose aussi setWindow(start, end), scrollToGroup(id), timeToX, xToTime.

Slots

  • item — { item, group, placed }, contenu d'un bloc ;
  • group — { group, row }, libellé d'une ligne ;
  • corner — coin haut-gauche ;
  • empty — aucun groupe.

Personnalisation

Les couleurs passent par des variables CSS sur .vgt (--vgt-item-bg, --vgt-border, --vgt-now, --vgt-dependency, --vgt-chain, …) ; className et style sur un bloc ou un groupe restent prioritaires.

Développement

npm run dev          # playground (demo/App.vue)
npm run build        # vérification des types + build de la lib dans dist/
npm run build:watch  # rebuild à chaud, pratique avec un `npm link`

Lien local vers une application

cd /chemin/vers/ganttTimeline && npm link
cd /chemin/vers/application && npm link @adesin-fr/vue-gantt-timeline

Côté application Vite, dédupliquer Vue (le paquet lié embarque le sien) :

resolve: { dedupe: ['vue'] },
server: { fs: { allow: ['..'] } },
optimizeDeps: { exclude: ['@adesin-fr/vue-gantt-timeline'] },

Masquer des plages horaires

hiddenTimeRanges reçoit un tableau de { start, end, days? } (HH:mm, 24:00 accepté pour end). Si start est après end, la plage passe minuit et appartient au jour où elle commence. days (0 = dimanche … 6 = samedi) restreint la plage à certains jours de début.

Les plages masquées ne prennent aucune largeur : le temps visible est mis bout à bout, un trait pointillé marque chaque coupure, et les blocs entièrement masqués ne sont pas rendus. Un bloc à cheval sur une coupure est affiché d'un seul tenant. zoomMin / zoomMax s'appliquent à la durée visible. start / end (et range-change) restent de vrais instants.

Flèches de dépendance

dependencies reçoit un tableau de { id?, from, to, className?, style? }, où from et to sont des ids de blocs. La flèche part du bord droit de from et arrive sur le bord gauche de to, au milieu de leur ligne d'empilement, en coudes à angle droit. Si to commence avant la fin de from, elle contourne en passant entre les deux lignes.

Les flèches suivent un bloc pendant son déplacement. Celles dont un des deux blocs n'est pas rendu (hors fenêtre, masqué, ou d'un groupe absent) ne sont pas tracées. Elles ne captent pas la souris. La couleur se règle par --vgt-dependency, ou par className / style (stroke) sur une dépendance ; la pointe suit la couleur du trait.

Dès qu'on saisit un bloc pour le déplacer ou le redimensionner, toute sa chaîne est mise en évidence : ses parents et ses enfants, de proche en proche, reçoivent un halo (vgt__item--chain) et les flèches qui les relient sont renforcées (vgt__dependency--chain), couleur --vgt-chain. Les branches sœurs (les autres blocs qui attendent un même parent) ne sont pas concernées. dependencyKey regroupe plusieurs blocs en un seul maillon, par exemple une même tâche affichée sur la ligne de chacun de ses intervenants.

buildDependencyPaths(rows, dependencies, metrics) est exporté pour qui veut tracer ses flèches lui-même à partir de rows (exposé par le composant).