[
  {
    "path": ".browserslistrc",
    "content": "> 1%\nlast 2 versions\nnot dead\n"
  },
  {
    "path": ".editorconfig",
    "content": "[*.{js,jsx,ts,tsx,vue}]\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nmax_line_length = 100"
  },
  {
    "path": ".eslintrc.cjs",
    "content": "/* eslint-env node */\nrequire(\"@rushstack/eslint-patch/modern-module-resolution\")\n\nmodule.exports = {\n  root: true,\n\n  extends: [\n    \"plugin:vue/vue3-recommended\",\n    \"eslint:recommended\",\n    \"@vue/eslint-config-typescript/recommended\",\n    \"@vue/eslint-config-prettier\"\n  ],\n\n  rules: {\n    \"no-console\": process.env.NODE_ENV === \"production\" ? \"warn\" : \"off\",\n    \"no-debugger\": process.env.NODE_ENV === \"production\" ? \"warn\" : \"off\",\n    \"@typescript-eslint/no-unused-vars\": \"off\",\n    \"@typescript-eslint/explicit-module-boundary-types\": \"off\",\n    quotes: [\"error\", \"double\"],\n    // \"object-curly-spacing\": [\"error\", \"never\"],\n    \"prettier/prettier\": [\"error\", {}, { usePrettierrc: true }]\n  }\n}\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\n"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "content": "# Sample workflow for building and deploying a VitePress site to GitHub Pages\n#\nname: Deploy VitePress site to Pages\n\non:\n  # Runs on pushes targeting the `main` branch. Change this to `master` if you're\n  # using the `master` branch as the default branch.\n  push:\n    branches: [master]\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\n# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\nconcurrency:\n  group: pages\n  cancel-in-progress: false\n\njobs:\n  # Build job\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0 # Not needed if lastUpdated is not enabled\n      # - uses: pnpm/action-setup@v3 # Uncomment this if you're using pnpm\n      # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun\n      - name: Setup Node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: npm # or pnpm / yarn\n      - name: Setup Pages\n        uses: actions/configure-pages@v4\n      - name: Install dependencies\n        run: npm ci # or pnpm install / yarn install / bun install\n      - name: Build with VitePress\n        run: npm run docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: docs/.vitepress/dist\n\n  # Deployment job\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    needs: build\n    runs-on: ubuntu-latest\n    name: Deploy\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n/lib\n/lib_types\n\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n# Docs dist directory\ndocs/.vitepress/cache\ndocs/.vitepress/temp\ndocs/.vitepress/dist\n\n*.tgz\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"semi\": false,\n  \"trailingComma\": \"none\",\n  \"endOfLine\": \"auto\"\n}"
  },
  {
    "path": "README.md",
    "content": "# Vue Ganttastic\n\n<div style=\"display: flex; flex-direction: column; align-items:center;\">\n<img\n    src=\"https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png\" \n    style=\"margin: 10px;\" height=\"150\"\n    alt=\"Vue Ganttastic logo\"\n/>\n\n<b>Vue Ganttastic</b> is a simple, interactive and highly customizable Gantt chart component for Vue 3.\n\n![image](https://user-images.githubusercontent.com/28678851/148191571-76bd8d61-4583-4538-8c59-cc2915494890.png)\n\n</div>\n\n## Features\n\n- **[Vue 3](https://v3.vuejs.org/) support**\n- **[TypeScript](https://www.typescriptlang.org/) support** _(ships with out of the box type declarations)_\n- **Interactivity** _(dynamic, movable and pushable bars)_\n- **Reactivity / Responsiveness** (_when changes occur, bars are repositioned accordingly_)\n- **Customization options** (_chart/bar styling, slots, event handlers etc._)\n\nUsing Vue 2? Check out [Vue-Ganttastic v1](https://github.com/zunnzunn/vue-ganttastic/tree/vue-ganttastic-v1).\n\n## Guide and Docs\n\nFor further guides and references, check out the [official docs](https://zunnzunn.github.io/vue-ganttastic/getting-started.html).\n\n## Quickstart\n\nInstall using\n\n```\nnpm install @infectoone/vue-ganttastic\n```\n\nThen, initalize the plugin in the starting point of your app (most likely src/main.js):\n\n```js\nimport { createApp } from \"vue\"\nimport App from \"./App.vue\"\n...\nimport ganttastic from '@infectoone/vue-ganttastic'\n...\ncreateApp(App)\n  .use(ganttastic)\n  .mount('#app')\n```\n\nThis will globally register the components g-gantt-chart and g-gantt-row and you will be able to use those two components right away.\n\n```html\n<template>\n  <g-gantt-chart\n    chart-start=\"2021-07-12 12:00\"\n    chart-end=\"2021-07-14 12:00\"\n    precision=\"hour\"\n    bar-start=\"myBeginDate\"\n    bar-end=\"myEndDate\"\n  >\n    <g-gantt-row label=\"My row 1\" :bars=\"row1BarList\" />\n    <g-gantt-row label=\"My row 2\" :bars=\"row2BarList\" />\n  </g-gantt-chart>\n</template>\n\n<script setup>\n  import { ref } from \"vue\"\n\n  const row1BarList = ref([\n    {\n      myBeginDate: \"2021-07-13 13:00\",\n      myEndDate: \"2021-07-13 19:00\",\n      ganttBarConfig: {\n        // each bar must have a nested ganttBarConfig object ...\n        id: \"unique-id-1\", // ... and a unique \"id\" property\n        label: \"Lorem ipsum dolor\"\n      }\n    }\n  ])\n  const row2BarList = ref([\n    {\n      myBeginDate: \"2021-07-13 00:00\",\n      myEndDate: \"2021-07-14 02:00\",\n      ganttBarConfig: {\n        id: \"another-unique-id-2\",\n        hasHandles: true,\n        label: \"Hey, look at me\",\n        style: {\n          // arbitrary CSS styling for your bar\n          background: \"#e09b69\",\n          borderRadius: \"20px\",\n          color: \"black\"\n        },\n        class: \"foo\" // you can also add CSS classes to your bars!\n      }\n    }\n  ])\n</script>\n```\n\n## Contributing\n\nClone the project, make some changes, test your changes out, create a pull request with a short summary of what changes you made. Contributing is warmly welcomed!\n\nTo test your changes out before creating a pull request, create a build:\n\n```\nnpm run build\n```\n\nTo test out the build, you should create a tarball using:\n\n```\nnpm pack\n```\n\nThen, place the tarball in some other test project and install the package from the tarball by using:\n\n```\nnpm install <name_of_the_package>.tgz\n```\n\n\n## About\n\n**License** [MIT](https://choosealicense.com/licenses/mit/)  \n**Author**: Marko Žunić, BSc  \n[GitHub Repository](https://github.com/zunnzunn/vue-ganttastic)\n\n## Support the project!\n\nIn case you found the library useful, a little tip would be much appreciated!\n\n<form action=\"https://www.paypal.com/donate\" method=\"post\" target=\"_top\">\n<input type=\"hidden\" name=\"hosted_button_id\" value=\"M63C8DAMV5YDJ\" />\n<input type=\"image\" src=\"https://pics.paypal.com/00/s/MTdhMWZmNTUtOWQ1Yi00YmRjLWJjMjgtY2Y0NTNhODM0OTJl/file.PNG\" border=\"0\" name=\"submit\" title=\"PayPal - The safer, easier way to pay online!\" alt=\"Donate with PayPal button\" style=\"max-width:200px\"/>\n<img alt=\"\" border=\"0\" src=\"https://www.paypal.com/en_AT/i/scr/pixel.gif\" width=\"1\" height=\"1\" />\n</form>\n\nBTC address:  \n![image](https://user-images.githubusercontent.com/28678851/233090745-a0a6d8a4-6df6-4b82-ac0c-90e69551786e.png)\n\n## Screenshots\n\n![image](https://user-images.githubusercontent.com/28678851/148191571-76bd8d61-4583-4538-8c59-cc2915494890.png)\n\n![image](https://user-images.githubusercontent.com/28678851/148191529-b50c0d17-bcc1-4a78-9d2c-ff2a36b03f52.png)\n\n![image](https://user-images.githubusercontent.com/28678851/148191757-a2520dce-aeed-43df-87b2-3a64e225f9e7.png)\n"
  },
  {
    "path": "deploy.sh",
    "content": "set -e\n\nnpm run docs:build\ncd docs/.vuepress/dist\n\ngit init\ngit add -A\ngit commit -m 'deploy'\n\ngit push -f git@github.com:InfectoOne/vue-ganttastic.git master:gh-pages\n\ncd -"
  },
  {
    "path": "docs/.vitepress/config.ts",
    "content": "import { defineConfig } from 'vitepress'\n\n// https://vitepress.dev/reference/site-config\nexport default defineConfig({\n  lang: 'en-US',\n  title: 'Vue-Ganttastic',\n  description: 'Simple and customizable Gantt chart component for Vue 3.',\n  base: '/vue-ganttastic/',\n  head: [['link', { rel: 'icon', href: 'https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png' }]],\n  themeConfig: {\n    logo: 'https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png',\n    nav: [\n      { text: 'Home', link: '/' },\n    ],\n    sidebar: [\n      { text: 'Introduction', link: '/introduction'},\n      { text: 'Getting Started',link: '/getting-started' },\n      { text: 'Common use cases', link: '/common-use-cases' },\n      { text: 'Examples', link: '/examples' },\n      {\n        text: 'API Reference',\n        items: [\n          { text: 'GGanttChart', link: '/GGanttChart' },\n          { text: 'GGanttRow', link: '/GGanttRow' }\n        ]\n      }\n    ],\n    socialLinks: [\n      { icon: 'github', link: 'https://github.com/zunnzunn/vue-ganttastic' }\n    ]\n  }\n})\n"
  },
  {
    "path": "docs/.vitepress/theme/custom.css",
    "content": ":root {\n    --vp-home-hero-name-color: #2fb585;\n    --vp-button-brand-bg: #2fb585;\n    --vp-button-brand-hover-bg: #354b5d;\n    --vp-c-brand: #2fb585;\n}"
  },
  {
    "path": "docs/.vitepress/theme/index.js",
    "content": "import DefaultTheme from 'vitepress/theme'\nimport './custom.css'\nimport {ganttastic} from \"../../../src/vue-ganttastic\"\n\nexport default {\n    extends: DefaultTheme,\n    enhanceApp(ctx) {\n        ctx.app.use(ganttastic)\n\n    }\n}"
  },
  {
    "path": "docs/GGanttChart.md",
    "content": "# API: GGanttChart\nThe main component of Vue Ganttastic. Represents an entire chart and is meant to have at least one `g-gantt-row` child component.\n## Props\n| Prop        | Type    | Default | Description                  |\n|-------------|---------|---------|------------------------------|\n| `chart-start` | string | | Start date-time of the chart.\n| `chart-end` | string  | | End date-time of the chart.\n| `precision` | string? | `\"hour\"` | Display precision of the time-axis. Possible values: `hour`, `day`, `date`, `week` and `month`. |\n| `bar-start` | string | | Name of the property in bar objects that represents the start date.\n| `bar-end` | string  | | Name of the property in bar objects that represents the end date .\n| `date-format` | string \\| false  | `\"YYYY-MM-DD HH:mm\"` | Datetime string format of `chart-start`, `chart-end` and the values of the `bar-start`, `bar-end` properties in bar objects. See [Day.js format tokens](https://day.js.org/docs/en/parse/string-format). If the aforementioned properties are native JavaScript [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) objects in your use case, pass `false`.\n| `width` | string? | `\"100%\"` | Width of the chart (e.g. `80%` or `800px`)\n| `hide-timeaxis` | boolean? | `false` | Toggle visibility of the time axis.\n| `color-scheme` | string \\| ColorScheme | `\"default\"` | Color scheme (theme) of the chart. Either use the name of one of the predefined schemes or pass a color-scheme-object of your own. See [color schemes](#color-schemes).\n| `grid` | string? | `false` | Toggle visibility of background grid.\n| `current-time` | boolean? | `false` | Toggle visibility of current time marker.\n| `current-time-label` | string? | `''` | Text to be displayed next to the current time marker.\n| `push-on-overlap` | boolean? | `false` | Specifies whether bars \"push one another\" when dragging and overlaping.\n| `no-overlap` | boolean? |  `false` | If `push-on-overlap` is `false`, toggle this to prevent overlaps after drag by snapping the dragged bar back to its original position.\n| `row-height` | number? | `40` | Height of each row in pixels.\n| `highlighted-units` | number[]? | `[]` | The time units specified here will be visually highlighted in the chart with a mild opaque color.\n| `font` | string | `\"Helvetica\"`| Font family of the chart.\n| `label-column-title` | string? | `''` | If specified, a dedicated column for the row labels will be rendered on the left side of the graph. The specified title is displayed in the upper left corner, as the column's header.\n| `label-column-width` | string? | `150px` | Width of the column containing the row labels (if `label-column-title` specified)\n\n\n## Custom Events\n| Event name                 | Event data                                                 |\n|----------------------------|------------------------------------------------------------|\n| `click-bar`                |  `{bar: GanttBarObject, e: MouseEvent, datetime?: string}` |\n| `mousedown-bar`            |  `{bar: GanttBarObject, e: MouseEvent, datetime?: string}` |\n| `mouseup-bar`            |  `{bar: GanttBarObject, e: MouseEvent, datetime?: string}` |\n| `dblclick-bar`            |  `{bar: GanttBarObject, e: MouseEvent, datetime?: string}` |\n| `mouseenter-bar`            |  `{bar: GanttBarObject, e: MouseEvent}` |\n| `mouseleave-bar`            |  `{bar: GanttBarObject, e: MouseEvent}` |\n| `dragstart-bar`            |  `{bar: GanttBarObject, e: MouseEvent}` |\n| `drag-bar`            |  `{bar: GanttBarObject, e: MouseEvent}` |\n| `dragend-bar`            |  `{bar: GanttBarObject, e: MouseEvent, movedBars?: Map<GanttBarObject, {oldStart: string, oldEnd: string}>}` |\n| `contextmenu-bar`            |  `{bar: GanttBarObject, e: MouseEvent, datetime?: string}` |\n\n\n## Slots\n| Slot name                  | Slot data             | Description                             |\n|----------------------------|-----------------------| ----------------------------------------|\n| `upper-timeunit`           |  `{label: string, value: string}` | Content of an upper time-unit section in the time axis. |\n| `timeunit`           |  `{label: string, value: string}` | Content of a time-unit section in the time axis. |\n| `bar-tooltip`        |  `{bar: GanttBarObject}` | Slot for the tooltip which appears when hovering over a bar. |\n| `current-time-label`        |  | Slot for the text shown next to the current time marker when the prop `current-time` is set to `true`. |\n| `label-column-title`        |  | Slot for the title of the extra column to the left where the row labels are shown if the prop `label-column-title` is set. |\n| `label-column-row`       | `{ label: string } ` | Slot for the label of a row if `label-column-title` is set.  |\n\n## Color Schemes  \n\nList of pre-defined color schemes:\n- `default`\n- `creamy`\n- `crimson`\n- `dark`\n- `flare`\n- `fuchsia`\n- `grove`\n- `material-blue`\n- `sky`\n- `slumber`\n- `vue`\n\nYou can also provide your own color scheme. Your custom color scheme should be an object of the following shape:\n```typescript\n{\n  primary: string,\n  secondary: string,\n  ternary: string,\n  quartenary: string,\n  hoverHighlight: string,\n  markerCurrentTime: string,\n  text: string,\n  background: string,\n  toast?: string\n}\n```"
  },
  {
    "path": "docs/GGanttRow.md",
    "content": "# API: GGanttRow\nRepresents a single row of the chart. It is meant to be a child component of `g-gantt-chart`.  \n\n## Props\n| Prop        | Type    | Default | Description                  |\n|-------------|---------|---------|------------------------------|\n| `label`     |`string?`| `\"\"`    | Text that is floating in the upper left corner of the row.\n| `bars`      |`GanttBarObject[]`|  | Array of objects, each representing a bar in this row. Any JavaScript/TypeScript object with a nested `ganttBarConfig` object with a unique `id` string property is compatible. The objects must also contain two properties which represent the start and end datetime of the bar. The names of those properties must be passed  to the `bar-start` and `bar-end` props of the `g-gantt-chart` parent.\n| `highlight-on-hover` | `boolean?` | `false` | Used for toggling a background color transition effect on mouse hover.\n  \n## Custom Events\n| Event name                 | Event data                                                 |\n|----------------------------|------------------------------------------------------------|\n| `drop`                     | `{ e: MouseEvent, datetime: string}`                       |\n\n\n## Slots\n| Slot name                  | Slot data             | Description                             |\n|----------------------------|-----------------------| ----------------------------------------|\n| `label`           |   | Used for modifying the text that is floating in the upper left corner of the row. |\n| `bar-label`        |  `{bar: GanttBarObject}` | Used for modifying the text in a bar. |"
  },
  {
    "path": "docs/common-use-cases.md",
    "content": "# Common use cases\n The following section provides a non-exhausting list of common use cases and special features of Vue Ganttastic with corresponding code snippets.\n\n## Adding new bars\nFor each row of the chart, you will render a `g-gantt-row` component, which accepts a `bars` prop, which is an array of bar objects. Since the prop is reactive, all you need to do to add a new bar is to push a new bar-object into that array. Just make sure that the new bar-object has a nested `ganttBarConfig` object with a unique `id`, and don't forget to specify the property values for the start and end date of the bar (the properties' names must be the ones you passed to the `bar-start` and `bar-end` props of `g-gantt-chart`):\n```vue \n<template>\n  <g-gantt-chart\n    chart-start=\"2021-07-11 12:00\"\n    chart-end=\"2021-07-15 12:00\"\n    precision=\"hour\"\n    width=\"100%\"\n    bar-start=\"myBeginDate\"\n    bar-end=\"myEndDate\"\n  >\n    <g-gantt-row\n      label=\"My row 1\"\n      :bars=\"myBarList\"\n    />\n  </g-gantt-chart>\n</template>\n\n<script setup>\n\nimport { ref } from \"vue\"\n\nconst myBarList = ref([])\nconst addNewBar = () => {\n  const bar = {\n    myBeginDate: \"2021-07-11 17:00\",\n    myEndDate: \"2021-07-12 03:00\",\n    ganttBarConfig : {\n      id: \"some-id-blabla\" // make sure this is unique!\n    }\n  }\n  myBarList.push(bar)\n}\n</script>\n\n```\n## Configuring and styling bars\nYour bar objects can be of any type and contain any properties you want. The only requirements are:\n- a datetime-string property for the bar start date\n- a datetime-string property for the bar end date\n- a nested object `ganttBarConfig` with a unique string property `id`\n\nFor further configuration, you can add some optional properties to the nested `ganttBarConfig` object:\n\n| Property name | Type    | Description           |\n|---------------|---------|-----------------------|\n| `id`          | `string` | A unique string identifier for the bar.  (**mandatory**) \n| `label`       | `string?`  | Text displayed on the bar.\n| `html`        | `string?`  | Optional HTML Code that will be rendered after the label (e.g. for tags). Please sanitize user input to avoid cross site scripting, if applicable.\n| `hasHandles`  | `boolean?`  | Used to toggle handles on the left and right side of the bar that can be dragged to change the width of the bar. |\n| `immobile`    | `boolean?`  | Used to toggle whether bar can be moved (dragged).\n| `bundle`      | `string?`  | A string identifier for a bundle. A bundle is a collection of bars that are dragged simultaneously.\n| `style`       | `CSSStyleSheet?`  | CSS-based styling for your bar (e.g `background`, `fontSize`, `borderRadius` etc.).\n\n## Extending the width of a bar\nSimply add `hasHandles: true` to the `ganttBarConfig` to make the bar extendable by dragging the handles on its left or right side.  \n\n## Push bars when dragging\nBy default, bars can overlap with other bars while being dragged. If you would like to prevent this and have the bars \"push\" one another while dragging, use the `push-on-overlap` prop:\n```vue \n  <g-gantt-chart\n    ...\n    push-on-overlap\n    ...\n  >\n    ...\n  </g-gantt-chart>\n```\n\n## Bundling bars together\nIf you want to bind a group of bars one to another so that when you drag one bar, all the others move together with it, specify a `bundle` string in the `ganttBarConfig` of each affected bar.\n\n## Custom behavior on clicking/dragging a bar\nIt is completely up to you to specify which kind of behavior you would like e.g. when a bar is clicked on or when a bar-drag is ended. For this, you may use special events emitted by `g-gantt-chart`:\n```vue\n<g-gantt-chart\n  ...\n  @mousedown-bar=\"onMousedownBar($event.bar, $event.e, $event.datetime)\"\n  @dblclick-bar=\"onMouseupBar($event.bar, $event.e, $event.datetime)\"\n  @mouseenter-bar=\"onMouseenterBar($event.bar, $event.e)\"\n  @mouseleave-bar=\"onMouseleaveBar($event.bar, $event.e)\"\n  @dragstart-bar=\"onDragstartBar($event.bar, $event.e)\"\n  @drag-bar=\"onDragBar($event.bar, $event.e)\"\n  @dragend-bar=\"onDragendBar($event.bar, $event.e, $event.movedBars)\"\n  @contextmenu-bar=\"onContextmenuBar($event.bar, $event.e, $event.datetime)\"\n>\n  ...\n</g-gantt-chart>\n\n<script setup lang=\"ts\">\n...\nconst onMousedownBar = (bar: GanttBarObject, e: MouseEvent, datetime?: string) => {\n  // do something\n}\n...\n</script>\n```\n## Drag and drop  \nThe `g-gantt-row` component comes with a special `drop` event, that you can use to implement custom drag-and-drop behavior. The event data also includes the `datetime` position on which the drop occured.\n```vue\n<g-gantt-chart\n   ...\n>\n  <g-gantt-row\n    label=\"This is my row\"\n    :bars=\"bars1\"\n    @drop=\"onDrop($event.e, $event.datetime)\"\n  />\n</g-gantt-chart>\n\n<script setup lang=\"ts\">\n...\nconst onDrop = (e: MouseEvent, datetime?: string) => {\n  // do something\n}\n...\n</script>\n```\n\n## Time axis precision\nIf the time-range (`chart-start` to `chart-end`) of your chart is very large, the displayed time units in the time axis might be too dense if the chart is not wide enough. You might want to specify the precision of the time axis accordingly. Use the `precision` prop of `g-gantt-chart` for this. Possible values are `hour`, `day`, `week` and `month`.\n\n## Chart themes\nVue Ganttastic ships with several pre-made color schemes that you may specify using the `color-scheme` prop of `g-gantt-chart`. [List of available color-schemes](https://infectoone.github.io/vue-ganttastic/GGanttChart.html#color-schemes)\n\n## Locale\nSince Vue Ganttastic uses Day.js for all datetime manipulations, you can change the locale of Vue Ganttastic by [changing the global locale of Day.js](https://day.js.org/docs/en/i18n/changing-locale). You will usually do this in your `src/main.js` before you initialize the Ganttastic plugin.\n\n"
  },
  {
    "path": "docs/examples.md",
    "content": "\n# Live Demos\n\n## Simple hour chart  \n- `precision`: `hour`\n<g-gantt-chart chart-start=\"01.01.2022 12:00\" chart-end=\"02.01.2022 12:00\" precision=\"hour\" grid width=\"100%\" bar-start=\"beginDate\" bar-end=\"endDate\" date-format=\"DD.MM.YYYY HH:mm\">\n<g-gantt-row label=\"My row 1\" :bars=\"hourBarList1\" highlight-on-hover/>\n<g-gantt-row label=\"Another row\" :bars=\"hourBarList2\" highlight-on-hover/>\n</g-gantt-chart>\n\n<button @click=\"addHourBar()\" :disabled=\"hourBarList2.length > 0\"> Add bar </button>\n<button @click=\"deleteHourBar()\" style=\"margin-left: 10px\" :disabled=\"hourBarList2.length === 0\"> Delete bar </button>\n\n\n\n## Day chart with dark theme  \n- `precision`: `day`\n- `row-height` : `70`\n- `no-overlap`\n- `color-scheme` : `dark`\n\nUsed slots:\n`g-gantt-row` >  `label`, `bar-label`\n<g-gantt-chart chart-start=\"30.10.2022 12:00\" chart-end=\"02.11.2022 13:00\" precision=\"day\" grid width=\"100%\" :row-height=\"70\" bar-start=\"beginDate\" bar-end=\"endDate\" date-format=\"DD.MM.YYYY HH:mm\" color-scheme=\"dark\" no-overlap>\n<g-gantt-row label=\"Row label\" :bars=\"dayBarList1\" highlight-on-hover>\n<template #bar-label=\"{bar}\">\n<img v-if=\"bar.imgSrc\" :src=\"bar.imgSrc\" height=\"30\" width=\"30\"/>\n{{bar.ganttBarConfig.label}}\n</template>\n</g-gantt-row>\n<g-gantt-row label=\"My row 2\" :bars=\"[]\" highlight-on-hover>\n<template #label>\n<img src='https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png' height=\"30\" width=\"30\" style=\"padding-right:10px\"/>\nLabel with image\n</template>\n</g-gantt-row>\n</g-gantt-chart>\n\n\n\n## Month chart pushing and bundles\n- `precision`: `month`\n- `push-on-overlap`\n- `color-scheme` : `vue`\n- `font` : `Courier`\n<g-gantt-chart chart-start=\"01.01.2022 12:00\" chart-end=\"15.03.2022 03:00\" precision=\"month\" grid width=\"100%\" bar-start=\"beginDate\" bar-end=\"endDate\" date-format=\"DD.MM.YYYY HH:mm\" color-scheme=\"vue\" font=\"Courier\" push-on-overlap>\n<g-gantt-row label=\"My row 1\" :bars=\"monthBarList1\" highlight-on-hover/>\n<g-gantt-row label=\"My row 2\" :bars=\"monthBarList2\" highlight-on-hover/>\n<g-gantt-row label=\"Look at me!\" :bars=\"monthBarList3\" highlight-on-hover/>\n<g-gantt-row label=\"Fourth row\" :bars=\"[]\" highlight-on-hover/>\n</g-gantt-chart>\n\n\n\n<script setup>\nimport { ref } from \"vue\"\n\nconst hourBarList1 = ref([\n  {\n    beginDate: \"01.01.2022 15:00\",\n    endDate: \"01.01.2022 19:45\",\n    ganttBarConfig: {\n      id: \"8621987329\",\n      label: \"Drag me\",\n      style: {\n        color: \"white\"\n      }\n    }\n  },\n  {\n    beginDate: \"01.01.2022 23:00\",\n    endDate: \"02.01.2022 08:05\",\n    ganttBarConfig: {\n      id: \"8621987322\",\n      label: \"Drag my handles\",\n      hasHandles: true,\n      style: {\n        background: \"#d66f2a\",\n        color: \"white\"\n      }\n    }\n  }\n])\n\nconst hourBarList2 = ref([])\n\nconst dayBarList1 = ref([\n  {\n    beginDate: \"31.10.2022 15:00\",\n    endDate: \"01.11.2022 05:45\",\n    ganttBarConfig: {\n      id: \"a621987323\",\n      label: \"Drag me\",\n      style: {\n        background: \"#cc2a2d\",\n        color: \"white\"\n      }\n    }\n  },\n  {\n    beginDate: \"01.11.2022 09:00\",\n    endDate: \"02.11.2022 08:00\",\n    imgSrc: \"https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png\",\n    ganttBarConfig: {\n      id: \"x21987322\",\n      label: \"I have an image\",\n      hasHandles: true,\n      style: {\n        background: \"#e2e595\",\n        color: \"black\",\n        borderRadius: \"40px\"\n      }\n    }\n  }\n])\n\nconst monthBarList1 = ref([\n  {\n    beginDate: \"01.01.2022 23:00\",\n    endDate: \"02.02.2022 08:05\",\n    ganttBarConfig: {\n      id: \"5621987352\",\n      label: \"I'm in a bundle\",\n      hasHandles: true,\n      bundle: \"myBundle\",\n      style: {\n        background: \"#1c8745\",\n        color: \"white\",\n        borderRadius: \"20px\"\n      }\n    }\n  }\n])\n\nconst monthBarList2 = ref([\n  {\n    beginDate: \"01.01.2022 23:00\",\n    endDate: \"02.02.2022 08:05\",\n    ganttBarConfig: {\n      id: \"8621987321\",\n      label: \"I'm in a bundle\",\n      hasHandles: true,\n      bundle: \"myBundle\",\n      style: {\n        background: \"#a02353\",\n        color: \"white\",\n        borderRadius: \"20px\"\n      }\n    }\n  },\n  {\n    beginDate: \"15.02.2022 00:00\",\n    endDate: \"01.03.2022 00:05\",\n    ganttBarConfig: {\n      id: \"7721987321\",\n      label: \"Lorem ispum dolor\",\n      bundle: \"bundle2\",\n      style: {\n        backgroundImage: \"repeating-linear-gradient(45deg, #ccc, #ccc 30px, #8221b2 30px, #8221b2 60px)\",\n        borderRadius: \"20px\",\n        color: \"black\"\n      }\n    }\n  }\n])\nconst monthBarList3 = ref([{\n    beginDate: \"15.02.2022 00:00\",\n    endDate: \"01.03.2022 00:05\",\n    ganttBarConfig: {\n      id: \"7721987325\",\n      label: \"Lorem ispum dolor\",\n      bundle: \"bundle2\",\n      style: {\n        backgroundImage: \"repeating-linear-gradient(45deg, #ccc, #ccc 30px, #8221b2 30px, #8221b2 60px)\",\n        borderRadius: \"20px\",\n        color: \"black\"\n      }\n    }\n  }])\n\nconst addHourBar = () => {\n  if (hourBarList2.value.some(bar => bar.ganttBarConfig.id === \"test1\")) {\n    return\n  }\n  const bar = {\n    beginDate: \"01.01.2022 18:00\",\n    endDate: \"02.01.2022 02:00\",\n    ganttBarConfig: {\n      id: \"test1\",\n      hasHandles: true,\n      label: \"Hello!\",\n      style: {\n        background: \"#5484b7\",\n        borderRadius: \"20px\",\n        color: \"white\"\n      }\n    }\n  }\n  hourBarList2.value.push(bar)\n}\n\nconst deleteHourBar = () => {\n  const idx = hourBarList2.value.findIndex(b => b.ganttBarConfig.id === \"test1\")\n  if (idx !== -1) {\n    hourBarList2.value.splice(idx, 1)\n  }\n}\n</script>\n\n<style scoped>\n  button {\n    padding: 10px;\n    background: #258A5D;\n    color: white;\n    border: none;\n    border-radius: 5px;\n  }\n  button:disabled {\n    opacity: 0.5;\n  }\n</style>\n"
  },
  {
    "path": "docs/getting-started.md",
    "content": "# Getting started\n\n## Install\n\nYou can add Vue Ganttastic to your project using <kbd>npm</kbd>:\n\n```\nnpm install @infectoone/vue-ganttastic\n```\n\nThen, initalize the plugin in the starting point of your app (most likely `src/main.js`):\n\n```javascript\nimport { createApp } from \"vue\"\nimport App from \"./App.vue\"\n...\nimport ganttastic from '@infectoone/vue-ganttastic'\n...\ncreateApp(App)\n  .use(ganttastic)\n  .mount('#app')\n```\n\nThis will globally register the components `g-gantt-chart` and `g-gantt-row` and you will be able to use those two components right away.\n\n## Basic usage\n\n```vue\n<template>\n  <g-gantt-chart\n    chart-start=\"2021-07-12 12:00\"\n    chart-end=\"2021-07-14 12:00\"\n    precision=\"hour\"\n    bar-start=\"myBeginDate\"\n    bar-end=\"myEndDate\"\n  >\n    <g-gantt-row label=\"My row 1\" :bars=\"row1BarList\" />\n    <g-gantt-row label=\"My row 2\" :bars=\"row2BarList\" />\n  </g-gantt-chart>\n</template>\n\n<script setup>\nimport { ref } from \"vue\"\n\nconst row1BarList = ref([\n  {\n    myBeginDate: \"2021-07-13 13:00\",\n    myEndDate: \"2021-07-13 19:00\",\n    ganttBarConfig: {\n      // each bar must have a nested ganttBarConfig object ...\n      id: \"unique-id-1\", // ... and a unique \"id\" property\n      label: \"Lorem ipsum dolor\"\n    }\n  }\n])\nconst row2BarList = ref([\n  {\n    myBeginDate: \"2021-07-13 00:00\",\n    myEndDate: \"2021-07-14 02:00\",\n    ganttBarConfig: {\n      id: \"another-unique-id-2\",\n      hasHandles: true,\n      label: \"Hey, look at me\",\n      style: {\n        // arbitrary CSS styling for your bar\n        background: \"#e09b69\",\n        borderRadius: \"20px\",\n        color: \"black\"\n      }\n    }\n  }\n])\n</script>\n```\n\nThe result shoud look like this:  \n<g-gantt-chart chart-start=\"2021-07-12 12:00\" chart-end=\"2021-07-14 12:00\" precision=\"hour\" width=\"100%\" bar-start=\"myBeginDate\" bar-end=\"myEndDate\"> <g-gantt-row label=\"My row 1\" :bars=\"row1BarList\"/>\n<g-gantt-row label=\"My row 2\" :bars=\"row2BarList\"/>\n</g-gantt-chart>\n\n<script setup>\n\nimport { ref } from \"vue\"\n\nconst row1BarList = ref([\n  {\n    myBeginDate: \"2021-07-13 13:00\",\n    myEndDate: \"2021-07-13 19:00\",\n    ganttBarConfig: {    // each bar must have a nested ganttBarConfig object ...\n      id: \"unique-id-1\", // ... and a unique \"id\" property\n      label: \"Lorem ipsum dolor\"\n    }\n  }\n])\nconst row2BarList = ref([\n  {\n    myBeginDate: \"2021-07-13 00:00\",\n    myEndDate: \"2021-07-14 02:00\",\n    ganttBarConfig: {\n      id: \"another-unique-id-2\",\n      hasHandles: true,\n      label: \"Hey, look at me\",\n      style: {     \n        // arbitrary CSS styling for your bar\n        background: \"#e09b69\",\n        borderRadius: \"20px\",\n        color: \"#000000\"\n      },\n      class: \"foo\" // you can also add CSS classes to your bars!\n    }\n  }\n])\n</script>\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\n# https://vitepress.dev/reference/default-theme-home-page\nlayout: home\n\nhero:\n  name: Vue-Ganttastic\n  text: Gantt chart component for Vue\n  tagline: A simple, interactive and highly customizable Gantt chart component for Vue.js \n  image:\n    src: https://user-images.githubusercontent.com/28678851/148047714-301f07df-4101-48b8-9e47-1f272b290e80.png\n    alt: Vue-Ganttastic logo\n  actions:\n    - theme: brand\n      text: Get started\n      link: /introduction\n    - theme: alt\n      text: API Reference\n      link: /GGanttChart\n\nfeatures:\n  - title: Vue 3 and TypeScript support\n    details: Written in Vue 3 and TypeScript. Ships with out-of-the-box type declarations.\n  - title: Interactive\n    details: Dynamic Gantt chart with movable bars and numerous event handlers.\n  - title:  Customizable\n    details: Style the chart and each individual bar to your own liking!\n---\n\n"
  },
  {
    "path": "docs/introduction.md",
    "content": "# Introduction\nVue Ganttastic is a simple, interactive and highly customizable Gantt chart component for Vue 3.   \n\n## Features\n- **[Vue 3](https://v3.vuejs.org/) support**\n- **[TypeScript](https://www.typescriptlang.org/) support** *(ships with out of the box type declarations)*\n- **Interactivity** *(dynamic, movable and pushable bars)*\n- **Reactivity / Responsiveness** (*when changes occur, bars are repositioned accordingly*)\n- **Customization options** (*chart/bar styling, slots, event handlers etc.*)\n\n## About\n**License** [MIT](https://choosealicense.com/licenses/mit/)  \n**Author**: Marko Žunić, BSc  \n[GitHub Repository](https://github.com/InfectoOne/vue-ganttastic)\n\n## Support the project!\nIn case you found the library useful, a little tip would be much appreciated!\n\n<form action=\"https://www.paypal.com/donate\" method=\"post\" target=\"_top\">\n<input type=\"hidden\" name=\"hosted_button_id\" value=\"M63C8DAMV5YDJ\" />\n<input type=\"image\" src=\"https://pics.paypal.com/00/s/MTdhMWZmNTUtOWQ1Yi00YmRjLWJjMjgtY2Y0NTNhODM0OTJl/file.PNG\" border=\"0\" name=\"submit\" title=\"PayPal - The safer, easier way to pay online!\" alt=\"Donate with PayPal button\" style=\"max-width:200px\"/>\n<img alt=\"\" border=\"0\" src=\"https://www.paypal.com/en_AT/i/scr/pixel.gif\" width=\"1\" height=\"1\" />\n</form>\n\nBTC address:   \n![image](https://user-images.githubusercontent.com/28678851/233090745-a0a6d8a4-6df6-4b82-ac0c-90e69551786e.png)  \n\n\n"
  },
  {
    "path": "docs-deploy.yml",
    "content": "# Sample workflow for building and deploying a VitePress site to GitHub Pages\n#\nname: Deploy VitePress site to Pages\n\non:\n  # Runs on pushes targeting the `main` branch. Change this to `master` if you're\n  # using the `master` branch as the default branch.\n  push:\n    branches: [master]\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\n# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\nconcurrency:\n  group: pages\n  cancel-in-progress: false\n\njobs:\n  # Build job\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0 # Not needed if lastUpdated is not enabled\n      # - uses: pnpm/action-setup@v2 # Uncomment this if you're using pnpm\n      - name: Setup Node\n        uses: actions/setup-node@v3\n        with:\n          node-version: 18\n          cache: npm # or pnpm / yarn\n      - name: Setup Pages\n        uses: actions/configure-pages@v3\n      - name: Install dependencies\n        run: npm ci # or pnpm install / yarn install\n      - name: Build with VitePress\n        run: npm run docs:build # or pnpm docs:build / yarn docs:build\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v2\n        with:\n          path: docs/.vitepress/dist\n\n  # Deployment job\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    needs: build\n    runs-on: ubuntu-latest\n    name: Deploy\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v2"
  },
  {
    "path": "env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n\t<title>@infectoone/vue-ganttastic</title>\n\n\t<link rel=\"icon\" href=\"/favicon.ico\">\n\t<style>\n\t\tbody {\n\t\t\tfont-family: Helvetica, sans-serif;\n\t\t}\n\t</style>\n</head>\n<body>\n<noscript>\n\t<strong>We're sorry but the app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>\n</noscript>\n<div id=\"app\"></div>\n<script type=\"module\" src=\"/src/playground.ts\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@infectoone/vue-ganttastic\",\n  \"version\": \"2.3.2\",\n  \"description\": \"A simple and customizable Gantt chart component for Vue.js\",\n  \"author\": \"Marko Zunic (@zunnzunn)\",\n  \"scripts\": {\n    \"serve\": \"vite\",\n    \"build\": \"npm run build:types && npm run build:lib\",\n    \"build:lib\": \"vite build\",\n    \"build:types\": \"vue-tsc --declaration --emitDeclarationOnly --outDir lib_types\",\n    \"typecheck\": \"vue-tsc --noEmit\",\n    \"lint\": \"eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore\",\n    \"lint:fix\": \"npm run lint --fix\",\n    \"docs:build\": \"vitepress build docs\",\n    \"docs:dev\": \"vitepress dev docs\",\n    \"docs:preview\": \"vitepress preview docs\"\n  },\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./lib_types/vue-ganttastic.d.ts\",\n      \"import\": \"./lib/vue-ganttastic.js\",\n      \"require\": \"./lib/vue-ganttastic.umd.cjs\"\n    }\n  },\n  \"main\": \"./lib/vue-ganttastic.umd.cjs\",\n  \"types\": \"./lib_types/vue-ganttastic.d.ts\",\n  \"files\": [\n    \"lib_types\",\n    \"lib/vue-ganttastic.js\",\n    \"lib/vue-ganttastic.umd.cjs\"\n  ],\n  \"devDependencies\": {\n    \"@rushstack/eslint-patch\": \"^1.2.0\",\n    \"@senojs/rollup-plugin-style-inject\": \"^0.1.1\",\n    \"@types/node\": \"^16.11.58\",\n    \"@types/postcss-preset-env\": \"^7.7.0\",\n    \"@vitejs/plugin-vue\": \"^3.1.2\",\n    \"@vue/eslint-config-prettier\": \"^7.0.0\",\n    \"@vue/eslint-config-typescript\": \"^11.0.2\",\n    \"@vue/tsconfig\": \"^0.1.3\",\n    \"@vuepress/plugin-search\": \"2.0.0-beta.51\",\n    \"eslint\": \"^8.25.0\",\n    \"eslint-plugin-vue\": \"^9.6.0\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"postcss\": \"^8.4.17\",\n    \"postcss-preset-env\": \"^7.8.2\",\n    \"prettier\": \"^2.7.1\",\n    \"typescript\": \"~4.8.4\",\n    \"vite\": \"^3.1.6\",\n    \"vitepress\": \"^1.0.0-rc.4\",\n    \"vue-tsc\": \"^1.8.27\"\n  },\n  \"peerDependencies\": {\n    \"dayjs\": \"^1.11.5\",\n    \"vue\": \"^3.2.40\"\n  },\n  \"homepage\": \"https://zunnzunn.github.io/vue-ganttastic/\",\n  \"keywords\": [\n    \"gantt\",\n    \"chart\",\n    \"bar\",\n    \"diagram\",\n    \"vue\",\n    \"vuejs\",\n    \"ganttastic\"\n  ],\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/zunnzunn/vue-ganttastic\"\n  },\n  \"dependencies\": {\n    \"@vueuse/core\": \"^9.1.1\"\n  }\n}\n"
  },
  {
    "path": "src/GanttPlayground.vue",
    "content": "<template>\n  <g-gantt-chart\n    :chart-start=\"chartStart\"\n    :chart-end=\"chartEnd\"\n    precision=\"week\"\n    :row-height=\"40\"\n    grid\n    current-time\n    width=\"100%\"\n    bar-start=\"beginDate\"\n    bar-end=\"endDate\"\n    :date-format=\"format\"\n    @click-bar=\"onClickBar($event.bar, $event.e, $event.datetime)\"\n    @mousedown-bar=\"onMousedownBar($event.bar, $event.e, $event.datetime)\"\n    @dblclick-bar=\"onMouseupBar($event.bar, $event.e, $event.datetime)\"\n    @mouseenter-bar=\"onMouseenterBar($event.bar, $event.e)\"\n    @mouseleave-bar=\"onMouseleaveBar($event.bar, $event.e)\"\n    @dragstart-bar=\"onDragstartBar($event.bar, $event.e)\"\n    @drag-bar=\"onDragBar($event.bar, $event.e)\"\n    @dragend-bar=\"onDragendBar($event.bar, $event.e, $event.movedBars)\"\n    @contextmenu-bar=\"onContextmenuBar($event.bar, $event.e, $event.datetime)\"\n  >\n    <g-gantt-row label=\"My row to test\" :bars=\"bars1\" highlight-on-hover />\n    <g-gantt-row label=\"My another new row to test\" highlight-on-hover :bars=\"bars2\" />\n    <g-gantt-row label=\"just another row to test gantt\" highlight-on-hover :bars=\"bars3\" />\n    <g-gantt-row\n      label=\"errors teach us, and debugging makes us stronger!\"\n      highlight-on-hover\n      :bars=\"bars4\"\n    />\n  </g-gantt-chart>\n\n  <button type=\"button\" @click=\"addBar()\">Add bar</button>\n  <button type=\"button\" @click=\"deleteBar()\">Delete bar</button>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport type { GanttBarObject } from \"./types\"\nimport dayjs from \"dayjs\"\n\nconst format = ref(\"DD.MM.YYYY HH:mm\")\nconst chartStart = ref(dayjs().startOf(\"day\").format(format.value))\nconst chartEnd = ref(\n  dayjs(chartStart.value, format.value).add(3, \"days\").hour(12).format(format.value)\n)\n\nconst bars1 = ref<GanttBarObject[]>([\n  {\n    beginDate: dayjs().hour(13).startOf(\"hour\").format(format.value),\n    endDate: dayjs().hour(19).startOf(\"hour\").format(format.value),\n    ganttBarConfig: {\n      id: \"8621987329\",\n      label: \"I'm in a bundle\",\n      bundle: \"bundle2\"\n    }\n  }\n])\n\nconst bars2 = ref([\n  {\n    beginDate: dayjs().hour(13).startOf(\"hour\").format(format.value),\n    endDate: dayjs().hour(19).startOf(\"hour\").format(format.value),\n    ganttBarConfig: {\n      id: \"1592311887\",\n      label: \"I'm in a bundle\",\n      bundle: \"bundle2\",\n      style: {\n        background: \"magenta\"\n      }\n    }\n  },\n  {\n    beginDate: dayjs().add(2, \"day\").hour(0).startOf(\"hour\").format(format.value),\n    endDate: dayjs().add(2, \"day\").hour(19).startOf(\"hour\").format(format.value),\n    ganttBarConfig: {\n      id: \"7716981641\",\n      label: \"Lorem ipsum dolor\",\n      hasHandles: true,\n      style: {\n        background: \"#b74b52\"\n      }\n    }\n  },\n  {\n    beginDate: dayjs().add(1, \"day\").hour(4).startOf(\"hour\").format(format.value),\n    endDate: dayjs().add(1, \"day\").hour(16).startOf(\"hour\").format(format.value),\n    ganttBarConfig: {\n      id: \"9716981641\",\n      label: \"Oh hey\",\n      style: {\n        background: \"#69e064\",\n        borderRadius: \"15px\",\n        color: \"blue\",\n        fontSize: \"10px\"\n      }\n    }\n  }\n])\n\nconst bars3 = [\n  {\n    beginDate: \"15.01.2024 08:30\",\n    endDate: \"20.02.2024 16:45\",\n    ganttBarConfig: {\n      id: \"9876543210\",\n      label: \"Updated Bundle\",\n      bundle: \"bundle3\",\n      style: {\n        background: \"cyan\"\n      }\n    }\n  },\n  {\n    beginDate: \"20.02.2024 12:00\",\n    endDate: \"10.03.2024 18:30\",\n    ganttBarConfig: {\n      id: \"1234567890\",\n      label: \"New Task\",\n      hasHandles: true,\n      style: {\n        background: \"#f79466\"\n      }\n    }\n  },\n  {\n    beginDate: \"25.04.2024 09:15\",\n    endDate: \"30.04.2024 21:00\",\n    ganttBarConfig: {\n      id: \"2468135790\",\n      label: \"Greetings\",\n      style: {\n        background: \"#aabbcc\",\n        borderRadius: \"8px\",\n        color: \"white\",\n        fontSize: \"12px\"\n      }\n    }\n  }\n]\n\nconst bars4 = [\n  {\n    beginDate: \"10.01.2024 08:00\",\n    endDate: \"15.03.2024 16:30\",\n    ganttBarConfig: {\n      id: \"9876543210\",\n      label: \"Novo Pacote\",\n      bundle: \"pacote3\",\n      style: {\n        background: \"pink\"\n      }\n    }\n  },\n  {\n    beginDate: \"05.03.2024 10:00\",\n    endDate: \"15.04.2024 22:15\",\n    ganttBarConfig: {\n      id: \"2468135790\",\n      label: \"hello folks\",\n      style: {\n        background: \"#ffd700\",\n        borderRadius: \"10px\",\n        color: \"black\",\n        fontSize: \"14px\"\n      }\n    }\n  }\n]\n\nconst addBar = () => {\n  if (bars1.value.some((bar) => bar.ganttBarConfig.id === \"test1\")) {\n    return\n  }\n  const bar = {\n    beginDate: dayjs().add(1, \"day\").hour(4).startOf(\"hour\").format(format.value),\n    endDate: dayjs().add(2, \"day\").hour(4).startOf(\"hour\").format(format.value),\n    ganttBarConfig: {\n      id: \"test1\",\n      hasHandles: true,\n      label: \"Hello!\",\n      style: {\n        background: \"#5484b7\",\n        borderRadius: \"20px\"\n      }\n    }\n  }\n  bars1.value.push(bar)\n}\n\nconst deleteBar = () => {\n  const idx = bars1.value.findIndex((b) => b.ganttBarConfig.id === \"test1\")\n  if (idx !== -1) {\n    bars1.value.splice(idx, 1)\n  }\n}\n\nconst onClickBar = (bar: GanttBarObject, e: MouseEvent, datetime?: string) => {\n  console.log(\"click-bar\", bar, e, datetime)\n}\n\nconst onMousedownBar = (bar: GanttBarObject, e: MouseEvent, datetime?: string) => {\n  console.log(\"mousedown-bar\", bar, e, datetime)\n}\n\nconst onMouseupBar = (bar: GanttBarObject, e: MouseEvent, datetime?: string) => {\n  console.log(\"mouseup-bar\", bar, e, datetime)\n}\n\nconst onMouseenterBar = (bar: GanttBarObject, e: MouseEvent) => {\n  console.log(\"mouseenter-bar\", bar, e)\n}\n\nconst onMouseleaveBar = (bar: GanttBarObject, e: MouseEvent) => {\n  console.log(\"mouseleave-bar\", bar, e)\n}\n\nconst onDragstartBar = (bar: GanttBarObject, e: MouseEvent) => {\n  console.log(\"dragstart-bar\", bar, e)\n}\n\nconst onDragBar = (bar: GanttBarObject, e: MouseEvent) => {\n  console.log(\"drag-bar\", bar, e)\n}\n\nconst onDragendBar = (\n  bar: GanttBarObject,\n  e: MouseEvent,\n  movedBars?: Map<GanttBarObject, { oldStart: string; oldEnd: string }>\n) => {\n  console.log(\"dragend-bar\", bar, e, movedBars)\n}\n\nconst onContextmenuBar = (bar: GanttBarObject, e: MouseEvent, datetime?: string) => {\n  console.log(\"contextmenu-bar\", bar, e, datetime)\n}\n</script>\n"
  },
  {
    "path": "src/color-schemes.ts",
    "content": "import type * as CSS from \"csstype\"\n\ntype Color = CSS.DataType.Color\n\nexport type ColorScheme = {\n  primary: Color\n  secondary: Color\n  ternary: Color\n  quartenary: Color\n  hoverHighlight: Color\n  markerCurrentTime: Color\n  text: Color\n  background: Color\n  toast?: Color\n}\n\nexport const colorSchemes: Record<string, ColorScheme> = {\n  default: {\n    primary: \"#eeeeee\",\n    secondary: \"#E0E0E0\",\n    ternary: \"#F5F5F5\",\n    quartenary: \"#ededed\",\n    hoverHighlight: \"rgba(204, 216, 219, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"#404040\",\n    background: \"white\"\n  },\n\n  creamy: {\n    primary: \"#ffe8d9\",\n    secondary: \"#fcdcc5\",\n    ternary: \"#fff6f0\",\n    quartenary: \"#f7ece6\",\n    hoverHighlight: \"rgba(230, 221, 202, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"#542d05\",\n    background: \"white\"\n  },\n\n  crimson: {\n    primary: \"#a82039\",\n    secondary: \"#c41238\",\n    ternary: \"#db4f56\",\n    quartenary: \"#ce5f64\",\n    hoverHighlight: \"rgba(196, 141, 141, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  },\n\n  dark: {\n    primary: \"#404040\",\n    secondary: \"#303030\",\n    ternary: \"#353535\",\n    quartenary: \"#383838\",\n    hoverHighlight: \"rgba(159, 160, 161, 0.5)\",\n    markerCurrentTime: \"#fff\",\n    text: \"white\",\n    background: \"#525252\",\n    toast: \"#1f1f1f\"\n  },\n\n  flare: {\n    primary: \"#e08a38\",\n    secondary: \"#e67912\",\n    ternary: \"#5e5145\",\n    quartenary: \"#665648\",\n    hoverHighlight: \"rgba(196, 141, 141, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  },\n\n  fuchsia: {\n    primary: \"#de1d5a\",\n    secondary: \"#b50b41\",\n    ternary: \"#ff7da6\",\n    quartenary: \"#f2799f\",\n    hoverHighlight: \"rgba(196, 141, 141, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  },\n\n  grove: {\n    primary: \"#3d9960\",\n    secondary: \"#288542\",\n    ternary: \"#72b585\",\n    quartenary: \"#65a577\",\n    hoverHighlight: \"rgba(160, 219, 171, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  },\n\n  \"material-blue\": {\n    primary: \"#0D47A1\",\n    secondary: \"#1565C0\",\n    ternary: \"#42a5f5\",\n    quartenary: \"#409fed\",\n    hoverHighlight: \"rgba(110, 165, 196, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  },\n\n  sky: {\n    primary: \"#b5e3ff\",\n    secondary: \"#a1d6f7\",\n    ternary: \"#d6f7ff\",\n    quartenary: \"#d0edf4\",\n    hoverHighlight: \"rgba(193, 202, 214, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"#022c47\",\n    background: \"white\"\n  },\n\n  slumber: {\n    primary: \"#2a2f42\",\n    secondary: \"#2f3447\",\n    ternary: \"#35394d\",\n    quartenary: \"#2c3044\",\n    hoverHighlight: \"rgba(179, 162, 127, 0.5)\",\n    markerCurrentTime: \"#fff\",\n    text: \"#ffe0b3\",\n    background: \"#38383b\",\n    toast: \"#1f1f1f\"\n  },\n\n  vue: {\n    primary: \"#258a5d\",\n    secondary: \"#41B883\",\n    ternary: \"#35495E\",\n    quartenary: \"#2a3d51\",\n    hoverHighlight: \"rgba(160, 219, 171, 0.5)\",\n    markerCurrentTime: \"#000\",\n    text: \"white\",\n    background: \"white\"\n  }\n}\n\nexport type ColorSchemeKey = keyof typeof colorSchemes\n\nexport default colorSchemes\n"
  },
  {
    "path": "src/components/GGanttBar.vue",
    "content": "<template>\n  <div\n    :id=\"barConfig.id\"\n    :class=\"['g-gantt-bar', barConfig.class || '']\"\n    :style=\"{\n      ...barConfig.style,\n      position: 'absolute',\n      top: `${rowHeight * 0.1}px`,\n      left: `${xStart}px`,\n      width: `${xEnd - xStart}px`,\n      height: `${rowHeight * 0.8}px`,\n      zIndex: isDragging ? 3 : 2\n    }\"\n    @mousedown=\"onMouseEvent\"\n    @click=\"onMouseEvent\"\n    @dblclick=\"onMouseEvent\"\n    @mouseenter=\"onMouseEvent\"\n    @mouseleave=\"onMouseEvent\"\n    @contextmenu=\"onMouseEvent\"\n  >\n    <div class=\"g-gantt-bar-label\">\n      <slot :bar=\"bar\">\n        <div>\n          {{ barConfig.label || \"\" }}\n        </div>\n        <div v-if=\"barConfig.html\" v-html=\"barConfig.html\"/>\n      </slot>\n    </div>\n    <template v-if=\"barConfig.hasHandles\">\n      <div class=\"g-gantt-bar-handle-left\" />\n      <div class=\"g-gantt-bar-handle-right\" />\n    </template>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, toRefs, watch, onMounted, inject } from \"vue\"\n\nimport useBarDragManagement from \"../composables/useBarDragManagement.js\"\nimport useTimePositionMapping from \"../composables/useTimePositionMapping.js\"\nimport useBarDragLimit from \"../composables/useBarDragLimit.js\"\nimport type { GanttBarObject } from \"../types\"\nimport provideEmitBarEvent from \"../provider/provideEmitBarEvent.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\nimport { BAR_CONTAINER_KEY } from \"../provider/symbols\"\n\nconst props = defineProps<{\n  bar: GanttBarObject\n}>()\nconst emitBarEvent = provideEmitBarEvent()\nconst config = provideConfig()\nconst { rowHeight } = config\n\nconst { bar } = toRefs(props)\nconst { mapTimeToPosition, mapPositionToTime } = useTimePositionMapping()\nconst { initDragOfBar, initDragOfBundle } = useBarDragManagement()\nconst { setDragLimitsOfGanttBar } = useBarDragLimit()\n\nconst isDragging = ref(false)\n\nconst barConfig = computed(() => bar.value.ganttBarConfig)\n\nfunction firstMousemoveCallback(e: MouseEvent) {\n  barConfig.value.bundle != null ? initDragOfBundle(bar.value, e) : initDragOfBar(bar.value, e)\n  isDragging.value = true\n}\n\nconst prepareForDrag = () => {\n  setDragLimitsOfGanttBar(bar.value)\n  if (barConfig.value.immobile) {\n    return\n  }\n\n  window.addEventListener(\"mousemove\", firstMousemoveCallback, {\n    once: true\n  }) // on first mousemove event\n  window.addEventListener(\n    \"mouseup\",\n    () => {\n      // in case user does not move the mouse after mousedown at all\n      window.removeEventListener(\"mousemove\", firstMousemoveCallback)\n      isDragging.value = false\n    },\n    { once: true }\n  )\n}\n\nconst barContainerEl = inject(BAR_CONTAINER_KEY)\n\nconst onMouseEvent = (e: MouseEvent) => {\n  e.preventDefault()\n  if (e.type === \"mousedown\") {\n    prepareForDrag()\n  }\n  const barContainer = barContainerEl?.value?.getBoundingClientRect()\n  if (!barContainer) {\n    return\n  }\n  const datetime = mapPositionToTime(e.clientX - barContainer.left)\n  emitBarEvent(e, bar.value, datetime)\n}\n\nconst { barStart, barEnd, width, chartStart, chartEnd, chartSize } = config\n\nconst xStart = ref(0)\nconst xEnd = ref(0)\n\nonMounted(() => {\n  watch(\n    [bar, width, chartStart, chartEnd, chartSize.width],\n    () => {\n      xStart.value = mapTimeToPosition(bar.value[barStart.value])\n      xEnd.value = mapTimeToPosition(bar.value[barEnd.value])\n    },\n    { deep: true, immediate: true }\n  )\n})\n</script>\n\n<style>\n.g-gantt-bar {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  background: cadetblue;\n  overflow: hidden;\n}\n\n.g-gantt-bar-label {\n  width: 100%;\n  height: 100%;\n  box-sizing: border-box;\n  padding: 0 14px 0 14px; /* 14px is the width of the handle */\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n.g-gantt-bar-label > * {\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.g-gantt-bar-handle-left,\n.g-gantt-bar-handle-right {\n  position: absolute;\n  width: 10px;\n  height: 100%;\n  background: white;\n  opacity: 0.7;\n  border-radius: 0px;\n  cursor: ew-resize;\n  top: 0;\n}\n.g-gantt-bar-handle-left {\n  left: 0;\n}\n.g-gantt-bar-handle-right {\n  right: 0;\n}\n\n.g-gantt-bar-label img {\n  pointer-events: none;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttBarTooltip.vue",
    "content": "<template>\n  <teleport to=\"body\">\n    <transition name=\"g-fade\" mode=\"out-in\">\n      <div\n        v-if=\"modelValue\"\n        class=\"g-gantt-tooltip\"\n        :style=\"{\n          top: tooltipTop,\n          left: tooltipLeft,\n          fontFamily: font\n        }\"\n      >\n        <div class=\"g-gantt-tooltip-color-dot\" :style=\"{ background: dotColor }\" />\n        <slot :bar=\"bar\" :bar-start=\"barStartRaw\" :bar-end=\"barEndRaw\">\n          {{ tooltipContent }}\n        </slot>\n      </div>\n    </transition>\n  </teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, toRefs, ref, watch, nextTick } from \"vue\"\n\nimport type { GanttBarObject } from \"../types\"\nimport useDayjsHelper from \"../composables/useDayjsHelper.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nconst TOOLTIP_FORMATS = {\n  hour: \"HH:mm\",\n  day: \"DD. MMM HH:mm\",\n  date: \"DD. MMMM YYYY\",\n  month: \"DD. MMMM YYYY\",\n  week: \"DD. MMMM YYYY (WW)\"\n} as const\n\nconst DEFAULT_DOT_COLOR = \"cadetblue\"\n\nconst props = defineProps<{\n  bar: GanttBarObject | undefined\n  modelValue: boolean\n}>()\n\nconst { bar } = toRefs(props)\nconst { precision, font, barStart, barEnd, rowHeight } = provideConfig()\n\nconst tooltipTop = ref(\"0px\")\nconst tooltipLeft = ref(\"0px\")\nwatch(\n  () => props.bar,\n  async () => {\n    await nextTick()\n\n    const barId = bar?.value?.ganttBarConfig.id || \"\"\n    if (!barId) {\n      return\n    }\n\n    const barElement = document.getElementById(barId)\n    const { top, left } = barElement?.getBoundingClientRect() || {\n      top: 0,\n      left: 0\n    }\n    const leftValue = Math.max(left, 10)\n    tooltipTop.value = `${top + rowHeight.value - 10}px`\n    tooltipLeft.value = `${leftValue}px`\n  },\n  { deep: true, immediate: true }\n)\n\nconst dotColor = computed(() => bar?.value?.ganttBarConfig.style?.background || DEFAULT_DOT_COLOR)\n\nconst { toDayjs } = useDayjsHelper()\n\nconst barStartRaw = computed(() => bar.value?.[barStart.value])\nconst barEndRaw = computed(() => bar.value?.[barEnd.value])\n\nconst tooltipContent = computed(() => {\n  if (!bar?.value) {\n    return \"\"\n  }\n  const format = TOOLTIP_FORMATS[precision.value]\n  const barStartFormatted = toDayjs(barStartRaw.value).format(format)\n  const barEndFormatted = toDayjs(barEndRaw.value).format(format)\n  return `${barStartFormatted} \\u2013 ${barEndFormatted}`\n})\n</script>\n\n<style>\n.g-gantt-tooltip {\n  position: fixed;\n  background: black;\n  color: white;\n  z-index: 4;\n  font-size: 0.85em;\n  padding: 5px;\n  border-radius: 3px;\n  transition: opacity 0.2s;\n  display: flex;\n  align-items: center;\n  font-variant-numeric: tabular-nums;\n}\n\n.g-gantt-tooltip:before {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: 10%;\n  width: 0;\n  height: 0;\n  border: 10px solid transparent;\n  border-bottom-color: black;\n  border-top: 0;\n  margin-left: -5px;\n  margin-top: -5px;\n}\n\n.g-gantt-tooltip-color-dot {\n  width: 8px;\n  height: 8px;\n  border-radius: 100%;\n  margin-right: 4px;\n}\n\n.g-fade-enter-active,\n.g-fade-leave-active {\n  transition: opacity 0.3s ease;\n}\n\n.g-fade-enter-from,\n.g-fade-leave-to {\n  opacity: 0;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttChart.vue",
    "content": "<template>\n  <div>\n    <div :class=\"[{ 'labels-in-column': !!labelColumnTitle }]\">\n      <g-gantt-label-column\n        v-if=\"labelColumnTitle\"\n        :style=\"{\n          width: labelColumnWidth\n        }\"\n      >\n        <template #label-column-title>\n          <slot name=\"label-column-title\" />\n        </template>\n        <template #label-column-row=\"{ label }\">\n          <slot name=\"label-column-row\" :label=\"label\" />\n        </template>\n      </g-gantt-label-column>\n      <div\n        ref=\"ganttChart\"\n        :class=\"['g-gantt-chart', { 'with-column': labelColumnTitle }]\"\n        :style=\"{ width, background: colors.background, fontFamily: font }\"\n      >\n        <g-gantt-timeaxis v-if=\"!hideTimeaxis\">\n          <template #upper-timeunit=\"{ label, value, date }\">\n            <!-- expose upper-timeunit slot of g-gantt-timeaxis-->\n            <slot name=\"upper-timeunit\" :label=\"label\" :value=\"value\" :date=\"date\" />\n          </template>\n          <template #timeunit=\"{ label, value, date }\">\n            <!-- expose timeunit slot of g-gantt-timeaxis-->\n            <slot name=\"timeunit\" :label=\"label\" :value=\"value\" :date=\"date\" />\n          </template>\n        </g-gantt-timeaxis>\n        <g-gantt-grid v-if=\"grid\" :highlighted-units=\"highlightedUnits\" />\n        <g-gantt-current-time v-if=\"currentTime\">\n          <template #current-time-label>\n            <slot name=\"current-time-label\" />\n          </template>\n        </g-gantt-current-time>\n        <div class=\"g-gantt-rows-container\">\n          <slot />\n          <!-- the g-gantt-row components go here -->\n        </div>\n      </div>\n    </div>\n    <g-gantt-bar-tooltip :model-value=\"showTooltip || isDragging\" :bar=\"tooltipBar\">\n      <template #default>\n        <slot name=\"bar-tooltip\" :bar=\"tooltipBar\" />\n      </template>\n    </g-gantt-bar-tooltip>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n  computed,\n  provide,\n  ref,\n  toRefs,\n  useSlots,\n  type ComputedRef,\n  type Ref,\n  type ToRefs\n} from \"vue\"\n\nimport GGanttGrid from \"./GGanttGrid.vue\"\nimport GGanttLabelColumn from \"./GGanttLabelColumn.vue\"\nimport GGanttTimeaxis from \"./GGanttTimeaxis.vue\"\nimport GGanttBarTooltip from \"./GGanttBarTooltip.vue\"\nimport GGanttCurrentTime from \"./GGanttCurrentTime.vue\"\n\nimport type { GanttBarObject } from \"../types\"\nimport type { ColorSchemeKey } from \"../color-schemes.js\"\n\nimport { useElementSize } from \"@vueuse/core\"\nimport { DEFAULT_DATE_FORMAT } from \"../composables/useDayjsHelper\"\nimport { colorSchemes, type ColorScheme } from \"../color-schemes.js\"\nimport {\n  CHART_ROWS_KEY,\n  CONFIG_KEY,\n  EMIT_BAR_EVENT_KEY,\n  type ChartRow\n} from \"../provider/symbols.js\"\n\nexport interface GGanttChartProps {\n  chartStart: string | Date\n  chartEnd: string | Date\n  precision?: \"hour\" | \"day\" | \"date\" | \"week\" | \"month\"\n  barStart: string\n  barEnd: string\n  currentTime?: boolean\n  currentTimeLabel?: string\n  dateFormat?: string | false\n  width?: string\n  hideTimeaxis?: boolean\n  colorScheme?: ColorSchemeKey | ColorScheme\n  grid?: boolean\n  pushOnOverlap?: boolean\n  noOverlap?: boolean\n  rowHeight?: number\n  highlightedUnits?: number[]\n  font?: string\n  labelColumnTitle?: string\n  labelColumnWidth?: string\n}\n\nexport type GGanttChartConfig = ToRefs<Required<GGanttChartProps>> & {\n  colors: ComputedRef<ColorScheme>\n  chartSize: {\n    width: Ref<number>\n    height: Ref<number>\n  }\n}\n\nconst props = withDefaults(defineProps<GGanttChartProps>(), {\n  currentTimeLabel: \"\",\n  dateFormat: DEFAULT_DATE_FORMAT,\n  precision: \"day\",\n  width: \"100%\",\n  hideTimeaxis: false,\n  colorScheme: \"default\",\n  grid: false,\n  pushOnOverlap: false,\n  noOverlap: false,\n  rowHeight: 40,\n  highlightedUnits: () => [],\n  font: \"inherit\",\n  labelColumnTitle: \"\",\n  labelColumnWidth: \"150px\"\n})\n\nconst emit = defineEmits<{\n  (e: \"click-bar\", value: { bar: GanttBarObject; e: MouseEvent; datetime?: string | Date }): void\n  (\n    e: \"mousedown-bar\",\n    value: { bar: GanttBarObject; e: MouseEvent; datetime?: string | Date }\n  ): void\n  (e: \"mouseup-bar\", value: { bar: GanttBarObject; e: MouseEvent; datetime?: string | Date }): void\n  (e: \"dblclick-bar\", value: { bar: GanttBarObject; e: MouseEvent; datetime?: string | Date }): void\n  (e: \"mouseenter-bar\", value: { bar: GanttBarObject; e: MouseEvent }): void\n  (e: \"mouseleave-bar\", value: { bar: GanttBarObject; e: MouseEvent }): void\n  (e: \"dragstart-bar\", value: { bar: GanttBarObject; e: MouseEvent }): void\n  (e: \"drag-bar\", value: { bar: GanttBarObject; e: MouseEvent }): void\n  (\n    e: \"dragend-bar\",\n    value: {\n      bar: GanttBarObject\n      e: MouseEvent\n      movedBars?: Map<GanttBarObject, { oldStart: string; oldEnd: string }>\n    }\n  ): void\n  (\n    e: \"contextmenu-bar\",\n    value: { bar: GanttBarObject; e: MouseEvent; datetime?: string | Date }\n  ): void\n}>()\n\nconst { width, font, colorScheme } = toRefs(props)\n\nconst slots = useSlots()\nconst colors = computed(() =>\n  typeof colorScheme.value !== \"string\"\n    ? colorScheme.value\n    : colorSchemes[colorScheme.value as ColorSchemeKey] || colorSchemes.default\n)\nconst getChartRows = () => {\n  const defaultSlot = slots.default?.()\n  const allBars: ChartRow[] = []\n\n  if (!defaultSlot) {\n    return allBars\n  }\n  defaultSlot.forEach((child) => {\n    if (child.props?.bars) {\n      const { label, bars } = child.props\n      allBars.push({ label, bars })\n      // if using v-for to generate rows, rows will be children of a single \"fragment\" v-node:\n    } else if (Array.isArray(child.children)) {\n      child.children.forEach((grandchild) => {\n        const granchildNode = grandchild as {\n          props?: ChartRow\n        }\n        if (granchildNode?.props?.bars) {\n          const { label, bars } = granchildNode.props\n          allBars.push({ label, bars })\n        }\n      })\n    }\n  })\n  return allBars\n}\n\nconst showTooltip = ref(false)\nconst isDragging = ref(false)\nconst tooltipBar = ref<GanttBarObject | undefined>(undefined)\nlet tooltipTimeoutId: ReturnType<typeof setTimeout>\nconst initTooltip = (bar: GanttBarObject) => {\n  if (tooltipTimeoutId) {\n    clearTimeout(tooltipTimeoutId)\n  }\n  tooltipTimeoutId = setTimeout(() => {\n    showTooltip.value = true\n  }, 800)\n  tooltipBar.value = bar\n}\n\nconst clearTooltip = () => {\n  clearTimeout(tooltipTimeoutId)\n  showTooltip.value = false\n}\n\nconst emitBarEvent = (\n  e: MouseEvent,\n  bar: GanttBarObject,\n  datetime?: string | Date,\n  movedBars?: Map<GanttBarObject, { oldStart: string; oldEnd: string }>\n) => {\n  switch (e.type) {\n    case \"click\":\n      emit(\"click-bar\", { bar, e, datetime })\n      break\n    case \"mousedown\":\n      emit(\"mousedown-bar\", { bar, e, datetime })\n      break\n    case \"mouseup\":\n      emit(\"mouseup-bar\", { bar, e, datetime })\n      break\n    case \"dblclick\":\n      emit(\"dblclick-bar\", { bar, e, datetime })\n      break\n    case \"mouseenter\":\n      initTooltip(bar)\n      emit(\"mouseenter-bar\", { bar, e })\n      break\n    case \"mouseleave\":\n      clearTooltip()\n      emit(\"mouseleave-bar\", { bar, e })\n      break\n    case \"dragstart\":\n      isDragging.value = true\n      emit(\"dragstart-bar\", { bar, e })\n      break\n    case \"drag\":\n      emit(\"drag-bar\", { bar, e })\n      break\n    case \"dragend\":\n      isDragging.value = false\n      emit(\"dragend-bar\", { bar, e, movedBars })\n      break\n    case \"contextmenu\":\n      emit(\"contextmenu-bar\", { bar, e, datetime })\n      break\n  }\n}\n\nconst ganttChart = ref<HTMLElement | null>(null)\nconst chartSize = useElementSize(ganttChart)\n\nprovide(CHART_ROWS_KEY, getChartRows)\nprovide(CONFIG_KEY, {\n  ...toRefs(props),\n  colors,\n  chartSize\n})\nprovide(EMIT_BAR_EVENT_KEY, emitBarEvent)\n</script>\n\n<style>\n.g-gantt-chart {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  overflow-x: hidden;\n  -webkit-touch-callout: none;\n  user-select: none;\n  font-variant-numeric: tabular-nums;\n  border-radius: 5px;\n}\n\n.with-column {\n  border-top-left-radius: 0px;\n  border-bottom-left-radius: 0px;\n  border-top-right-radius: 5px;\n  border-bottom-right-radius: 5px;\n}\n\n.g-gantt-rows-container {\n  position: relative;\n}\n\n.labels-in-column {\n  display: flex;\n  flex-direction: row;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttCurrentTime.vue",
    "content": "<template>\n  <div\n    class=\"g-grid-current-time\"\n    :style=\"{\n      left: `${xDist}px`\n    }\"\n  >\n    <div\n      class=\"g-grid-current-time-marker\"\n      :style=\"{\n        border: `1px dashed ${colors.markerCurrentTime}`\n      }\"\n    />\n    <span class=\"g-grid-current-time-text\" :style=\"{ color: colors.markerCurrentTime }\">\n      <slot name=\"current-time-label\">\n        {{ currentTimeLabel }}\n      </slot>\n    </span>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed } from \"vue\"\nimport useTimePositionMapping from \"../composables/useTimePositionMapping.js\"\nimport dayjs from \"dayjs\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nconst { mapTimeToPosition } = useTimePositionMapping()\nconst currentMoment = ref(dayjs())\nconst { colors, dateFormat, currentTimeLabel } = provideConfig()\nconst xDist = computed(() => {\n  const format = dateFormat.value || \"YYYY-MM-DD HH:mm\"\n  return mapTimeToPosition(dayjs(currentMoment.value, format).format(format))\n})\n</script>\n\n<style>\n.g-grid-current-time {\n  position: absolute;\n  height: 100%;\n  display: flex;\n  z-index: 5;\n  pointer-events: none;\n}\n\n.g-grid-current-time-marker {\n  width: 0px;\n  height: calc(100% - 2px);\n  display: flex;\n}\n\n.g-grid-current-time-text {\n  font-size: x-small;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttGrid.vue",
    "content": "<template>\n  <div class=\"g-grid-container\">\n    <div\n      v-for=\"{ label, value, width } in timeaxisUnits.lowerUnits\"\n      :key=\"label\"\n      class=\"g-grid-line\"\n      :style=\"{\n        width,\n        background: highlightedUnits?.includes(Number(value)) ? colors.hoverHighlight : undefined\n      }\"\n    />\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport provideConfig from \"../provider/provideConfig.js\"\nimport useTimeaxisUnits from \"../composables/useTimeaxisUnits.js\"\n\ndefineProps<{\n  highlightedUnits?: number[]\n}>()\n\nconst { colors } = provideConfig()\nconst { timeaxisUnits } = useTimeaxisUnits()\n</script>\n\n<style>\n.g-grid-container {\n  position: absolute;\n  top: 0;\n  left: 0%;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  justify-content: space-between;\n}\n\n.g-grid-line {\n  width: 1px;\n  height: 100%;\n  border-left: 1px solid #eaeaea;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttLabelColumn.vue",
    "content": "<template>\n  <div class=\"g-label-column\" :style=\"{ fontFamily: font, color: colors.text }\">\n    <slot name=\"label-column-title\">\n      <div class=\"g-label-column-header\" :style=\"{ background: colors.primary }\">\n        {{ labelColumnTitle }}\n      </div>\n    </slot>\n    <div class=\"g-label-column-rows\">\n      <div\n        v-for=\"({ label }, index) in getChartRows()\"\n        :key=\"`${label}_${index}`\"\n        class=\"g-label-column-row\"\n        :style=\"{\n          background: index % 2 === 0 ? colors.ternary : colors.quartenary,\n          height: `${rowHeight}px`\n        }\"\n      >\n        <slot name=\"label-column-row\" :label=\"label\">\n          <span>{{ label }}</span>\n        </slot>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport provideGetChartRows from \"../provider/provideGetChartRows\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nconst { font, colors, labelColumnTitle, rowHeight } = provideConfig()\nconst getChartRows = provideGetChartRows()\n</script>\n\n<style>\n.g-label-column {\n  display: flex;\n  align-items: center;\n  flex-direction: column;\n  color: rgb(64, 64, 64);\n  font-variant-numeric: tabular-nums;\n  font-size: 0.9em;\n}\n\n.g-label-column-header {\n  width: 100%;\n  height: 80px;\n  min-height: 80px;\n  overflow: hidden;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-top-left-radius: 5px;\n}\n\n.g-label-column-rows {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  border-bottom-left-radius: 5px;\n}\n\n.g-label-column-row {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  padding: 0.1rem 0.3rem;\n  overflow: hidden;\n  white-space: normal;\n  box-sizing: border-box;\n  text-align: center;\n  align-items: center;\n  justify-content: center;\n}\n\n.g-label-column-row:last-child {\n  border-bottom-left-radius: 5px;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttRow.vue",
    "content": "<template>\n  <div\n    class=\"g-gantt-row\"\n    :style=\"rowStyle\"\n    @dragover.prevent=\"isHovering = true\"\n    @dragleave=\"isHovering = false\"\n    @drop=\"onDrop($event)\"\n    @mouseover=\"isHovering = true\"\n    @mouseleave=\"isHovering = false\"\n  >\n    <div\n      v-if=\"!isBlank(label) && !labelColumnTitle\"\n      class=\"g-gantt-row-label\"\n      :style=\"{ background: colors.primary, color: colors.text }\"\n    >\n      <slot name=\"label\">\n        {{ label }}\n      </slot>\n    </div>\n    <div ref=\"barContainer\" class=\"g-gantt-row-bars-container\" v-bind=\"$attrs\">\n      <transition-group name=\"bar-transition\" tag=\"div\">\n        <g-gantt-bar v-for=\"bar in bars\" :key=\"bar.ganttBarConfig.id\" :bar=\"bar\">\n          <slot name=\"bar-label\" :bar=\"bar\" />\n        </g-gantt-bar>\n      </transition-group>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, type Ref, toRefs, computed, type StyleValue, provide } from \"vue\"\n\nimport useTimePositionMapping from \"../composables/useTimePositionMapping.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\nimport type { GanttBarObject } from \"../types\"\nimport GGanttBar from \"./GGanttBar.vue\"\nimport { BAR_CONTAINER_KEY } from \"../provider/symbols\"\n\nconst props = defineProps<{\n  label: string\n  bars: GanttBarObject[]\n  highlightOnHover?: boolean\n}>()\n\nconst emit = defineEmits<{\n  (e: \"drop\", value: { e: MouseEvent; datetime: string | Date }): void\n}>()\n\nconst { rowHeight, colors, labelColumnTitle } = provideConfig()\nconst { highlightOnHover } = toRefs(props)\nconst isHovering = ref(false)\n\nconst rowStyle = computed(() => {\n  return {\n    height: `${rowHeight.value}px`,\n    background: highlightOnHover?.value && isHovering.value ? colors.value.hoverHighlight : null\n  } as StyleValue\n})\n\nconst { mapPositionToTime } = useTimePositionMapping()\nconst barContainer: Ref<HTMLElement | null> = ref(null)\n\nprovide(BAR_CONTAINER_KEY, barContainer)\n\nconst onDrop = (e: MouseEvent) => {\n  const container = barContainer.value?.getBoundingClientRect()\n  if (!container) {\n    console.error(\"Vue-Ganttastic: failed to find bar container element for row.\")\n    return\n  }\n  const xPos = e.clientX - container.left\n  const datetime = mapPositionToTime(xPos)\n  emit(\"drop\", { e, datetime })\n}\n\nconst isBlank = (str: string) => {\n  return (!str || /^\\s*$/.test(str))\n}\n\n</script>\n\n<style>\n.g-gantt-row {\n  width: 100%;\n  transition: background 0.4s;\n  position: relative;\n}\n\n.g-gantt-row > .g-gantt-row-bars-container {\n  position: relative;\n  border-top: 1px solid #eaeaea;\n  width: 100%;\n  border-bottom: 1px solid #eaeaea;\n}\n\n.g-gantt-row-label {\n  position: absolute;\n  top: 0;\n  left: 0px;\n  padding: 0px 8px;\n  display: flex;\n  align-items: center;\n  height: 60%;\n  min-height: 20px;\n  font-size: 0.8em;\n  font-weight: bold;\n  border-bottom-right-radius: 6px;\n  background: #f2f2f2;\n  z-index: 3;\n  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.6);\n}\n\n.bar-transition-leave-active,\n.bar-transition-enter-active {\n  transition: all 0.2s;\n}\n\n.bar-transition-enter-from,\n.bar-transition-leave-to {\n  transform: scale(0.8);\n  opacity: 0;\n}\n</style>\n"
  },
  {
    "path": "src/components/GGanttTimeaxis.vue",
    "content": "<template>\n  <div class=\"g-timeaxis\">\n    <div class=\"g-timeunits-container\">\n      <div\n        v-for=\"({ label, value, date, width }, index) in timeaxisUnits.upperUnits\"\n        :key=\"label\"\n        class=\"g-upper-timeunit\"\n        :style=\"{\n          background: index % 2 === 0 ? colors.primary : colors.secondary,\n          color: colors.text,\n          width\n        }\"\n      >\n        <slot name=\"upper-timeunit\" :label=\"label\" :value=\"value\" :date=\"date\">\n          {{ label }}\n        </slot>\n      </div>\n    </div>\n\n    <div class=\"g-timeunits-container\">\n      <div\n        v-for=\"({ label, value, date, width }, index) in timeaxisUnits.lowerUnits\"\n        :key=\"label\"\n        class=\"g-timeunit\"\n        :style=\"{\n          background: index % 2 === 0 ? colors.ternary : colors.quartenary,\n          color: colors.text,\n          flexDirection: precision === 'hour' ? 'column' : 'row',\n          alignItems: precision === 'hour' ? '' : 'center',\n          width\n        }\"\n      >\n        <slot name=\"timeunit\" :label=\"label\" :value=\"value\" :date=\"date\">\n          {{ label }}\n        </slot>\n        <div\n          v-if=\"precision === 'hour'\"\n          class=\"g-timeaxis-hour-pin\"\n          :style=\"{ background: colors.text }\"\n        />\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport provideConfig from \"../provider/provideConfig.js\"\nimport useTimeaxisUnits from \"../composables/useTimeaxisUnits.js\"\n\nconst { precision, colors } = provideConfig()\nconst { timeaxisUnits } = useTimeaxisUnits()\n</script>\n\n<style>\n.g-timeaxis {\n  position: sticky;\n  top: 0;\n  width: 100%;\n  height: 80px;\n  background: white;\n  z-index: 4;\n  display: flex;\n  flex-direction: column;\n}\n\n.g-timeunits-container {\n  display: flex;\n  width: 100%;\n  height: 50%;\n}\n\n.g-timeunit {\n  height: 100%;\n  font-size: 65%;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n}\n\n.g-upper-timeunit {\n  display: flex;\n  height: 100%;\n  justify-content: center;\n  align-items: center;\n}\n\n.g-timeaxis-hour-pin {\n  width: 1px;\n  height: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/composables/createBarDrag.ts",
    "content": "import { ref } from \"vue\"\nimport type { GGanttChartConfig } from \"../components/GGanttChart.vue\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nimport type { GanttBarObject } from \"../types\"\nimport useDayjsHelper from \"./useDayjsHelper.js\"\nimport useTimePositionMapping from \"./useTimePositionMapping.js\"\n\nexport default function createBarDrag(\n  bar: GanttBarObject,\n  onDrag: (e: MouseEvent, bar: GanttBarObject) => void = () => null,\n  onEndDrag: (e: MouseEvent, bar: GanttBarObject) => void = () => null,\n  config: GGanttChartConfig = provideConfig()\n) {\n  const { barStart, barEnd, pushOnOverlap } = config\n\n  const isDragging = ref(false)\n  let cursorOffsetX = 0\n  let dragCallBack: (e: MouseEvent) => void\n\n  const { mapPositionToTime } = useTimePositionMapping(config)\n  const { toDayjs } = useDayjsHelper(config)\n\n  const initDrag = (e: MouseEvent) => {\n    const barElement = document.getElementById(bar.ganttBarConfig.id)\n    if (!barElement) {\n      return\n    }\n\n    cursorOffsetX = e.clientX - (barElement.getBoundingClientRect().left || 0)\n    const mousedownType = (e.target as Element).className\n    switch (mousedownType) {\n      case \"g-gantt-bar-handle-left\":\n        document.body.style.cursor = \"ew-resize\"\n        dragCallBack = dragByLeftHandle\n        break\n      case \"g-gantt-bar-handle-right\":\n        document.body.style.cursor = \"ew-resize\"\n        dragCallBack = dragByRightHandle\n        break\n      default:\n        dragCallBack = drag\n    }\n    isDragging.value = true\n    window.addEventListener(\"mousemove\", dragCallBack)\n    window.addEventListener(\"mouseup\", endDrag)\n  }\n\n  const getBarElements = () => {\n    const barElement = document.getElementById(bar.ganttBarConfig.id)\n    const barContainer = barElement?.closest(\".g-gantt-row-bars-container\")?.getBoundingClientRect()\n    return { barElement, barContainer }\n  }\n\n  const drag = (e: MouseEvent) => {\n    const { barElement, barContainer } = getBarElements()\n    if (!barElement || !barContainer) {\n      return\n    }\n\n    const barWidth = barElement.getBoundingClientRect().width\n    const xStart = e.clientX - barContainer.left - cursorOffsetX\n    const xEnd = xStart + barWidth\n    if (isOutOfRange(xStart, xEnd)) {\n      return\n    }\n    bar[barStart.value] = mapPositionToTime(xStart)\n    bar[barEnd.value] = mapPositionToTime(xEnd)\n    onDrag(e, bar)\n  }\n\n  const dragByLeftHandle = (e: MouseEvent) => {\n    const { barElement, barContainer } = getBarElements()\n    if (!barElement || !barContainer) {\n      return\n    }\n\n    const xStart = e.clientX - barContainer.left\n    const newBarStart = mapPositionToTime(xStart)\n    if (toDayjs(newBarStart).isSameOrAfter(toDayjs(bar, \"end\"))) {\n      return\n    }\n    bar[barStart.value] = newBarStart\n    onDrag(e, bar)\n  }\n\n  const dragByRightHandle = (e: MouseEvent) => {\n    const { barElement, barContainer } = getBarElements()\n    if (!barElement || !barContainer) {\n      return\n    }\n\n    const xEnd = e.clientX - barContainer.left\n    const newBarEnd = mapPositionToTime(xEnd)\n    if (toDayjs(newBarEnd).isSameOrBefore(toDayjs(bar, \"start\"))) {\n      return\n    }\n    bar[barEnd.value] = newBarEnd\n    onDrag(e, bar)\n  }\n\n  const isOutOfRange = (xStart?: number, xEnd?: number) => {\n    if (!pushOnOverlap.value) {\n      return false\n    }\n    const dragLimitLeft = bar.ganttBarConfig.dragLimitLeft\n    const dragLimitRight = bar.ganttBarConfig.dragLimitRight\n\n    return (\n      (xStart && dragLimitLeft != null && xStart < dragLimitLeft) ||\n      (xEnd && dragLimitRight != null && xEnd > dragLimitRight)\n    )\n  }\n\n  const endDrag = (e: MouseEvent) => {\n    isDragging.value = false\n    document.body.style.cursor = \"\"\n    window.removeEventListener(\"mousemove\", dragCallBack)\n    window.removeEventListener(\"mouseup\", endDrag)\n    onEndDrag(e, bar)\n  }\n\n  return {\n    isDragging,\n    initDrag\n  }\n}\n"
  },
  {
    "path": "src/composables/useBarDragLimit.ts",
    "content": "import type { GanttBarObject } from \"../types\"\nimport provideConfig from \"../provider/provideConfig.js\"\nimport provideGetChartRows from \"../provider/provideGetChartRows.js\"\n\nexport default function useBarDragLimit() {\n  const { pushOnOverlap } = provideConfig()\n  const getChartRows = provideGetChartRows()\n\n  const getBarsFromBundle = (bundle?: string) => {\n    const res: GanttBarObject[] = []\n    if (bundle != null) {\n      getChartRows().forEach((row) => {\n        row.bars.forEach((bar) => {\n          if (bar.ganttBarConfig.bundle === bundle) {\n            res.push(bar)\n          }\n        })\n      })\n    }\n    return res\n  }\n\n  const setDragLimitsOfGanttBar = (bar: GanttBarObject) => {\n    if (!pushOnOverlap.value || bar.ganttBarConfig.pushOnOverlap === false) {\n      return\n    }\n    for (const sideValue of [\"left\", \"right\"]) {\n      const side = sideValue as \"left\" | \"right\"\n      const { gapDistanceSoFar, bundleBarsAndGapDist } = countGapDistanceToNextImmobileBar(\n        bar,\n        0,\n        side\n      )\n      let totalGapDistance = gapDistanceSoFar\n      const bundleBarsOnPath = bundleBarsAndGapDist\n      if (!bundleBarsOnPath) {\n        continue\n      }\n\n      for (let i = 0; i < bundleBarsOnPath.length; i++) {\n        const barFromBundle = bundleBarsOnPath[i].bar\n        const gapDist = bundleBarsOnPath[i].gapDistance\n        const otherBarsFromBundle = getBarsFromBundle(barFromBundle.ganttBarConfig.bundle).filter(\n          (otherBar) => otherBar !== barFromBundle\n        )\n        otherBarsFromBundle.forEach((otherBar) => {\n          const nextGapDistanceAndBars = countGapDistanceToNextImmobileBar(otherBar, gapDist, side)\n          const newGapDistance = nextGapDistanceAndBars.gapDistanceSoFar\n          const newBundleBars = nextGapDistanceAndBars.bundleBarsAndGapDist\n          if (newGapDistance != null && (!totalGapDistance || newGapDistance < totalGapDistance)) {\n            totalGapDistance = newGapDistance\n          }\n          newBundleBars.forEach((newBundleBar) => {\n            if (!bundleBarsOnPath.find((barAndGap) => barAndGap.bar === newBundleBar.bar)) {\n              bundleBarsOnPath.push(newBundleBar)\n            }\n          })\n        })\n      }\n      const barElem = document.getElementById(bar.ganttBarConfig.id) as HTMLElement\n      if (totalGapDistance != null && side === \"left\") {\n        bar.ganttBarConfig.dragLimitLeft = barElem.offsetLeft - totalGapDistance\n      } else if (totalGapDistance != null && side === \"right\") {\n        bar.ganttBarConfig.dragLimitRight =\n          barElem.offsetLeft + barElem.offsetWidth + totalGapDistance\n      }\n    }\n    // all bars from the bundle of the clicked bar need to have the same drag limit:\n    const barsFromBundleOfClickedBar = getBarsFromBundle(bar.ganttBarConfig.bundle)\n    barsFromBundleOfClickedBar.forEach((barFromBundle) => {\n      barFromBundle.ganttBarConfig.dragLimitLeft = bar.ganttBarConfig.dragLimitLeft\n      barFromBundle.ganttBarConfig.dragLimitRight = bar.ganttBarConfig.dragLimitRight\n    })\n  }\n\n  // returns the gap distance to the next immobile bar\n  // in the row where the given bar (parameter) is (added to gapDistanceSoFar)\n  // and a list of all bars on that path that belong to a bundle\n  const countGapDistanceToNextImmobileBar = (\n    bar: GanttBarObject,\n    gapDistanceSoFar = 0,\n    side: \"left\" | \"right\"\n  ) => {\n    const bundleBarsAndGapDist = bar.ganttBarConfig.bundle\n      ? [{ bar, gapDistance: gapDistanceSoFar }]\n      : []\n    let currentBar = bar\n    let nextBar = getNextGanttBar(currentBar, side)\n    // left side:\n    if (side === \"left\") {\n      while (nextBar) {\n        const currentBarElem = document.getElementById(currentBar.ganttBarConfig.id) as HTMLElement\n        const nextBarElem = document.getElementById(nextBar.ganttBarConfig.id) as HTMLElement\n        const nextBarOffsetRight = nextBarElem.offsetLeft + nextBarElem.offsetWidth\n        gapDistanceSoFar += currentBarElem.offsetLeft - nextBarOffsetRight\n        if (nextBar.ganttBarConfig.immobile) {\n          return { gapDistanceSoFar, bundleBarsAndGapDist }\n        } else if (nextBar.ganttBarConfig.bundle) {\n          bundleBarsAndGapDist.push({\n            bar: nextBar,\n            gapDistance: gapDistanceSoFar\n          })\n        }\n        currentBar = nextBar\n        nextBar = getNextGanttBar(nextBar, \"left\")\n      }\n    }\n    if (side === \"right\") {\n      while (nextBar) {\n        const currentBarElem = document.getElementById(currentBar.ganttBarConfig.id) as HTMLElement\n        const nextBarElem = document.getElementById(nextBar.ganttBarConfig.id) as HTMLElement\n        const currentBarOffsetRight = currentBarElem.offsetLeft + currentBarElem.offsetWidth\n        gapDistanceSoFar += nextBarElem.offsetLeft - currentBarOffsetRight\n        if (nextBar.ganttBarConfig.immobile) {\n          return { gapDistanceSoFar, bundleBarsAndGapDist }\n        } else if (nextBar.ganttBarConfig.bundle) {\n          bundleBarsAndGapDist.push({\n            bar: nextBar,\n            gapDistance: gapDistanceSoFar\n          })\n        }\n        currentBar = nextBar\n        nextBar = getNextGanttBar(nextBar, \"right\")\n      }\n    }\n    return { gapDistanceSoFar: null, bundleBarsAndGapDist }\n  }\n\n  const getNextGanttBar = (bar: GanttBarObject, side: \"left\" | \"right\") => {\n    const barElem = document.getElementById(bar.ganttBarConfig.id) as HTMLElement\n    const allBarsInRow = getChartRows().find((row) => row.bars.includes(bar))?.bars ?? []\n    let allBarsLeftOrRight = []\n    if (side === \"left\") {\n      allBarsLeftOrRight = allBarsInRow.filter((otherBar) => {\n        const otherBarElem = document.getElementById(otherBar.ganttBarConfig.id) as HTMLElement\n        return (\n          otherBarElem &&\n          otherBarElem.offsetLeft < barElem.offsetLeft &&\n          otherBar.ganttBarConfig.pushOnOverlap !== false\n        )\n      })\n    } else {\n      allBarsLeftOrRight = allBarsInRow.filter((otherBar) => {\n        const otherBarElem = document.getElementById(otherBar.ganttBarConfig.id) as HTMLElement\n        return (\n          otherBarElem &&\n          otherBarElem.offsetLeft > barElem.offsetLeft &&\n          otherBar.ganttBarConfig.pushOnOverlap !== false\n        )\n      })\n    }\n    if (allBarsLeftOrRight.length > 0) {\n      return allBarsLeftOrRight.reduce((bar1, bar2) => {\n        const bar1Elem = document.getElementById(bar1.ganttBarConfig.id) as HTMLElement\n        const bar2Elem = document.getElementById(bar2.ganttBarConfig.id) as HTMLElement\n        const bar1Dist = Math.abs(bar1Elem.offsetLeft - barElem.offsetLeft)\n        const bar2Dist = Math.abs(bar2Elem.offsetLeft - barElem.offsetLeft)\n        return bar1Dist < bar2Dist ? bar1 : bar2\n      }, allBarsLeftOrRight[0])\n    } else {\n      return null\n    }\n  }\n\n  return {\n    setDragLimitsOfGanttBar\n  }\n}\n"
  },
  {
    "path": "src/composables/useBarDragManagement.ts",
    "content": "import type { GanttBarObject } from \"../types\"\n\nimport createBarDrag from \"./createBarDrag.js\"\nimport useDayjsHelper from \"./useDayjsHelper.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\nimport provideGetChartRows from \"../provider/provideGetChartRows.js\"\nimport provideEmitBarEvent from \"../provider/provideEmitBarEvent.js\"\n\nexport default function useBarDragManagement() {\n  const config = provideConfig()\n  const getChartRows = provideGetChartRows()\n  const emitBarEvent = provideEmitBarEvent()\n  const { pushOnOverlap, barStart, barEnd, noOverlap, dateFormat } = config\n\n  const movedBarsInDrag = new Map<GanttBarObject, { oldStart: string; oldEnd: string }>()\n\n  const { toDayjs, format } = useDayjsHelper()\n\n  const initDragOfBar = (bar: GanttBarObject, e: MouseEvent) => {\n    const { initDrag } = createBarDrag(bar, onDrag, onEndDrag, config)\n    emitBarEvent({ ...e, type: \"dragstart\" }, bar)\n    initDrag(e)\n    addBarToMovedBars(bar)\n  }\n\n  const initDragOfBundle = (mainBar: GanttBarObject, e: MouseEvent) => {\n    const bundle = mainBar.ganttBarConfig.bundle\n    if (bundle == null) {\n      return\n    }\n    getChartRows().forEach((row) => {\n      row.bars.forEach((bar) => {\n        if (bar.ganttBarConfig.bundle === bundle) {\n          const dragEndHandler = bar === mainBar ? onEndDrag : () => null\n          const { initDrag } = createBarDrag(bar, onDrag, dragEndHandler, config)\n          initDrag(e)\n          addBarToMovedBars(bar)\n        }\n      })\n    })\n    emitBarEvent({ ...e, type: \"dragstart\" }, mainBar)\n  }\n\n  const onDrag = (e: MouseEvent, bar: GanttBarObject) => {\n    emitBarEvent({ ...e, type: \"drag\" }, bar)\n    fixOverlaps(bar)\n  }\n\n  const fixOverlaps = (ganttBar: GanttBarObject) => {\n    if (!pushOnOverlap?.value) {\n      return\n    }\n    let currentBar = ganttBar\n    let { overlapBar, overlapType } = getOverlapBarAndType(currentBar)\n    while (overlapBar) {\n      addBarToMovedBars(overlapBar)\n      const currentBarStart = toDayjs(currentBar[barStart.value])\n      const currentBarEnd = toDayjs(currentBar[barEnd.value])\n      const overlapBarStart = toDayjs(overlapBar[barStart.value])\n      const overlapBarEnd = toDayjs(overlapBar[barEnd.value])\n      let minuteDiff: number\n      switch (overlapType) {\n        case \"left\":\n          minuteDiff = overlapBarEnd.diff(currentBarStart, \"minutes\", true)\n          overlapBar[barEnd.value] = format(currentBar[barStart.value], dateFormat.value)\n          overlapBar[barStart.value] = format(\n            overlapBarStart.subtract(minuteDiff, \"minutes\"),\n            dateFormat.value\n          )\n          break\n        case \"right\":\n          minuteDiff = currentBarEnd.diff(overlapBarStart, \"minutes\", true)\n          overlapBar[barStart.value] = format(currentBarEnd, dateFormat.value)\n          overlapBar[barEnd.value] = format(\n            overlapBarEnd.add(minuteDiff, \"minutes\"),\n            dateFormat.value\n          )\n          break\n        default:\n          console.warn(\n            \"Vue-Ganttastic: One bar is inside of the other one! This should never occur while push-on-overlap is active!\"\n          )\n          return\n      }\n      if (overlapBar && (overlapType === \"left\" || overlapType === \"right\")) {\n        moveBundleOfPushedBarByMinutes(overlapBar, minuteDiff, overlapType)\n      }\n      currentBar = overlapBar\n      ;({ overlapBar, overlapType } = getOverlapBarAndType(overlapBar))\n    }\n  }\n\n  const getOverlapBarAndType = (ganttBar: GanttBarObject) => {\n    let overlapLeft, overlapRight, overlapInBetween\n    const allBarsInRow = getChartRows().find((row) => row.bars.includes(ganttBar))?.bars ?? []\n    const ganttBarStart = toDayjs(ganttBar[barStart.value])\n    const ganttBarEnd = toDayjs(ganttBar[barEnd.value])\n    const overlapBar = allBarsInRow.find((otherBar) => {\n      if (otherBar === ganttBar) {\n        return false\n      }\n      const otherBarStart = toDayjs(otherBar[barStart.value])\n      const otherBarEnd = toDayjs(otherBar[barEnd.value])\n      overlapLeft = ganttBarStart.isBetween(otherBarStart, otherBarEnd)\n      overlapRight = ganttBarEnd.isBetween(otherBarStart, otherBarEnd)\n      overlapInBetween =\n        otherBarStart.isBetween(ganttBarStart, ganttBarEnd) ||\n        otherBarEnd.isBetween(ganttBarStart, ganttBarEnd)\n      return overlapLeft || overlapRight || overlapInBetween\n    })\n    const overlapType = overlapLeft\n      ? \"left\"\n      : overlapRight\n      ? \"right\"\n      : overlapInBetween\n      ? \"between\"\n      : null\n    return { overlapBar, overlapType }\n  }\n\n  const moveBundleOfPushedBarByMinutes = (\n    pushedBar: GanttBarObject,\n    minutes: number,\n    direction: \"left\" | \"right\"\n  ) => {\n    addBarToMovedBars(pushedBar)\n    if (!pushedBar.ganttBarConfig.bundle) {\n      return\n    }\n    getChartRows().forEach((row) => {\n      row.bars.forEach((bar) => {\n        if (bar.ganttBarConfig.bundle === pushedBar.ganttBarConfig.bundle && bar !== pushedBar) {\n          addBarToMovedBars(bar)\n          moveBarByMinutes(bar, minutes, direction)\n        }\n      })\n    })\n  }\n\n  const moveBarByMinutes = (bar: GanttBarObject, minutes: number, direction: \"left\" | \"right\") => {\n    switch (direction) {\n      case \"left\":\n        bar[barStart.value] = format(\n          toDayjs(bar, \"start\").subtract(minutes, \"minutes\"),\n          dateFormat.value\n        )\n        bar[barEnd.value] = format(\n          toDayjs(bar, \"end\").subtract(minutes, \"minutes\"),\n          dateFormat.value\n        )\n        break\n      case \"right\":\n        bar[barStart.value] = format(\n          toDayjs(bar, \"start\").add(minutes, \"minutes\"),\n          dateFormat.value\n        )\n        bar[barEnd.value] = format(toDayjs(bar, \"end\").add(minutes, \"minutes\"), dateFormat.value)\n    }\n    fixOverlaps(bar)\n  }\n\n  const onEndDrag = (e: MouseEvent, bar: GanttBarObject) => {\n    snapBackAllMovedBarsIfNeeded()\n    const ev = {\n      ...e,\n      type: \"dragend\"\n    }\n    emitBarEvent(ev, bar, undefined, new Map(movedBarsInDrag))\n    movedBarsInDrag.clear()\n  }\n\n  const addBarToMovedBars = (bar: GanttBarObject) => {\n    if (!movedBarsInDrag.has(bar)) {\n      const oldStart = bar[barStart.value]\n      const oldEnd = bar[barEnd.value]\n      movedBarsInDrag.set(bar, { oldStart, oldEnd })\n    }\n  }\n\n  const snapBackAllMovedBarsIfNeeded = () => {\n    if (pushOnOverlap.value || !noOverlap.value) {\n      return\n    }\n\n    let isAnyOverlap = false\n    movedBarsInDrag.forEach((_, bar) => {\n      const { overlapBar } = getOverlapBarAndType(bar)\n      if (overlapBar != null) {\n        isAnyOverlap = true\n      }\n    })\n    if (!isAnyOverlap) {\n      return\n    }\n    movedBarsInDrag.forEach(({ oldStart, oldEnd }, bar) => {\n      bar[barStart.value] = oldStart\n      bar[barEnd.value] = oldEnd\n    })\n  }\n\n  return {\n    initDragOfBar,\n    initDragOfBundle\n  }\n}\n"
  },
  {
    "path": "src/composables/useDayjsHelper.ts",
    "content": "import dayjs, { type Dayjs } from \"dayjs\"\nimport { computed } from \"vue\"\n\nimport type { GGanttChartConfig } from \"../components/GGanttChart.vue\"\nimport type { GanttBarObject } from \"../types\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nexport const DEFAULT_DATE_FORMAT = \"YYYY-MM-DD HH:mm\"\n\nexport default function useDayjsHelper(config: GGanttChartConfig = provideConfig()) {\n  const { chartStart, chartEnd, barStart, barEnd, dateFormat } = config\n\n  const chartStartDayjs = computed(() => toDayjs(chartStart.value))\n  const chartEndDayjs = computed(() => toDayjs(chartEnd.value))\n\n  const toDayjs = (input: string | Date | GanttBarObject, startOrEnd?: \"start\" | \"end\") => {\n    let value\n    if (startOrEnd !== undefined && typeof input !== \"string\" && !(input instanceof Date)) {\n      value = startOrEnd === \"start\" ? input[barStart.value] : input[barEnd.value]\n    }\n    if (typeof input === \"string\") {\n      value = input\n    } else if (input instanceof Date) {\n      return dayjs(input)\n    }\n    const format = dateFormat.value || DEFAULT_DATE_FORMAT\n    return dayjs(value, format, true)\n  }\n\n  const format = (input: string | Date | Dayjs, pattern?: string | false) => {\n    if (pattern === false) {\n      return input instanceof Date ? input : dayjs(input).toDate()\n    }\n    const inputDayjs = typeof input === \"string\" || input instanceof Date ? toDayjs(input) : input\n\n    return inputDayjs.format(pattern)\n  }\n\n  return {\n    chartStartDayjs,\n    chartEndDayjs,\n    toDayjs,\n    format\n  }\n}\n"
  },
  {
    "path": "src/composables/useTimePositionMapping.ts",
    "content": "import type { GGanttChartConfig } from \"../components/GGanttChart.vue\"\nimport { computed } from \"vue\"\n\nimport useDayjsHelper from \"./useDayjsHelper.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nexport default function useTimePositionMapping(config: GGanttChartConfig = provideConfig()) {\n  const { dateFormat, chartSize } = config\n  const { chartStartDayjs, chartEndDayjs, toDayjs, format } = useDayjsHelper(config)\n\n  const totalNumOfMinutes = computed(() => {\n    return chartEndDayjs.value.diff(chartStartDayjs.value, \"minutes\")\n  })\n\n  const mapTimeToPosition = (time: string) => {\n    const width = chartSize.width.value || 0\n    const diffFromStart = toDayjs(time).diff(chartStartDayjs.value, \"minutes\", true)\n    return Math.ceil((diffFromStart / totalNumOfMinutes.value) * width)\n  }\n\n  const mapPositionToTime = (xPos: number) => {\n    const width = chartSize.width.value || 0\n    const diffFromStart = (xPos / width) * totalNumOfMinutes.value\n    return format(chartStartDayjs.value.add(diffFromStart, \"minutes\"), dateFormat.value)\n  }\n\n  return {\n    mapTimeToPosition,\n    mapPositionToTime\n  }\n}\n"
  },
  {
    "path": "src/composables/useTimeaxisUnits.ts",
    "content": "import { computed } from \"vue\"\nimport useDayjsHelper from \"./useDayjsHelper.js\"\nimport provideConfig from \"../provider/provideConfig.js\"\n\nexport default function useTimeaxisUnits() {\n  const { precision } = provideConfig()\n  const { chartStartDayjs, chartEndDayjs } = useDayjsHelper()\n\n  const upperPrecision = computed(() => {\n    switch (precision?.value) {\n      case \"hour\":\n        return \"day\"\n      case \"day\":\n        return \"month\"\n      case \"date\":\n      case \"week\":\n        return \"month\"\n      case \"month\":\n        return \"year\"\n      default:\n        throw new Error(\n          \"Precision prop incorrect. Must be one of the following: 'hour', 'day', 'date', 'week', 'month'\"\n        )\n    }\n  })\n\n  const lowerPrecision = computed(() => {\n    switch (precision.value) {\n      case \"date\":\n        return \"day\"\n      case \"week\":\n        return \"isoWeek\"\n      default:\n        return precision.value\n    }\n  })\n\n  const displayFormats = {\n    hour: \"HH\",\n    date: \"DD.MMM\",\n    day: \"DD.MMM\",\n    week: \"WW\",\n    month: \"MMMM YYYY\",\n    year: \"YYYY\"\n  }\n\n  const timeaxisUnits = computed(() => {\n    const upperUnits: { label: string; value?: string; date: Date; width?: string }[] = []\n    const lowerUnits: { label: string; value?: string; date: Date; width?: string }[] = []\n    const totalMinutes = chartEndDayjs.value.diff(chartStartDayjs.value, \"minutes\", true)\n    const upperUnit = upperPrecision.value\n    const lowerUnit = lowerPrecision.value\n    let currentUpperUnit = chartStartDayjs.value\n    let currentLowerUnit = chartStartDayjs.value\n\n    while (currentLowerUnit.isSameOrBefore(chartEndDayjs.value)) {\n      const endCurrentLowerUnit = currentLowerUnit.endOf(lowerUnit)\n      const isLastItem = endCurrentLowerUnit.isAfter(chartEndDayjs.value)\n\n      const lowerWidth = isLastItem\n        ? (chartEndDayjs.value.diff(currentLowerUnit, \"minutes\", true) / totalMinutes) * 100\n        : (endCurrentLowerUnit.diff(currentLowerUnit, \"minutes\", true) / totalMinutes) * 100\n\n      lowerUnits.push({\n        label: currentLowerUnit.format(displayFormats[precision?.value]),\n        value: String(currentLowerUnit),\n        date: currentLowerUnit.toDate(),\n        width: String(lowerWidth) + \"%\"\n      })\n      currentLowerUnit = endCurrentLowerUnit\n        .add(1, lowerUnit === \"isoWeek\" ? \"week\" : lowerUnit)\n        .startOf(lowerUnit)\n    }\n    while (currentUpperUnit.isSameOrBefore(chartEndDayjs.value)) {\n      const endCurrentUpperUnit = currentUpperUnit.endOf(upperUnit)\n      const isLastItem = endCurrentUpperUnit.isAfter(chartEndDayjs.value)\n\n      const upperWidth = isLastItem\n        ? (chartEndDayjs.value.diff(currentUpperUnit, \"minutes\", true) / totalMinutes) * 100\n        : (endCurrentUpperUnit.diff(currentUpperUnit, \"minutes\", true) / totalMinutes) * 100\n\n      upperUnits.push({\n        label: currentUpperUnit.format(displayFormats[upperUnit]),\n        value: String(currentUpperUnit),\n        date: currentUpperUnit.toDate(),\n        width: String(upperWidth) + \"%\"\n      })\n\n      currentUpperUnit = endCurrentUpperUnit.add(1, upperUnit).startOf(upperUnit)\n    }\n    return { upperUnits, lowerUnits }\n  })\n\n  return {\n    timeaxisUnits\n  }\n}\n"
  },
  {
    "path": "src/playground.ts",
    "content": "import { createApp } from \"vue\"\nimport Playground from \"./GanttPlayground.vue\"\nimport ganttastic from \"./vue-ganttastic.js\"\n\ncreateApp(Playground).use(ganttastic).mount(\"#app\")\n"
  },
  {
    "path": "src/provider/provideConfig.ts",
    "content": "import { inject } from \"vue\"\nimport { CONFIG_KEY } from \"./symbols.js\"\n\nexport default function provideConfig() {\n  const config = inject(CONFIG_KEY)\n  if (!config) {\n    throw Error(\"Failed to inject config!\")\n  }\n  return config\n}\n"
  },
  {
    "path": "src/provider/provideEmitBarEvent.ts",
    "content": "import { inject } from \"vue\"\nimport { EMIT_BAR_EVENT_KEY } from \"./symbols.js\"\n\nexport default function provideEmitBarEvent() {\n  const emitBarEvent = inject(EMIT_BAR_EVENT_KEY)\n  if (!emitBarEvent) {\n    throw Error(\"Failed to inject emitBarEvent!\")\n  }\n  return emitBarEvent\n}\n"
  },
  {
    "path": "src/provider/provideGetChartRows.ts",
    "content": "import { inject } from \"vue\"\nimport { CHART_ROWS_KEY } from \"./symbols.js\"\n\nexport default function provideGetChartRows() {\n  const getChartRows = inject(CHART_ROWS_KEY)\n  if (!getChartRows) {\n    throw Error(\"Failed to inject getChartRows!\")\n  }\n  return getChartRows\n}\n"
  },
  {
    "path": "src/provider/symbols.ts",
    "content": "import type { InjectionKey, Ref } from \"vue\"\n\nimport type { GGanttChartConfig } from \"../components/GGanttChart.vue\"\nimport type { GanttBarObject } from \"../types\"\n\nexport type ChartRow = { label: string; bars: GanttBarObject[] }\nexport type GetChartRows = () => ChartRow[]\nexport type EmitBarEvent = (\n  e: MouseEvent,\n  bar: GanttBarObject,\n  datetime?: string | Date,\n  movedBars?: Map<GanttBarObject, { oldStart: string; oldEnd: string }>\n) => void\n\nexport const CHART_ROWS_KEY = Symbol(\"CHART_ROWS_KEY\") as InjectionKey<GetChartRows>\nexport const CONFIG_KEY = Symbol(\"CONFIG_KEY\") as InjectionKey<GGanttChartConfig>\nexport const EMIT_BAR_EVENT_KEY = Symbol(\"EMIT_BAR_EVENT_KEY\") as InjectionKey<EmitBarEvent>\nexport const BAR_CONTAINER_KEY = Symbol(\"BAR_CONTAINER_KEY\") as InjectionKey<\n  Ref<HTMLElement | null>\n>\n"
  },
  {
    "path": "src/types.ts",
    "content": "import type { CSSProperties } from \"vue\"\n\nexport type GanttBarObject = {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  [key: string]: any\n  ganttBarConfig: {\n    id: string\n    label?: string\n    html?: string\n    hasHandles?: boolean\n    immobile?: boolean\n    bundle?: string\n    pushOnOverlap?: boolean\n    dragLimitLeft?: number\n    dragLimitRight?: number\n    style?: CSSProperties\n    class?: string\n  }\n}\n"
  },
  {
    "path": "src/vue-ganttastic.ts",
    "content": "import type { Plugin } from \"vue\"\nimport dayjs from \"dayjs\"\nimport isoWeek from \"dayjs/plugin/isoWeek\"\nimport isSameOrBefore from \"dayjs/plugin/isSameOrBefore.js\"\nimport isSameOrAfter from \"dayjs/plugin/isSameOrAfter.js\"\nimport isBetween from \"dayjs/plugin/isBetween.js\"\nimport weekOfYear from \"dayjs/plugin/weekOfYear\"\nimport advancedFormat from \"dayjs/plugin/advancedFormat\"\nimport customParseFormat from \"dayjs/plugin/customParseFormat.js\"\n\nimport type { GanttBarObject } from \"./types.js\"\nimport type { ColorScheme } from \"./color-schemes\"\n\nimport GGanttChart from \"./components/GGanttChart.vue\"\nimport GGanttRow from \"./components/GGanttRow.vue\"\n\nexport function extendDayjs() {\n  dayjs.extend(isSameOrBefore)\n  dayjs.extend(isSameOrAfter)\n  dayjs.extend(isBetween)\n  dayjs.extend(customParseFormat)\n  dayjs.extend(weekOfYear)\n  dayjs.extend(isoWeek)\n  dayjs.extend(advancedFormat)\n}\n\nexport type { ColorScheme, GanttBarObject }\nexport { GGanttChart, GGanttRow }\n\nexport const ganttastic: Plugin = {\n  install(app, options?) {\n    extendDayjs()\n    app.component(\"GGanttChart\", GGanttChart)\n    app.component(\"GGanttRow\", GGanttRow)\n  }\n}\n\nexport default ganttastic\n"
  },
  {
    "path": "tsconfig.config.json",
    "content": "{\n  \"extends\": \"@vue/tsconfig/tsconfig.node.json\",\n  \"include\": [\"vite.config.*\", \"vitest.config.*\", \"cypress.config.*\"],\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"types\": [\"node\"]\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"@vue/tsconfig/tsconfig.web.json\",\n  \"include\": [\"env.d.ts\", \"src/**/*\", \"src/**/*.vue\"],\n  \"compilerOptions\": {\n    \"baseUrl\": \".\"\n  },\n\n  \"references\": [\n    {\n      \"path\": \"./tsconfig.config.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "vite.config.mts",
    "content": "import { fileURLToPath, URL } from \"node:url\"\n\nimport { defineConfig } from \"vite\"\nimport vue from \"@vitejs/plugin-vue\"\nimport postcssPresetEnv from \"postcss-preset-env\"\nimport styleInject from \"@senojs/rollup-plugin-style-inject\"\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [\n    vue(),\n    styleInject({\n      insertAt: \"top\"\n    })\n  ],\n  css: {\n    postcss: {\n      plugins: [postcssPresetEnv()]\n    }\n  },\n  build: {\n    lib:\n      process.env.NODE_ENV === \"production\"\n        ? {\n            entry: fileURLToPath(\n              new URL(\"src/vue-ganttastic.ts\", import.meta.url)\n            ),\n            name: \"VueGanttastic\",\n            fileName: \"vue-ganttastic\"\n          }\n        : undefined,\n    outDir: process.env.NODE_ENV === \"production\" ? \"lib\" : \"dist\",\n    rollupOptions: {\n      // make sure to externalize deps that shouldn't be bundled\n      // into the library\n      external: [\"vue\", \"dayjs\"],\n      output: {\n        // Provide global variables to use in the UMD build\n        // for externalized deps\n        globals: {\n          vue: \"Vue\",\n          dayjs: \"dayjs\"\n        },\n        exports: \"named\"\n      }\n    }\n  }\n})\n"
  }
]