npm package: @lipme/gene-map-component
Description: Vue Component to display genes.
Author: Walid SBYI
Latest version: 0.2.2

# gene-map-component

Vue Component to display genes.

## Overview

`GeneMapComponent` is a Vue component designed to visualize gene data in a structured and interactive manner. It supports features like compressed views, pagination, highlighting regions, and exporting visualizations as images.

## Features

- Visualize gene data with customizable labels, tooltips, and links.
- Support for compressed and paginated views.
- Highlight specific regions of interest.
- Export the visualization as an image.
- Fully configurable dimensions and layout.

## Props

### `label`

- **Type**: `(x: GeneData) => string`
- **Description**: A function to define how each gene should be labeled.
- **Default**: Returns the `Name` attribute of the gene.
- **Example**:

  ```typescript
  label: (gene) => gene.attributes!.Name![0] || 'Unnamed Gene'
  ```

### `linksGenerator`

- **Type**: `(x: GeneData) => string | undefined`
- **Description**: A function to generate a URL for each gene, used for redirection when a gene is clicked.
- **Default**: `undefined`
- **Example**:

  ```typescript
  linksGenerator: (gene) => `https://example.com/gene/${gene.attributes!.ID![0]}`
  ```

### `tooltip`

- **Type**: `(x: GeneData) => string`
- **Description**: A function to define the tooltip content for each gene.
- **Default**: Returns the `Alias` attribute of the gene if available.
- **Example**:

  ```typescript
  tooltip: (gene) => `Gene: ${gene.attributes!.Alias![0]}`
  ```

### `selection`

- **Type**: `RegionInputType | PaginationInputType`
- **Description**: Specifies the region or pagination configuration for gene display.
- **Required**: Yes
- **Types**:

  - `RegionInputType`: For displaying a specific region

    ```typescript
    {
      seqID: string;
      start: number;
      end: number;
      compressed?: {
        offset: number;
      };
    }
    ```

  - `PaginationInputType`: For paginated display

    ```typescript
    {
      seqID: string
      index: number
      config: {
        numberOfRows: number
      }
    }
    ```

- **Examples**:

  - Region view:

    ```typescript
    selection: {
      seqID: 'chromosome1',
      start: 1000,
      end: 5000,
      compressed: { offset: 50 }
    }
    ```

  - Paginated view:

    ```typescript
    selection: {
      seqID: 'chromosome1',
      index: 2,
      config: { numberOfRows: 8 }
    }
    ```

### `fileUrl`

- **Type**: `string`
- **Description**: The HTTP source of the GFF3 file containing gene data.
- **Example**:

  ```typescript
  fileUrl: 'https://example.com/data/genes.gff3'
  ```

### `showLegend`

- **Type**: `boolean`
- **Description**: Whether to display the legend in the visualization.
- **Default**: `true`

### `indexUrl`

- **Type**: `string | undefined`
- **Description**: The index file URL for the GFF3 file. Defaults to the `fileUrl` with `.tbi` appended.
- **Default**: `undefined`

### `colors`

- **Type**: `ColorService`
- **Description**: A service to manage color schemes for the visualization.
- **Example**:

  ```typescript
  import { ColorService } from '@lipme/gffcolors'
  const colors = new ColorService()
  ```

### `highlight`

- **Type**: `Array<[number, number]> | undefined`
- **Description**: An array of regions to highlight in the visualization.
- **Default**: `undefined`
- **Example**:

  ```typescript
  highlight: [
    [1000, 2000],
    [3000, 4000]
  ]
  ```

### `config`

- **Type**: `{ width: number; height: number; rowSize: number }`
- **Description**: Configuration for the visualization layout.
  - `width`: Width of the visualization in pixels.
  - `height`: Height of the visualization in pixels.
  - `rowSize`: Size of each level.
- **Default**: `{ width: 1000, height: 800, rowSize: 30000 }`
- **Example**:

  ```typescript
  config: { width: 1200, height: 900, rowSize: 20000 }
  ```

## Emits

### `selectGene`

- **Type**: `(value: GeneData) => void`
- **Description**: Emitted when a gene is selected (clicked).
- **Example**:

  ```html
  <GeneMapComponent @selectGene="onGeneSelect" />
  <script>
    function onGeneSelect(gene) {
      console.log('Selected gene:', gene)
    }
  </script>
  ```

## Slots

### `screenshot`

- **Props**: `{ screenshotFunction: () => void }`
- **Description**: Slot to provide a custom button or UI for exporting the visualization as an image.
- **Example**:

  ```html
  <template #screenshot="{ screenshotFunction }">
    <button @click="screenshotFunction">Export as Image</button>
  </template>
  ```

## Examples

### Basic Region View

```vue
<template>
  <GeneMapComponent
    :fileUrl="'https://example.com/data/genes.gff3'"
    :colors="colorService"
    :selection="{
      seqID: 'chromosome1',
      start: 1000,
      end: 5000
    }"
  />
