npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@iccandle/vuejs-widget

v0.2.0

Published

Vue scanner overlay for TradingView Charting Library — ICCandle pattern search, remote theming, and plugin iframe integration.

Readme

@iccandle/vuejs-widget

Vue 3 scanner overlay for an existing TradingView Charting Library widget. It adds ICCandle’s draggable scanner popup, pattern search, replay of predicted candles, and a results embed.

Published as ESM and CommonJS. Component styles are bundled and injected at runtime — no separate CSS import.

Install

npm install @iccandle/vuejs-widget
# or
pnpm add @iccandle/vuejs-widget

vue ^3.5.0 is a peer dependency. Install it in your app. axios is a runtime dependency of this package.

Prerequisites

  • Vue 3.5+
  • TradingView Charting Library — obtain it under your own license, host the static assets (for example /charting_library/), and load it at runtime via library_path. This package does not ship the charting library.
  • A results iframe (or equivalent) that loads ICCandle’s embed app. Scan/tracker actions require the user to sign in inside that embed; the widget stores the session as iccandle_token in localStorage.

Quick start

<script setup lang="ts">
import { ref, shallowRef, watch } from "vue";
import type { IChartingLibraryWidget } from "charting_library/charting_library";
import {
  WidgetIccandle,
  WIDGET_RESULT_URL,
  handleResultIframeLoad,
} from "@iccandle/vuejs-widget";

const chartWidget = shallowRef<IChartingLibraryWidget | null>(null);
const language = "en" as const;
const theme = "dark" as const;

const iframeSrc = ref(`${WIDGET_RESULT_URL}/${language}?theme=${theme}&header=true`);
const iframeLoaded = ref(false);
const resultIframeRef = ref<HTMLIFrameElement | null>(null);
const resultIframeBox = { current: null as HTMLIFrameElement | null };

watch(
  resultIframeRef,
  (el) => {
    resultIframeBox.current = el;
  },
  { immediate: true },
);

function handleSubmit(src: string) {
  iframeSrc.value = src;
}

function handleIframeLoad() {
  iframeLoaded.value = true;
  handleResultIframeLoad(resultIframeRef.value);
}
</script>

<template>
  <div class="iccandle-selector-widget__container">
    <div class="iccandle-selector-widget__chart-pane">
      <WidgetIccandle
        :chart-widget="chartWidget"
        :submit-callback="handleSubmit"
        :theme="theme"
        :language="language"
        :iframe-loaded="iframeLoaded"
        :result-iframe-ref="resultIframeBox"
      >
        <!-- Bootstrap TradingView here and assign chartWidget when ready -->
        <div id="tv_chart_container" style="height: 100%" />
      </WidgetIccandle>
    </div>
    <iframe
      ref="resultIframeRef"
      :src="iframeSrc"
      class="iccandle-selector-widget__iframe"
      title="ICCandle results"
      @load="handleIframeLoad"
    />
  </div>
</template>

Replace the chart placeholder with your TradingView initialization and pass the IChartingLibraryWidget instance when the widget is created (typically right after new widget(options)).

Usage

1. Host the Charting Library

Copy the TradingView Charting Library build into a path your app can serve as static files (for example public/charting_library/ in Vite). Point library_path at that URL. The library is not bundled inside @iccandle/vuejs-widget.

2. Bootstrap TradingView with replay support

Wrap your datafeed with withPlayChart so the widget can inject predicted bars during replay. Register getCustomIndicators so those bars render as generated-candle studies:

import { onMounted, onBeforeUnmount, ref, shallowRef } from "vue";
import type {
  ChartingLibraryWidgetOptions,
  IChartingLibraryWidget,
  ResolutionString,
} from "charting_library/charting_library";
import { widget } from "charting_library/charting_library";
import { withPlayChart, getCustomIndicators } from "@iccandle/vuejs-widget";

const LIBRARY_PATH = "/charting_library/";

const containerRef = ref<HTMLDivElement | null>(null);
const chartWidget = shallowRef<IChartingLibraryWidget | null>(null);

