Skip to content

Commit

Permalink
Merge pull request #1652 from tradingview/v4.2-attribution-logo
Browse files Browse the repository at this point in the history
Attribution logo
  • Loading branch information
SlicedSilver authored Jul 26, 2024
2 parents 6e70f54 + b84e063 commit 2ce43a3
Show file tree
Hide file tree
Showing 273 changed files with 460 additions and 163 deletions.
8 changes: 4 additions & 4 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ module.exports = [
{
name: 'CJS',
path: 'dist/lightweight-charts.production.cjs',
limit: '48.35 KB',
limit: '49.28 KB',
},
{
name: 'ESM',
path: 'dist/lightweight-charts.production.mjs',
limit: '48.28 KB',
limit: '49.21 KB',
},
{
name: 'Standalone-ESM',
path: 'dist/lightweight-charts.standalone.production.mjs',
limit: '50.00 KB',
limit: '50.93 KB',
},
{
name: 'Standalone',
path: 'dist/lightweight-charts.standalone.production.js',
limit: '50.04 KB',
limit: '50.97 KB',
},
];
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ This software incorporates several parts of tslib (<https://github.com/Microsoft
This license requires specifying TradingView as the product creator.
You shall add the "attribution notice" from the NOTICE file and a link to <https://www.tradingview.com/> to the page of your website or mobile application that is available to your users.
As thanks for creating this product, we'd be grateful if you add it in a prominent place.
You can use the [`attributionLogo`](https://tradingview.github.io/lightweight-charts/docs/api/interfaces/LayoutOptions#attributionLogo) chart option for displaying an appropriate link to <https://www.tradingview.com/> on the chart itself, which will satisfy the link requirement.

[demo-url]: https://www.tradingview.com/lightweight-charts/

Expand Down
1 change: 1 addition & 0 deletions src/api/options/layout-options-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export const layoutOptionsDefaults: LayoutOptions = {
textColor: '#191919',
fontSize: 12,
fontFamily: defaultFontFamily,
attributionLogo: true,
};
84 changes: 84 additions & 0 deletions src/gui/attribution-logo-widget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { colorStringToGrayscale } from '../helpers/color';

import { IChartWidgetBase } from './chart-widget';

type LogoTheme = 'dark' | 'light';

const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 19" width="35" height="19" fill="none"><g fill-rule="evenodd" clip-path="url(#a)" clip-rule="evenodd"><path fill="var(--stroke)" d="M2 0H0v10h6v9h21.4l.5-1.3 6-15 1-2.7H23.7l-.5 1.3-.2.6a5 5 0 0 0-7-.9V0H2Zm20 17h4l5.2-13 .8-2h-7l-1 2.5-.2.5-1.5 3.8-.3.7V17Zm-.8-10a3 3 0 0 0 .7-2.7A3 3 0 1 0 16.8 7h4.4ZM14 7V2H2v6h6v9h4V7h2Z"/><path fill="var(--fill)" d="M14 2H2v6h6v9h6V2Zm12 15h-7l6-15h7l-6 15Zm-7-9a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/></g><defs><clipPath id="a"><path fill="var(--stroke)" d="M0 0h35v19H0z"/></clipPath></defs></svg>`;
const css = `a#tv-attr-logo{--fill:#131722;--stroke:#fff;position:absolute;left:10px;bottom:10px;height:19px;width:35px;margin:0;padding:0;border:0;z-index:3;}a#tv-attr-logo[data-dark]{--fill:#D1D4DC;--stroke:#131722;}`;

// This widget doesn't support dynamically responding to options changes
// because it is expected that the `attributionLogo` option won't be changed
// and this saves some bundle size.
export class AttributionLogoWidget {
private readonly _chart: IChartWidgetBase;
private readonly _container: HTMLElement;
private _element: HTMLAnchorElement | undefined = undefined;
private _cssElement: HTMLStyleElement | undefined = undefined;
private _theme: LogoTheme | undefined = undefined;
private _visible: boolean = false;

public constructor(container: HTMLElement, chart: IChartWidgetBase) {
this._container = container;
this._chart = chart;
this._render();
}

public update(): void {
this._render();
}

public removeElement(): void {
if (this._element) {
this._container.removeChild(this._element);
}
if (this._cssElement) {
this._container.removeChild(this._cssElement);
}
this._element = undefined;
this._cssElement = undefined;
}

private _shouldUpdate(): boolean {
return this._visible !== this._shouldBeVisible() || this._theme !== this._themeToUse();
}

private _themeToUse(): LogoTheme {
return colorStringToGrayscale(this._chart.options().layout.textColor) > 160 ? 'dark' : 'light';
}

private _shouldBeVisible(): boolean {
return this._chart.options().layout.attributionLogo;
}

private _getUTMSource(): string {
const url = new URL(location.href);
if (!url.hostname) {
// ignore local testing
return '';
}
return '&utm_source=' + url.hostname + url.pathname;
}

private _render(): void {
if (!this._shouldUpdate()) {
return;
}
this.removeElement();
this._visible = this._shouldBeVisible();
if (this._visible) {
this._theme = this._themeToUse();
this._cssElement = document.createElement('style');
this._cssElement.innerText = css;
this._element = document.createElement('a');
this._element.href = `https://www.tradingview.com/?utm_medium=lwc-link&utm_campaign=lwc-chart${this._getUTMSource()}`;
this._element.title = 'Charting by TradingView';
this._element.id = 'tv-attr-logo';
this._element.target = '_blank';
this._element.innerHTML = svg;
this._element.toggleAttribute('data-dark', this._theme === 'dark');
this._container.appendChild(this._cssElement);
this._container.appendChild(this._element);
}
}
}
11 changes: 11 additions & 0 deletions src/gui/pane-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { TouchMouseEventData } from '../model/touch-mouse-event-data';
import { IPaneRenderer } from '../renderers/ipane-renderer';
import { IPaneView } from '../views/pane/ipane-view';

import { AttributionLogoWidget } from './attribution-logo-widget';
import { createBoundCanvas, releaseCanvas } from './canvas-utils';
import { IChartWidgetBase } from './chart-widget';
import { drawBackground, drawForeground, DrawFunction, drawSourcePaneViews } from './draw-functions';
Expand Down Expand Up @@ -66,6 +67,7 @@ export class PaneWidget implements IDestroyable, MouseEventHandlers {
private _size: Size = size({ width: 0, height: 0 });
private _leftPriceAxisWidget: PriceAxisWidget | null = null;
private _rightPriceAxisWidget: PriceAxisWidget | null = null;
private _attributionLogoWidget: AttributionLogoWidget | null = null;
private readonly _paneCell: HTMLElement;
private readonly _leftAxisCell: HTMLElement;
private readonly _rightAxisCell: HTMLElement;
Expand Down Expand Up @@ -150,6 +152,7 @@ export class PaneWidget implements IDestroyable, MouseEventHandlers {
if (this._rightPriceAxisWidget !== null) {
this._rightPriceAxisWidget.destroy();
}
this._attributionLogoWidget = null;

this._topCanvasBinding.unsubscribeSuggestedBitmapSizeChanged(this._topCanvasSuggestedBitmapSizeChangedHandler);
releaseCanvas(this._topCanvasBinding.canvasElement);
Expand Down Expand Up @@ -182,6 +185,14 @@ export class PaneWidget implements IDestroyable, MouseEventHandlers {
}

this.updatePriceAxisWidgetsStates();

if (this._chart.paneWidgets().indexOf(this) === this._chart.paneWidgets().length - 1) {
this._attributionLogoWidget = this._attributionLogoWidget ?? new AttributionLogoWidget(this._paneCell, this._chart);
this._attributionLogoWidget.update();
} else {
this._attributionLogoWidget?.removeElement();
this._attributionLogoWidget = null;
}
}

public chart(): IChartWidgetBase {
Expand Down
4 changes: 4 additions & 0 deletions src/helpers/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ export function generateContrastColors(backgroundColor: string): ContrastColors
};
}

export function colorStringToGrayscale(backgroundColor: string): number {
return rgbaToGrayscale(colorStringToRgba(backgroundColor));
}

export function gradientColorAtPercent(topColor: string, bottomColor: string, percent: number): string {
const [topR, topG, topB, topA] = colorStringToRgba(topColor);
const [bottomR, bottomG, bottomB, bottomA] = colorStringToRgba(bottomColor);
Expand Down
14 changes: 14 additions & 0 deletions src/model/layout-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,18 @@ export interface LayoutOptions {
* @defaultValue `-apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif`
*/
fontFamily: string;

/**
* Display the TradingView attribution logo on the main chart pane.
*
* The licence for library specifies that you add the "attribution notice"
* from the NOTICE file to your code and a link to https://www.tradingview.com/ to
* the page of your website or mobile application that is available to your users.
* Using this attribution logo is sufficient for meeting this linking requirement.
* However, if you already fulfill this requirement then you can disable this
* attribution logo.
*
* @defaultValue true
*/
attributionLogo: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function generateData() {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container, { autoSize: true });
const chart = window.chart = LightweightCharts.createChart(container, { autoSize: true, layout: { attributionLogo: false } });

const series = chart.addCandlestickSeries();

Expand Down
1 change: 1 addition & 0 deletions tests/e2e/graphics/test-cases/add-series-after-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function generateData() {
function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container, {
height: 500, width: 600,
layout: { attributionLogo: false },
});

return new Promise(resolve => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });
const series = chart.addAreaSeries();
series.setData([
{ time: '1990-04-24', value: 0 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function generateData() {
function runTestCase(container) {
const chart = (window.chart = LightweightCharts.createChart(container, {
autoSize: true,
layout: { attributionLogo: false },
}));
const series = chart.addLineSeries();
series.setData(generateData());
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/graphics/test-cases/api/price-scale-width.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function runTestCase(container) {
leftPriceScale: {
visible: false,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries({ priceScaleId: 'overlay-scale' });
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/graphics/test-cases/api/series-data-by-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function checkSeries(series, data, compareItemsFn) {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });

const lineSeries = chart.addLineSeries();
checkSeries(
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/graphics/test-cases/api/series-markers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function compare(markers, seriesApiMarkers) {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });
const series = chart.addAreaSeries();
series.setData([
{ time: '1990-04-24', value: 0 },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });
const series = chart.addAreaSeries();
series.setData([
{ time: '1990-04-24', value: 0 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function runTestCase(container) {
leftPriceScale: {
visible: false,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function runTestCase(container) {
leftPriceScale: {
visible: false,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function runTestCase(container) {
leftPriceScale: {
visible: false,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function runTestCase(container) {
leftPriceScale: {
visible: false,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function runTestCase(container) {
rightPriceScale: {
ticksVisible: true,
},
layout: { attributionLogo: false },
});

const mainSeries = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function runTestCase(container) {
barSpacing: 40,
timeVisible: true,
},
layout: { attributionLogo: false },
});

const bar = chart.addBarSeries({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function runTestCase(container) {
barSpacing: 40,
timeVisible: true,
},
layout: { attributionLogo: false },
});

const candlestick = chart.addCandlestickSeries({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function runTestCase(container) {
},
mode: LightweightCharts.CrosshairMode.Normal,
},
layout: { attributionLogo: false },
});

const mainSeries = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function runTestCase(container) {
},
mode: LightweightCharts.CrosshairMode.Normal,
},
layout: { attributionLogo: false },
});

const mainSeries = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function generateData() {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });

const mainSeries = chart.addCandlestickSeries();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function generateData() {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });

const mainSeries = chart.addLineSeries();
mainSeries.setData(generateData());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function runTestCase(container) {
fixLeftEdge: true,
fixRightEdge: true,
},
layout: { attributionLogo: false },
});

const series = chart.addLineSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function runTestCase(container) {
fixLeftEdge: true,
fixRightEdge: true,
},
layout: { attributionLogo: false },
});

const mainSeries = chart.addCandlestickSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function generateData() {
}

function runTestCase(container) {
const chart = window.chart = LightweightCharts.createChart(container);
const chart = window.chart = LightweightCharts.createChart(container, { layout: { attributionLogo: false } });

const mainSeries = chart.addLineSeries();
mainSeries.setData(generateData());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function runTestCase(container) {
timeScale: {
minBarSpacing: 0.001,
},
layout: { attributionLogo: false },
});

const mainSeries = chart.addBarSeries();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function runTestCase(container) {
rightPriceScale: {
mode: LightweightCharts.PriceScaleMode.IndexedTo100,
},
layout: { attributionLogo: false },
});
const lineSeries = chart.addLineSeries({
baseLineVisible: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function runTestCase(container) {
rightPriceScale: {
mode: LightweightCharts.PriceScaleMode.IndexedTo100,
},
layout: { attributionLogo: false },
});
const lineSeries = chart.addLineSeries({
visible: false,
Expand Down
Loading

0 comments on commit 2ce43a3

Please sign in to comment.