</template>

<script setup>
import { ColorService } from '@lipme/gffcolors'
const colorService = new ColorService()
</script>
```

### Paginated View

```vue
<template>
  <GeneMapComponent
    :fileUrl="'https://example.com/data/genes.gff3'"
    :colors="colorService"
    :selection="{
      seqID: 'chromosome1',
      index: 2,
      config: { numberOfRows: 8 }
    }"
    :config="{ width: 1200, height: 800, rowSize: 10000 }"
  />
</template>

<script setup>
import { ColorService } from '@lipme/gffcolors'
const colorService = new ColorService()
</script>
```

### Compressed View with Highlighting

```vue
<template>
  <GeneMapComponent
    :fileUrl="'https://example.com/data/genes.gff3'"
    :colors="colorService"
    :selection="{
      seqID: 'chromosome1',
      start: 1000,
      end: 5000,
      compressed: { offset: 50 }
    }"
    :highlight="[
      [1500, 2500],
      [3000, 4000]
    ]"
    :config="{ width: 1200, height: 800, rowSize: 10000 }"
  />
</template>

<script setup>
import { ColorService } from '@lipme/gffcolors'
const colorService = new ColorService()
</script>
```

### Custom Gene Labeling and Export

```vue
<template>
  <GeneMapComponent
    :fileUrl="'https://example.com/data/genes.gff3'"
    :colors="colorService"
    :selection="{
      seqID: 'chromosome1',
      start: 1000,
      end: 5000
    }"
    :label="customLabel"
    :tooltip="customTooltip"
    :linksGenerator="generateLink"
  >
    <template #screenshot="{ screenshotFunction }">
      <button @click="screenshotFunction">Export as Image</button>
    </template>
  </GeneMapComponent>
</template>

<script setup>
import { ColorService } from '@lipme/gffcolors'
const colorService = new ColorService()

function customLabel(gene) {
  return gene.attributes?.locus_tag?.[0] || gene.attributes?.Name?.[0] || 'Unknown'
}

function customTooltip(gene) {
  return `${gene.attributes?.Name?.[0]} - ${gene.attributes?.product?.[0] || 'No product info'}`
}

function generateLink(gene) {
  return `https://example.com/gene/${gene.attributes?.ID?.[0]}`
}
</script>
```

## Recommended IDE Setup

[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).

## Type Support for `.vue` Imports in TS

TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.

## Customize Configuration

See [Vite Configuration Reference](https://vitejs.dev/config/).

## Project Setup

```sh
npm install
```

### Compile and Hot-Reload for Development

```sh
npm run dev
```

### Type-Check, Compile and Minify for Production

```sh
npm run build
```

### Run Unit Tests with [Vitest](https://vitest.dev/)

```sh
npm run test:unit
```

### Run End-to-End Tests with [Cypress](https://www.cypress.io/)

```sh
npm run test:e2e:dev
```

This runs the end-to-end tests against the Vite development server.
It is much faster than the production build.

But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments):

```sh
npm run build
npm run test:e2e
```

### Lint with [ESLint](https://eslint.org/)

```sh
npm run lint
```