onMounted(() => {
  const el = containerRef.value;
  if (!el) return;

  const options: ChartingLibraryWidgetOptions = {
    container: el,
    library_path: LIBRARY_PATH,
    symbol: "EURUSD",
    interval: "60" as ResolutionString,
    datafeed: withPlayChart(yourDatafeed),
    locale: "en",
    autosize: true,
    drawings_access: {
      type: "black",
      tools: [{ name: "Date Range" }],
    },
    custom_indicators_getter: () => getCustomIndicators("dark"),
  };

  const tv = new widget(options);
  chartWidget.value = tv;

  onBeforeUnmount(() => {
    try {
      tv.remove();
    } catch {
      /* no-op */
    }
    chartWidget.value = null;
  });
});

withPlayChart also accepts a factory plus its arguments: withPlayChart(createDatafeed, arg1, arg2).

You must supply a valid datafeed, symbol, interval, locale, and any other options required by your TradingView license.

3. Wrap the chart with WidgetIccandle

The component must wrap the same subtree that contains the chart container so the scanner overlay positions correctly. Pass null for chartWidget until the instance is ready.

<WidgetIccandle
  :chart-widget="chartWidget"
  :submit-callback="handleSubmit"
  theme="dark"
  language="en"
  :iframe-loaded="iframeLoaded"
  :result-iframe-ref="resultIframeBox"
  :available-intervals="['1', '5', '15', '30', '60']"
>
  <div ref="containerRef" style="height: 100%; min-height: 400px" />
</WidgetIccandle>

4. Handle the results iframe URL

After a successful scan, submitCallback receives a full HTTPS URL for the ICCandle embed. Typical query parameters include symbol, reference resolution, scan resolution, candle cache id (cid), time window (from / to), theme, and optional filters (fs, period, model, temp).

Split pane (recommended) — keep an iframe beside the chart and update its src:

const submitCallback = (nextSrc: string) => {
  iframeSrc.value = nextSrc;
};

Open in a new tab

submitCallback: (iframeSrc) => {
  window.open(iframeSrc, "_blank", "noopener,noreferrer");
};

On iframe load, call handleResultIframeLoad(iframe) so the embed knows the parent origin (required for sign-in to write iccandle_token) and so a Stripe return of ?payment=success can refresh the subscription without a full reload.

result-iframe-ref is a mutable { current } box, not a Vue ref. Sync it from the iframe element:

const resultIframeRef = ref<HTMLIFrameElement | null>(null);
const resultIframeBox = { current: null as HTMLIFrameElement | null };

watch(resultIframeRef, (el) => {
  resultIframeBox.current = el;
}, { immediate: true });

Sign-in

Scan and Pattern Tracker require localStorage.iccandle_token. The results iframe posts auth.signIn / auth.signOut; the widget listens and stores or clears the token. Until the user signs in, those actions show a login prompt.

Theme

| theme | Behavior | | ------- | -------- | | "light" (default) | Light scanner chrome and embed theme. | | "dark" | Dark scanner chrome; adds .iccandle-dark on the root. | | "system" | Follows prefers-color-scheme. |

The root uses CSS custom properties you can override: --iccandle-primary, --iccandle-border, --iccandle-text, --iccandle-background, --iccandle-primary-gradient-end, --iccandle-font.

Language

language accepts "en" | "zh" | "vi" | "th" | "ko" | "ja" | "mn" | "ru". Unknown values fall back to "en". The value is used for scanner copy and is forwarded into embed URLs.

Layout helpers

Injected CSS includes split-pane classes used in the demo:

| Class | Role | | ----- | ---- | | .iccandle-selector-widget__container | Flex row (stacks below 1024px). --chart-pane-size defaults to 60%. | | .iccandle-selector-widget__chart-pane | Chart column. | | .iccandle-selector-widget__resize-handle | Drag handle; add --stacked for the stacked layout. | | .iccandle-selector-widget__iframe | Results pane. |

Full working example

See src/App.vue, src/tradingview/TradingviewChart.vue, and src/tradingview/TradingviewChartContainer.vue in this repository.

API

Exports

