mirror of
https://github.com/FlipsideCrypto/flipside-js.git
synced 2026-02-06 10:48:11 +00:00
First commit.
This commit is contained in:
commit
dbc799602f
3
.babelrc
Normal file
3
.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["@babel/plugin-transform-react-jsx", { "pragma": "h" }]]
|
||||
}
|
||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.vscode/
|
||||
.DS_STORE
|
||||
node_modules/
|
||||
9
License.md
Normal file
9
License.md
Normal file
@ -0,0 +1,9 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2018 Flipsidecrypto.com hello@flipsidecrypto.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
64
README.md
Normal file
64
README.md
Normal file
@ -0,0 +1,64 @@
|
||||
# FlipsideJS
|
||||
|
||||
FlipsideJS provides a library embeddable widgets that display data from the Flipside Platform API.
|
||||
|
||||
## Install
|
||||
|
||||
```html
|
||||
<script src="https://flipsidecrypto.com/flipside-js/flipside.js"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<div id="container"></div>
|
||||
<script>
|
||||
var flipside = new Flipside(YOUR_FLIPSIDE_API_KEY);
|
||||
flipside.create("container", "BTC");
|
||||
</script>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
_create(id: string, symbol: string, options: object)_
|
||||
Creates an FCAS widget in the given element ID.
|
||||
|
||||
#### Parameters
|
||||
|
||||
- _id_: ID of the element in which to create the widget.
|
||||
- _symbol_: Symbol of the asset. e.g "BTC"
|
||||
- _opts_: Display options for the widget
|
||||
|
||||
#### Options
|
||||
|
||||
- `score: boolean`: Show/hide the score section.
|
||||
- `plot: boolean`: Show/hide the plot graph.
|
||||
- `logo: boolean`: Show/hide the asset's logo.
|
||||
- `symbol: boolean`: Show/hide the asset's symbol.
|
||||
- `trend: boolean`: Show/hide the 7 day trend.
|
||||
- `rank: boolean`: Show/hide the FCAS rank.
|
||||
|
||||
#### Default options
|
||||
|
||||
```js
|
||||
flipside.create("container", "ETH", {
|
||||
score: true,
|
||||
plot: true,
|
||||
logo: true,
|
||||
symbol: true,
|
||||
trend: true,
|
||||
rank: true
|
||||
});
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
```
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```
|
||||
$ npm run dev
|
||||
```
|
||||
8
dist/flipside.js
vendored
Normal file
8
dist/flipside.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
index.html
Normal file
24
index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>flipside.js</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script src="flipside.js"></script>
|
||||
<style>
|
||||
.wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper"><div id="widget-0"></div></div>
|
||||
<script>
|
||||
const flipside = new Flipside("<YourApiKey>");
|
||||
flipside.create("widget-0", "btc");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
7209
package-lock.json
generated
Normal file
7209
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
package.json
Normal file
31
package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "flipside-js",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server",
|
||||
"build": "webpack -p --env production",
|
||||
"build:stats": "webpack --env production --json > stats.json"
|
||||
},
|
||||
"author": "Flipsidecrypto.com <hello@flipsidecrypto.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"preact": "^8.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.1.6",
|
||||
"@babel/plugin-transform-react-jsx": "^7.1.6",
|
||||
"babel-loader": "^8.0.4",
|
||||
"css-loader": "^1.0.1",
|
||||
"node-sass": "^4.10.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"webpack": "^4.26.0",
|
||||
"webpack-bundle-analyzer": "^3.0.3",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-dev-server": "^3.1.10"
|
||||
}
|
||||
}
|
||||
25
src/api.js
Normal file
25
src/api.js
Normal file
@ -0,0 +1,25 @@
|
||||
import axios from "axios";
|
||||
|
||||
export default class API {
|
||||
constructor(apiKey) {
|
||||
this.client = axios.create({
|
||||
baseURL: "https://platform-api.flipsidecrypto.com/api/v1",
|
||||
params: { api_key: apiKey }
|
||||
});
|
||||
}
|
||||
|
||||
async fetchAssetMetric(symbol, metric = "FCAS", days = 7) {
|
||||
const sym = `${symbol}`.toUpperCase();
|
||||
const res = await this.client.get(`/assets/${sym}/metrics/${metric}`, {
|
||||
params: { change_over: days }
|
||||
});
|
||||
return res.data;
|
||||
}
|
||||
|
||||
async fetchFCASDistribution(asset) {
|
||||
const res = await this.client.get(`/metrics/FCAS/assets`, {
|
||||
params: { visual_distribution: true }
|
||||
});
|
||||
return res.data;
|
||||
}
|
||||
}
|
||||
41
src/fcas/index.js
Normal file
41
src/fcas/index.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { h, Component } from "preact";
|
||||
import Score from "./score";
|
||||
import Plot from "./plot";
|
||||
import "./styles.scss";
|
||||
|
||||
export default class FCAS extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
loading: true,
|
||||
metric: null
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const data = await this.props.api.fetchAssetMetric(
|
||||
this.props.symbol,
|
||||
"FCAS"
|
||||
);
|
||||
this.setState({
|
||||
loading: false,
|
||||
metric: {
|
||||
fcas: Math.round(data.value),
|
||||
change: data.percent_change,
|
||||
name: data.asset_name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render({ opts, api, symbol }, { metric, loading }) {
|
||||
if (loading) return null;
|
||||
return (
|
||||
<div class="fs-container">
|
||||
{opts.score && <Score symbol={symbol} metric={metric} opts={opts} />}
|
||||
{opts.plot && (
|
||||
<Plot symbol={symbol} metric={metric} api={api} opts={opts} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
119
src/fcas/plot/index.js
Normal file
119
src/fcas/plot/index.js
Normal file
@ -0,0 +1,119 @@
|
||||
import { h, Component } from "preact";
|
||||
import "./styles.scss";
|
||||
|
||||
const PLOT_WIDTH = 240;
|
||||
const PLOT_SCALE = PLOT_WIDTH / 1000;
|
||||
|
||||
export default class Plot extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
loading: true,
|
||||
distribution: null
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const data = await this.props.api.fetchFCASDistribution();
|
||||
this.setState({
|
||||
loading: false,
|
||||
distribution: data
|
||||
});
|
||||
}
|
||||
|
||||
render({ metric, symbol }, { loading, distribution }) {
|
||||
if (loading) return null;
|
||||
|
||||
const xPos = PLOT_SCALE * metric.fcas;
|
||||
const highlightedAssets = distribution
|
||||
.filter(i => ["ETH", "BTC"].indexOf(i.symbol) > -1)
|
||||
.filter(i => i.symbol != symbol.toUpperCase());
|
||||
|
||||
let lastHighlightX, lastHighlightY;
|
||||
|
||||
return (
|
||||
<svg width={PLOT_WIDTH} height="120" overflow="visible">
|
||||
<defs>
|
||||
<linearGradient id="gradient">
|
||||
<stop stop-color="#ff2600" offset="0%" />
|
||||
<stop stop-color="#ff7a18" offset="40%" />
|
||||
<stop stop-color="#8fcb89" offset="68%" />
|
||||
<stop stop-color="#30a92d" offset="92%" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g>
|
||||
<circle cx="0" cy="44" r="2.5" />
|
||||
<text x="6" y="47" font-size="8">
|
||||
Coins
|
||||
</text>
|
||||
</g>
|
||||
|
||||
<g fill="rgba(0, 0, 0, 0.4)">
|
||||
{distribution.map(i => (
|
||||
<circle cx={PLOT_SCALE * i.value} cy="58" r="2.5" />
|
||||
))}
|
||||
</g>
|
||||
|
||||
<rect
|
||||
x="0"
|
||||
y="64"
|
||||
width={PLOT_WIDTH}
|
||||
height="8"
|
||||
fill="url(#gradient)"
|
||||
/>
|
||||
|
||||
<text y="85" text-anchor="middle" class="fs-plot__x">
|
||||
<tspan x="0">0</tspan>
|
||||
<tspan x="50%">500</tspan>
|
||||
<tspan x="100%">1000</tspan>
|
||||
</text>
|
||||
|
||||
<text class="fs-plot__blue" text-anchor="middle">
|
||||
<tspan x={xPos} y="14">
|
||||
{symbol.toUpperCase()}
|
||||
</tspan>
|
||||
<tspan x={xPos} y="104">
|
||||
{metric.fcas}
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
<line
|
||||
x1={xPos}
|
||||
y1="16"
|
||||
x2={xPos}
|
||||
y2="92"
|
||||
style="stroke:rgb(45,87,237); stroke-width:1"
|
||||
/>
|
||||
|
||||
{highlightedAssets.map(a => {
|
||||
let yOffset = 0;
|
||||
const xPos = PLOT_SCALE * a.value;
|
||||
if (lastHighlightX && xPos - lastHighlightX < 10) {
|
||||
yOffset = 10;
|
||||
}
|
||||
lastHighlightX = xPos;
|
||||
return (
|
||||
<g>
|
||||
<text
|
||||
x={xPos}
|
||||
y={44 - yOffset}
|
||||
text-anchor="middle"
|
||||
font-size="10"
|
||||
>
|
||||
{a.symbol}
|
||||
</text>
|
||||
<line
|
||||
x1={xPos}
|
||||
y1={47 - yOffset}
|
||||
x2={xPos}
|
||||
y2="60"
|
||||
style="stroke:rgb(0,0,0); stroke-width:0.5"
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
})}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
8
src/fcas/plot/styles.scss
Normal file
8
src/fcas/plot/styles.scss
Normal file
@ -0,0 +1,8 @@
|
||||
.fs-plot__blue {
|
||||
fill: #2d57ed;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fs-plot__x {
|
||||
font-size: 7px;
|
||||
}
|
||||
9
src/fcas/score/images/icon-down.svg
Normal file
9
src/fcas/score/images/icon-down.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="11px" height="12px" viewBox="0 0 11 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>icon-down</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M4,7 L0,7 L5.5,0 L11,7 L7,7 L7,12 L4,12 L4,7 Z" id="icon-down" fill="#FF2700" transform="translate(5.500000, 6.000000) rotate(-180.000000) translate(-5.500000, -6.000000) "></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 630 B |
9
src/fcas/score/images/icon-eq.svg
Normal file
9
src/fcas/score/images/icon-eq.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="8px" height="7px" viewBox="0 0 8 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>icon-eq</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M0,4 L8,4 L8,7 L0,7 L0,4 Z M0,0 L8,0 L8,3 L0,3 L0,0 Z" id="icon-eq" fill="#808080"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 534 B |
9
src/fcas/score/images/icon-up.svg
Normal file
9
src/fcas/score/images/icon-up.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="11px" height="12px" viewBox="0 0 11 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 52.4 (67378) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>icon-up</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M4,7 L0,7 L5.5,0 L11,7 L7,7 L7,12 L4,12 L4,7 Z" id="icon-up" fill="#057511"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 531 B |
126
src/fcas/score/index.js
Normal file
126
src/fcas/score/index.js
Normal file
@ -0,0 +1,126 @@
|
||||
import { h, Component } from "preact";
|
||||
import "./styles.scss";
|
||||
|
||||
function round(value) {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
return Math.round(value * 100) / 100;
|
||||
}
|
||||
|
||||
export default class Score extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
showTooltip: false
|
||||
};
|
||||
this._showTooltip = this._showTooltip.bind(this);
|
||||
this._hideTooltip = this._hideTooltip.bind(this);
|
||||
}
|
||||
|
||||
_showTooltip() {
|
||||
this.setState({ showTooltip: true });
|
||||
}
|
||||
|
||||
_hideTooltip() {
|
||||
this.setState({ showTooltip: false });
|
||||
}
|
||||
|
||||
render({ opts, symbol, metric }, { showTooltip }) {
|
||||
let rank;
|
||||
if (metric.fcas <= 500) {
|
||||
rank = "f";
|
||||
} else if (metric.fcas <= 649) {
|
||||
rank = "c";
|
||||
} else if (metric.fcas <= 749) {
|
||||
rank = "b";
|
||||
} else if (metric.fcas <= 899) {
|
||||
rank = "a";
|
||||
} else {
|
||||
rank = "s";
|
||||
}
|
||||
|
||||
let trendDir, trendIcon;
|
||||
if (metric.change < 0) {
|
||||
trendDir = "down";
|
||||
trendIcon = require("./images/icon-down.svg");
|
||||
} else if (metric.change == 0) {
|
||||
trendDir = "eq";
|
||||
trendIcon = require("./images/icon-eq.svg");
|
||||
} else {
|
||||
trendDir = "up";
|
||||
trendIcon = require("./images/icon-up.svg");
|
||||
}
|
||||
|
||||
const trendDiff = Math.abs(metric.fcas * (metric.change / 100));
|
||||
|
||||
return (
|
||||
<div class="fs-score">
|
||||
<header class="fs-token">
|
||||
<img
|
||||
class="fs-token__logo"
|
||||
src={`https://s3.amazonaws.com/fsc-crypto-icons/svg/color/${symbol}.svg`}
|
||||
/>
|
||||
<h1 class="fs-token__name">
|
||||
{metric.name}
|
||||
{opts.symbol && <span class="fs-token__sym">{symbol}</span>}
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
<div class="fs-fcas">
|
||||
<h2 class="fs-fcas__header">FCAS</h2>
|
||||
<span
|
||||
class="fs-link fs-fcas__what"
|
||||
onMouseEnter={this._showTooltip}
|
||||
onMouseLeave={this._hideTooltip}
|
||||
>
|
||||
What's this?
|
||||
{showTooltip && (
|
||||
<div class="fs-tooltip">
|
||||
<div class="fs-tooltip__content">
|
||||
<p>
|
||||
<b>FCAS</b> is Flipside’s Crypto Asset Score, ranging from 0
|
||||
- 1000. The score combines values from the 3 major market
|
||||
factors to create a comparative metric across digital
|
||||
assets.
|
||||
</p>
|
||||
<p>
|
||||
Powered by{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://flipsidecrypto.com"
|
||||
class="fs-link"
|
||||
>
|
||||
flipsidecrypto.com
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="fs-data">
|
||||
<h3 class="fs-value">{metric.fcas}</h3>
|
||||
|
||||
{opts.trend && (
|
||||
<div class="fs-trend">
|
||||
<div class={`fs-trend__change fs-trend__change--${trendDir}`}>
|
||||
<img class="fs-trend__icon" src={trendIcon} />{" "}
|
||||
{round(trendDiff)}
|
||||
</div>
|
||||
7d
|
||||
</div>
|
||||
)}
|
||||
|
||||
{opts.rank && (
|
||||
<div class="fs-rank">
|
||||
<b class={`fs-rank__letter fs-rank__letter--${rank}`}>{rank}</b>{" "}
|
||||
Rank
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
148
src/fcas/score/styles.scss
Normal file
148
src/fcas/score/styles.scss
Normal file
@ -0,0 +1,148 @@
|
||||
.fs-score {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.fs-token {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
|
||||
.fs-token__logo {
|
||||
margin-right: 8px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.fs-token__name {
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fs-token__sym {
|
||||
font-size: 12px;
|
||||
color: #2d57ed;
|
||||
text-transform: uppercase;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.fs-fcas {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fs-fcas__header {
|
||||
margin: 0 10px 0 0;
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.fs-fcas__what {
|
||||
font-size: 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fs-tooltip {
|
||||
padding-left: 15px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.fs-tooltip__content {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.15);
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
line-height: 14px;
|
||||
padding: 5px 15px;
|
||||
border: 1px solid rgba(200, 200, 200, 0.5);
|
||||
&:before {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: calc(50% - 10px);
|
||||
transform: rotate(-45deg);
|
||||
background: #fff;
|
||||
box-shadow: -1px -1px 0 rgba(200, 200, 200, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.fs-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.fs-value {
|
||||
font-size: 58px;
|
||||
font-weight: bold;
|
||||
margin: 0 14px 0 0;
|
||||
}
|
||||
|
||||
.fs-trend {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.fs-trend__icon {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.fs-trend__change {
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 28px;
|
||||
margin-bottom: 5px;
|
||||
&--up {
|
||||
color: #057511;
|
||||
}
|
||||
&--down {
|
||||
color: #ff2700;
|
||||
}
|
||||
&--eq {
|
||||
color: #808080;
|
||||
}
|
||||
}
|
||||
|
||||
.fs-rank {
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.fs-rank__letter {
|
||||
width: 32px;
|
||||
height: 28px;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
border-radius: 2px;
|
||||
line-height: 28px;
|
||||
margin-bottom: 5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.fs-rank__letter--s {
|
||||
background: #68ba66;
|
||||
}
|
||||
.fs-rank__letter--a {
|
||||
background: #8fcb89;
|
||||
}
|
||||
.fs-rank__letter--b {
|
||||
background: #b2dbad;
|
||||
}
|
||||
.fs-rank__letter--c {
|
||||
background: #ff7a18;
|
||||
}
|
||||
.fs-rank__letter--f {
|
||||
background: #ff2600;
|
||||
}
|
||||
13
src/fcas/styles.scss
Normal file
13
src/fcas/styles.scss
Normal file
@ -0,0 +1,13 @@
|
||||
.fs-container {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
|
||||
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
padding: 28px 40px 40px;
|
||||
line-height: 1;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.fs-link {
|
||||
color: #2d57ed;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
27
src/index.js
Normal file
27
src/index.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { h, render } from "preact";
|
||||
import FCAS from "./fcas";
|
||||
import API from "./api";
|
||||
|
||||
class Flipside {
|
||||
constructor(apiKey) {
|
||||
this.api = new API(apiKey);
|
||||
}
|
||||
|
||||
create(id, symbol, opts) {
|
||||
const defaults = {
|
||||
score: true,
|
||||
plot: true,
|
||||
symbol: true,
|
||||
logo: true,
|
||||
trend: true,
|
||||
rank: true
|
||||
};
|
||||
const mergedOpts = Object.assign({}, defaults, opts);
|
||||
render(
|
||||
<FCAS symbol={symbol} api={this.api} opts={mergedOpts} />,
|
||||
document.getElementById(id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
window.Flipside = Flipside;
|
||||
18
webpack.config.js
Normal file
18
webpack.config.js
Normal file
@ -0,0 +1,18 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/index.js",
|
||||
output: {
|
||||
filename: "flipside.js",
|
||||
path: path.resolve(__dirname, "dist")
|
||||
},
|
||||
mode: "development",
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" },
|
||||
{ test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] },
|
||||
{ test: /\.svg$/, use: { loader: "url-loader" } }
|
||||
]
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user