Vuejs-Vue trend chart 0.15.3: vue-trend-chart - Simple trend charts for Vue.js

icon
Latest Release: 0.15.3
Vue Trend

? Installation

npm i vue-trend-chart

? Usage

import Vue from "vue";
import TrendChart from "vue-trend-chart";

Vue.use(TrendChart);

Example:

<TrendChart
  :datasets="[
    {
      data: [10, 50, 20, 100, 40, 60, 80],
      smooth: true,
      fill: true
    }
  ]"
  :grid="{
     verticalLines: true,
     horizontalLines: true
  }"
  :labels="{
     xLabels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
     yLabels: 5
  }"
  :min="0">
</TrendChart>

? Props

datasets

Required
Type: Array

Array of objects with properties for each dataset.

grid

Type: Object

Grid properties

labels

Type: Object

Labels properties

min

Type: Number
Default: min value from datasets

max

Type: Number
Default: max value from datasets

padding

Type: String
Default: "5"

If you set a large stroke-width on your lines, you may notice that it gets "cropped" towards the edges. It's similar to "padding" CSS property but without specifying units.

Examples:
"5" apply to all four sides
"5 10" vertical | horizontal
"5 15 10" top | horizontal | bottom
"5 10 15 20" top | right | bottom | left

interactive

Type: Boolean
Default: false

Allows to set onmousemove interaction. Set to true to enable.

Events

mouse-move

Callback function for onmouseover interaction.
Receives an object {index: Number, data: Array} parameter based on current active line.
This function has no effect if interactive isn't set to true.

? Dataset Props

Chart line (curve) properties

data

Type: Number|Object

Example: [70, 100, 400, 180, 100] or [{ value: 70 }, { value: 100 }, { value: 400 }, { value: 180 }, { value: 100 }]
For object type you can also add other properties to use them in interactive mode.

className

Type: String

Allows to append custom class to chart line for future styling.

smooth

Type: Boolean
Default: false

Allows the peaks to be 'rounded' out.

stroke

Type: Boolean
Default: true

If false, the line is not drawn for this dataset.

fill

Type: Boolean
Default: false

Allows to fill the area under the line. Set to true to enable.

showPoints

Type: Boolean
Default: false

Allows to show points. Set to true to enable.

#️⃣ Grid Props

verticalLines

Type: Boolean
Default: false

Allows to show vertical gridlines. Set to true to enable.

verticalLinesNumber

Type: Number
Default: number of xLabels

Allows to set custom number of vertical gridlines.
This prop has no effect if verticalLines isn't set to true.

horizontalLines

Type: Boolean
Default: false

Allows to show horizontal gridlines. Set to true to enable.

horizontalLinesNumber

Type: Number
Default: number of yLabels

Allows to set custom number of horizontal gridlines.
This prop has no effect if horizontalLines isn't set to true.

? Labels Props

xLabels

Type: Array

X axis labels.
Example: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

yLabels

Type: Number

Number of Y axis labels. Labels text is based on data values.

yLabelsTextFormatter

Type: Function

Allows to format Y axis labels text.
Example: val => "$" + Math.round(val * 100) / 100.
This function has no effect if yLabels prop has no value.

? Styling

Just use CSS to style your charts.

Here is an example of a tree structure with available class names:

<svg class="vtc">
  <g class="grid">
    <g class="vertical">
      <line class="line"></line>
      ...
    </g>
    <g class="horizontal">
      <line class="line"></line>
      ...
    </g>
  </g>

  <g class="labels">
    <g class="x-labels">
      <g class="label">
        <text></text>
      </g>
      ...
    </g>
    <g class="y-labels">
      <g class="label">
        <text></text>
      </g>
      ...
    </g>
  </g>

  <g class="curve">
    <path class="fill"></path>
    <path class="stroke"></path>
    <g class="points">
      <circle class="point"></circle>
      ...
    </g>
  </g>
  ...

  <line class="active-line"></line>
</svg>

? Development

npm install
npm run dev

? Contributing

Pull requests are welcome!