| Name | Kind | Description | | ---- | ---- | ----------- | | WidgetIccandle | Component | Scanner overlay around your chart subtree. | | WidgetIccandleProps | Type | Public props of WidgetIccandle. | | WidgetLanguage | Type | Supported UI languages. | | withPlayChart | Function | Wrap a TradingView datafeed (or factory) so replay can inject bars and block live ticks. | | getCustomIndicators | Function | Returns custom studies used to draw generated / predicted candles. Pass "light" or "dark". | | GeneratedCandlesTheme | Type | "light" | "dark" for getCustomIndicators. | | handleResultIframeLoad | Function | Post parent origin (and optional payment-success) to the results iframe. | | WIDGET_RESULT_URL | Constant | Default embed origin: https://embed-iccandle-app.iccandle.ai. | | OPEN_PRICING_MESSAGE_TYPE | Constant | "open-pricing" postMessage type. | | postOpenPricingToEmbed | Function | Ask the results iframe to open pricing. Returns false if no contentWindow. | | postOpenPricingToParent | Function | Forward pricing to window.parent when this widget is itself embedded. | | postOpenPricingToWindow | Function | Post an open-pricing message to an arbitrary Window. | | OpenPricingMessage | Type | { type, theme?, language? }. |

WidgetIccandle props

| Prop | Type | Required | Default | Description | | ---- | ---- | -------- | ------- | ----------- | | chartWidget | IChartingLibraryWidget \| null | Yes | — | Live TradingView widget (null until ready). | | submitCallback | (iframeSrc: string) => void | Yes | — | Called with the embed URL after a scan (and for some pricing / news navigations). | | theme | "light" \| "dark" \| "system" | No | "light" | Scanner and forwarded embed theme. | | language | WidgetLanguage | No | "en" | Scanner UI language. | | onCloseResult | () => void | No | — | Called when the embed posts selector.closeResult. | | iframeLoaded | boolean | No | true | When false, Scan and Pattern Tracker are disabled. Set true after the results iframe has loaded. | | resultIframeRef | { current: HTMLIFrameElement \| null } \| null | No | — | Results iframe box. Receives open-pricing and chart-resolution postMessages. | | isShowScanButton | boolean | No | true | Show Scan inside the popup. | | isShowTrackerButton | boolean | No | true | Show Pattern Tracker inside the popup. | | isShowScannerPopup | boolean | No | true | Show the scanner popup. | | availableIntervals | string[] | No | — | Resolutions allowed when drawing a pattern date range from embed selection. | | onScanClick | () => void | No | — | Fired when the user clicks Scan, before login / config / scan logic. |

Default slot receives { chartRefs } (highlightBarsRef, generated-candle study ids). The same object is exposed on the component instance as chartRefs.

Behavior

  • Subscribes to chart readiness, resolution, symbol, visible range, drawings, and timescale-mark clicks.
  • Draws a date_range shape for the scan window; bar count and exported candles drive the scanner.
  • Posts selected candles to ICCandle’s cache, then calls submitCallback with the embed URL.
  • Listens for window message events from the embed (replay, auth, news, pattern selection, navigation, loading).
  • Clears persisted news mark keys (tv:selected-news-events, tv:clicked-news-event) when a scan starts.

Embed postMessage names

The widget handles JSON messages with a name (and optional data) from the results iframe:

| Name | Effect | | ---- | ------ | | chart.play | Replay / predicted candles on the chart. | | chart.stop | Stop replay and restore live ticks. | | chart.requestResolution | Re-post the current chart resolution to the iframe. | | selector.closeResult | Invoke onCloseResult. | | selector.loading | Toggle scanner loading state. | | auth.signIn | Store data.idToken as iccandle_token. | | auth.signOut | Remove iccandle_token. | | news.eventClicked | Draw event marks / target window on the chart. | | news.back / news.backToSimilarEvents | Clear event overlay / replay. | | pattern.classicPatternSelected / pattern.custom_pattern_selected | Draw the compared pattern’s date range. | | pattern.clearClassicPatternSelected / pattern.clear_custom_pattern_selected | Clear pattern overlay. | | nav.click | Handle embed navigation (clears date range on /news routes). |

The host → embed helpers use a different shape: { type: "parent-origin" | "payment-success" | "open-pricing" | "chart-resolution", ... }.

Optional: timescale marks (news / events)

If your datafeed implements getTimescaleMarks, you can surface stored events from localStorage (tv:selected-news-events, tv:clicked-news-event) as marks on the time axis. See src/lib/data-feed.ts in this repo.

Development (this repo)

| Script | Command | Purpose | | ------ | ------- | ------- | | Dev demo | pnpm dev | Vite app with a local charting library. | | Library build | pnpm build | Emits dist/ (ESM, CJS, injected CSS, declarations). | | App build | pnpm build:app | Full demo app build. |

prepublishOnly runs build before publish.

License

MIT. TradingView Charting Library is subject to its own license from TradingView.