? License

MIT

Comments

  • Incorrect formatting xLabels
    Incorrect formatting xLabels

    May 19, 2020

    when I move data label from data()

      data() {
        return {
          ...
          labels: {
            xLabels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
            yLabels: 5,
            yLabelsTextFormatter: val => Math.round(val * 100) / 100
          },
    

    to mounted() like:

      mounted() {
        ...
        this.labels = {        
          xLabels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
          yLabels: 5,
          yLabelsTextFormatter: val => Math.round(val * 100) / 100}
      }
    

    then the bottom label (xLabels) overlaps the chart (changes position/moves up)

    image

    https://codepen.io/czelsa/pen/gOaQzbP

    bug 
    Reply
  • Graph sizes incorrectly in Electron app when programmatically resizing window
    Graph sizes incorrectly in Electron app when programmatically resizing window

    May 20, 2020

    In an Electron app, I'm loading up a vue-trend-chart in a Vuetify full-screen dialog.

    Initially, I had an issue with the graph loading up at what appears to be a minimum size. I think this was related to displaying it in a transitioning full-screen dialogue where the dialog size was undefined so the graph SVG didn't scale to fit properly. I remedied this by redrawing the graph once the dialog was opened.

    Then I re-encountered the issue when programmatically setting the window size in Electron. The graph looks fine by default: image and then when you close the dialog containing the graph, press a button to resize the current window, and reopen the dialog to view the graph: image

    EDIT: At this point, manually resizing the electron app window just a pixel will fix the graph and make it display properly, filling up the container size again.

    I'm not sure what the problem is here, I know SVG scaling is more awkward than say just having an image.

    Is it possible to provide a function to redraw the SVG's or any other way to combat this?

    Windows 10 Electron 7.3.0 Vue-Trend-Chart 0.15.2

    enhancement 
    Reply
  • Needs Typescript support
    Needs Typescript support

    Mar 1, 2021

    When using Typescript I get this error: Could not find a declaration file for module 'vue-trend-chart'. '/node_modules/vue-trend-chart/dist/vue-trend-chart.common.js' implicitly has an 'any' type.

    enhancement 
    Reply
  • Vue 3 Support
    Vue 3 Support

    Jun 21, 2021

    Tried to use it with Vue 3. Getting the following error:

    vue-trend-chart.esm.js?21e9:723 Uncaught (in promise) TypeError: h is not a function
        at Proxy.render (vue-trend-chart.esm.js?21e9:723)
        at renderComponentRoot (runtime-core.esm-bundler.js?9e79:846)
        at componentEffect (runtime-core.esm-bundler.js?9e79:4280)
        at reactiveEffect (reactivity.esm-bundler.js?0a2b:42)
        at effect (reactivity.esm-bundler.js?0a2b:17)
        at setupRenderEffect (runtime-core.esm-bundler.js?9e79:4263)
        at mountComponent (runtime-core.esm-bundler.js?9e79:4222)
        at processComponent (runtime-core.esm-bundler.js?9e79:4182)
        at patch (runtime-core.esm-bundler.js?9e79:3791)
        at mountChildren (runtime-core.esm-bundler.js?9e79:3975)
    render @ vue-trend-chart.esm.js?21e9:723
    
    enhancement 
    Reply
  • Outdated Axios Peer-Dependency
    Outdated Axios Peer-Dependency

    Jul 13, 2021

    Hey! I noticed that the package lists an outdated version of axios as a peer-dependency. Since some time now npm will install (and thus require) those by default - meaning that having vue-trend-chart anywhere in the dependency-tree prevents users from updating axios altogether.

    npm ERR! Found: [email protected]
    npm ERR! node_modules/axios
    npm ERR!   dev [email protected]"^0.21.1" from the root project
    npm ERR! 
    npm ERR! Could not resolve dependency:
    npm ERR! peer [email protected]"^0.18.0" from [email protected]
    npm ERR! node_modules/vue-trend-chart
    npm ERR!   [email protected]"^0.15.3" from the root project
    npm ERR! 
    npm ERR! Fix the upstream dependency conflict, or retry
    npm ERR! this command with --force, or --legacy-peer-deps
    npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
    

    Workaround:

    npm install [email protected] --save --legacy-peer-deps
    

    Since axios seems to only be included for the demo I'd suggest creating a separate package.json for that.

    Cheers!

    dependencies 
    Reply
  • Is it possible to specify the exact position of the horizontal lines?
    Is it possible to specify the exact position of the horizontal lines?

    Sep 15, 2021

    I would like to show a single horizontal line showing the average value across the data.

    Is it possible to configure the position of the horizontal line to do this?

    If not, would you be open to a pull request to support this? Can you provide any guidance on how best to achieve this?

    enhancement 
    Reply
  • Bump follow-redirects from 1.13.0 to 1.14.7
    Bump follow-redirects from 1.13.0 to 1.14.7

    Jan 13, 2022

    Bumps follow-redirects from 1.13.0 to 1.14.7.

    Commits
    • 2ede36d Release version 1.14.7 of the npm package.
    • 8b347cb Drop Cookie header across domains.
    • 6f5029a Release version 1.14.6 of the npm package.
    • af706be Ignore null headers.
    • d01ab7a Release version 1.14.5 of the npm package.
    • 40052ea Make compatible with Node 17.
    • 86f7572 Fix: clear internal timer on request abort to avoid leakage
    • 2e1eaf0 Keep Authorization header on subdomain redirects.
    • 2ad9e82 Carry over Host header on relative redirects (#172)
    • 77e2a58 Release version 1.14.4 of the npm package.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Bump js-yaml from 3.12.1 to 3.13.1
    Bump js-yaml from 3.12.1 to 3.13.1

    Jun 5, 2019

    Bumps js-yaml from 3.12.1 to 3.13.1.

    Changelog

    Sourced from js-yaml's changelog.

    3.13.1 / 2019-04-05

    • Fix possible code execution in (already unsafe) .load(), #480.

    3.13.0 / 2019-03-20

    • Security fix: safeLoad() can hang when arrays with nested refs used as key. Now throws exception for nested arrays. #475.

    3.12.2 / 2019-02-26

    • Fix noArrayIndent option for root level, #468.
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot ignore this [patch|minor|major] version will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language
    dependencies 
    Reply
  • on:mouseMove not working
    on:mouseMove not working

    Nov 12, 2019

    Hi there,

    I'm not sure what if I'm doing something wrong (because your codepen samples don't have this problem) or if this is a bug, but on:mouseMove event isn't being called.

    I suspect it's because of this: https://vuejs.org/v2/guide/components-custom-events.html#Event-Names

    Additionally, v-on event listeners inside DOM templates will be automatically transformed to lowercase (due to HTML’s case-insensitivity), so v-on:myEvent would become v-on:myevent – making myEvent impossible to listen to.

    Vue js hints in console (using non minified version of vue.js) seem to confirm this:

    [Vue tip]: Event "mousemove" is emitted in component but the handler is registered for "mouseMove". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "mouse-move" instead of "mouseMove".

    The fix for me seems to be change this

            this.$emit(
              "mouseMove",  ////// this should be lowercase to "mousemove"
              this.activeLineParams ? Object.assign({}, this.activeLineParams, {data: data}) : null
            );
    
    bug 
    Reply
  • Bump fstream from 1.0.11 to 1.0.12
    Bump fstream from 1.0.11 to 1.0.12

    Jun 1, 2019

    Bumps fstream from 1.0.11 to 1.0.12.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot ignore this [patch|minor|major] version will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language
    dependencies 
    Reply
  • Changing xLabels doesn't update the HTML
    Changing xLabels doesn't update the HTML

    Aug 22, 2019

    When changing xLabels, by changing it on TrendChartLabels directly or via TrendChart, the HTML doesn't get rerendered.

    I build a workaround by calling $forceReload everytime I update it, but there has to be a better solution.

    good first issue 
    Reply
  • Bump acorn from 6.1.0 to 6.4.1
    Bump acorn from 6.1.0 to 6.4.1

    Apr 8, 2020

    Bumps acorn from 6.1.0 to 6.4.1.

    Commits
    • 9a2e9b6 Mark version 6.4.1
    • 90a9548 More rigorously check surrogate pairs in regexp validator
    • df0cf1a Mark version 6.4.0
    • 5303412 Also export Parser via Parser.acorn
    • efe273e give token types and etc to plugins
    • ac6decb Mark version 6.3.0
    • 7e9817d Allow sourceType: module even with ecmaVersion < 6
    • e2b8cc0 Fix broken parsing of new expressions when allowReserved=="never"
    • 1555c52 Update acorn.d.ts
    • 77c20fa Mark version 6.2.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Can't start the y-axis range from a defined value except 0
    Can't start the y-axis range from a defined value except 0

    May 5, 2020

    I want to modify the y-axis range, want to start it from a defined value like 50 or 100. I tried using yLabelsTextFormatter but it's not plotting the graph in a correct way (means taking the y-axis from 0 only).

    Can you please suggest is there any way?

    Reply
  • Bump url-parse from 1.5.1 to 1.5.3
    Bump url-parse from 1.5.1 to 1.5.3

    Sep 14, 2021

    Bumps url-parse from 1.5.1 to 1.5.3.

    Commits
    • ad44493 [dist] 1.5.3
    • c798461 [fix] Fix host parsing for file URLs (#210)
    • 201034b [dist] 1.5.2
    • 2d9ac2c [fix] Sanitize only special URLs (#209)
    • fb128af [fix] Use 'null' as origin for non special URLs
    • fed6d9e [fix] Add a leading slash only if the URL is special
    • 94872e7 [fix] Do not incorrectly set the slashes property to true
    • 81ab967 [fix] Ignore slashes after the protocol for special URLs
    • ee22050 [ci] Use GitHub Actions
    • d2979b5 [fix] Special case the file: protocol (#204)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Bump color-string from 1.5.4 to 1.6.0
    Bump color-string from 1.5.4 to 1.6.0

    Sep 14, 2021

    Bumps color-string from 1.5.4 to 1.6.0.

    Release notes

    Sourced from color-string's releases.

    1.6.0

    Minor release 1.6.0

    • #55 - Add support for space-separated HSL

    Thanks @​htunnicliff for the contribution :)

    1.5.5 (Patch/Security Release) - hwb() ReDos patch (low-severity)

    Release notes copied verbatim from the commit message, which can be found here: 0789e21284c33d89ebc4ab4ca6f759b9375ac9d3

    Discovered by Yeting Li, c/o Colin Ife via Snyk.io.
    

    A ReDos (Regular Expression Denial of Service) vulnerability was responsibly disclosed to me via email by Colin on Mar 5 2021 regarding an exponential time complexity for linearly increasing input lengths for hwb() color strings.

    Strings reaching more than 5000 characters would see several milliseconds of processing time; strings reaching more than 50,000 characters began seeing 1500ms (1.5s) of processing time.

    The cause was due to a the regular expression that parses hwb() strings - specifically, the hue value - where the integer portion of the hue value used a 0-or-more quantifier shortly thereafter followed by a 1-or-more quantifier.

    This caused excessive backtracking and a cartesian scan, resulting in exponential time complexity given a linear increase in input length.

    Thank you Yeting Li and Colin Ife for bringing this to my attention in a secure, responsible and professional manner.

    A CVE will not be assigned for this vulnerability.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • vuejs3 compatibility
    vuejs3 compatibility

    Jan 22, 2021

    since chartjs is not compatible with vue3 vue-trend-chart also has some problems when it's used with vue3 like the h function, i solved the h function issue but still see a lot of problems , is there any future fix for this , &thank you

    enhancement 
    Reply
  • Upgrade axios dependency
    Upgrade axios dependency

    Feb 26, 2021

    Please upgrade axios dependency or release the version pin.

    Reply