mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Brings in the new donut charts.
Summary: - Donut charts is same as pie chart with few extra options to control size of the hole and to show/hide a big total in it. - Add a new option type to tune a numeric options using a slider/spinner/keyboard. - Add a new option type to tune a numeric options using a slider/keyboard - Add a new .propWithDefault method to ObjObservable to allows to set a default value when options is undefined. - mocha-webdriver's findContent does not work to find content in svg elements. So had to tweak original function into a sister function using .textContent instead. Test Plan: Adds new tests Reviewers: dsagal Reviewed By: dsagal Subscribers: anaisconce, dsagal Differential Revision: https://phab.getgrist.com/D3107
This commit is contained in:
parent
32bb89235e
commit
0b437d1544
@ -1,6 +1,7 @@
|
|||||||
import * as BaseView from 'app/client/components/BaseView';
|
import * as BaseView from 'app/client/components/BaseView';
|
||||||
import {GristDoc} from 'app/client/components/GristDoc';
|
import {GristDoc} from 'app/client/components/GristDoc';
|
||||||
import {consolidateValues, sortByXValues, splitValuesByIndex, uniqXValues} from 'app/client/lib/chartUtil';
|
import {consolidateValues, formatPercent, sortByXValues, splitValuesByIndex,
|
||||||
|
uniqXValues} from 'app/client/lib/chartUtil';
|
||||||
import {Delay} from 'app/client/lib/Delay';
|
import {Delay} from 'app/client/lib/Delay';
|
||||||
import {Disposable} from 'app/client/lib/dispose';
|
import {Disposable} from 'app/client/lib/dispose';
|
||||||
import {fromKoSave} from 'app/client/lib/fromKoSave';
|
import {fromKoSave} from 'app/client/lib/fromKoSave';
|
||||||
@ -18,23 +19,35 @@ import {cssDragger} from 'app/client/ui2018/draggableList';
|
|||||||
import {icon} from 'app/client/ui2018/icons';
|
import {icon} from 'app/client/ui2018/icons';
|
||||||
import {linkSelect, menu, menuItem, select} from 'app/client/ui2018/menus';
|
import {linkSelect, menu, menuItem, select} from 'app/client/ui2018/menus';
|
||||||
import {nativeCompare} from 'app/common/gutil';
|
import {nativeCompare} from 'app/common/gutil';
|
||||||
|
import {BaseFormatter} from 'app/common/ValueFormatter';
|
||||||
import {decodeObject} from 'app/plugin/objtypes';
|
import {decodeObject} from 'app/plugin/objtypes';
|
||||||
import {Events as BackboneEvents} from 'backbone';
|
import {Events as BackboneEvents} from 'backbone';
|
||||||
import {Computed, dom, DomElementArg, fromKo, Disposable as GrainJSDisposable, IOption,
|
import {Computed, dom, DomElementArg, fromKo, Disposable as GrainJSDisposable, IOption,
|
||||||
makeTestId, Observable, styled} from 'grainjs';
|
makeTestId, MultiHolder, Observable, styled} from 'grainjs';
|
||||||
import * as ko from 'knockout';
|
import * as ko from 'knockout';
|
||||||
|
import clamp = require('lodash/clamp');
|
||||||
import debounce = require('lodash/debounce');
|
import debounce = require('lodash/debounce');
|
||||||
import defaults = require('lodash/defaults');
|
import defaults = require('lodash/defaults');
|
||||||
import defaultsDeep = require('lodash/defaultsDeep');
|
import defaultsDeep = require('lodash/defaultsDeep');
|
||||||
import {Config, Data, Datum, ErrorBar, Layout, LayoutAxis, Margin} from 'plotly.js';
|
import isNumber = require('lodash/isNumber');
|
||||||
|
import sum = require('lodash/sum');
|
||||||
|
import {Annotations, Config, Data, Datum, ErrorBar, Layout, LayoutAxis, Margin} from 'plotly.js';
|
||||||
|
|
||||||
|
|
||||||
let Plotly: PlotlyType;
|
let Plotly: PlotlyType;
|
||||||
|
|
||||||
// When charting multiple series based on user data, limit the number of series given to plotly.
|
// When charting multiple series based on user data, limit the number of series given to plotly.
|
||||||
const MAX_SERIES_IN_CHART = 100;
|
const MAX_SERIES_IN_CHART = 100;
|
||||||
|
const DONUT_DEFAULT_HOLE_SIZE = 0.75;
|
||||||
|
const DONUT_DEFAULT_TEXT_SIZE = 24;
|
||||||
|
|
||||||
const testId = makeTestId('test-chart-');
|
const testId = makeTestId('test-chart-');
|
||||||
|
|
||||||
|
function isPieLike(chartType: string) {
|
||||||
|
return ['pie', 'donut'].includes(chartType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface ChartOptions {
|
interface ChartOptions {
|
||||||
multiseries?: boolean;
|
multiseries?: boolean;
|
||||||
lineConnectGaps?: boolean;
|
lineConnectGaps?: boolean;
|
||||||
@ -44,6 +57,9 @@ interface ChartOptions {
|
|||||||
// If "symmetric", one series after each Y series gives the length of the error bars around it. If
|
// If "symmetric", one series after each Y series gives the length of the error bars around it. If
|
||||||
// "separate", two series after each Y series give the length of the error bars above and below it.
|
// "separate", two series after each Y series give the length of the error bars above and below it.
|
||||||
errorBars?: 'symmetric' | 'separate';
|
errorBars?: 'symmetric' | 'separate';
|
||||||
|
donutHoleSize?: number;
|
||||||
|
showTotal?: boolean;
|
||||||
|
textSize?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
@ -79,11 +95,14 @@ interface PlotData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Data options to pass to chart functions.
|
// Data options to pass to chart functions.
|
||||||
interface DataOptions {
|
interface DataOptions extends Data {
|
||||||
|
|
||||||
// Allows to set the pie sort option (see: https://plotly.com/javascript/reference/pie/#pie-sort).
|
// Allows to set the pie sort option (see: https://plotly.com/javascript/reference/pie/#pie-sort).
|
||||||
// Supports pie charts only.
|
// Supports pie charts only.
|
||||||
sort?: boolean;
|
sort?: boolean;
|
||||||
|
|
||||||
|
// Formatter to be used for the total inside donut charts.
|
||||||
|
totalFormatter?: BaseFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a list of Series into a set of Plotly traces.
|
// Convert a list of Series into a set of Plotly traces.
|
||||||
@ -118,6 +137,7 @@ export class ChartView extends Disposable {
|
|||||||
protected viewSection: ViewSectionRec;
|
protected viewSection: ViewSectionRec;
|
||||||
protected sortedRows: SortedRowSet;
|
protected sortedRows: SortedRowSet;
|
||||||
protected tableModel: DataTableModel;
|
protected tableModel: DataTableModel;
|
||||||
|
protected gristDoc: GristDoc;
|
||||||
|
|
||||||
private _chartType: ko.Observable<string>;
|
private _chartType: ko.Observable<string>;
|
||||||
private _options: ObjObservable<any>;
|
private _options: ObjObservable<any>;
|
||||||
@ -125,6 +145,8 @@ export class ChartView extends Disposable {
|
|||||||
private _update: () => void;
|
private _update: () => void;
|
||||||
private _resize: () => void;
|
private _resize: () => void;
|
||||||
|
|
||||||
|
private _formatterComp: ko.Computed<BaseFormatter|undefined>;
|
||||||
|
|
||||||
public create(gristDoc: GristDoc, viewSectionModel: ViewSectionRec) {
|
public create(gristDoc: GristDoc, viewSectionModel: ViewSectionRec) {
|
||||||
BaseView.call(this as any, gristDoc, viewSectionModel);
|
BaseView.call(this as any, gristDoc, viewSectionModel);
|
||||||
|
|
||||||
@ -138,6 +160,13 @@ export class ChartView extends Disposable {
|
|||||||
this._chartType = this.viewSection.chartTypeDef;
|
this._chartType = this.viewSection.chartTypeDef;
|
||||||
this._options = this.viewSection.optionsObj;
|
this._options = this.viewSection.optionsObj;
|
||||||
|
|
||||||
|
// Computed that returns the formatter of the first series. This is useful to format the total
|
||||||
|
// within a donut chart.
|
||||||
|
this._formatterComp = this.autoDispose(ko.computed(() => {
|
||||||
|
const field = this.viewSection.viewFields().at(1);
|
||||||
|
return field?.createVisibleColFormatter();
|
||||||
|
}));
|
||||||
|
|
||||||
this._update = debounce(() => this._updateView(), 0);
|
this._update = debounce(() => this._updateView(), 0);
|
||||||
|
|
||||||
this.autoDispose(this._chartType.subscribe(this._update));
|
this.autoDispose(this._chartType.subscribe(this._update));
|
||||||
@ -145,6 +174,7 @@ export class ChartView extends Disposable {
|
|||||||
this.autoDispose(this.viewSection.viewFields().subscribe(this._update));
|
this.autoDispose(this.viewSection.viewFields().subscribe(this._update));
|
||||||
this.listenTo(this.sortedRows, 'rowNotify', this._update);
|
this.listenTo(this.sortedRows, 'rowNotify', this._update);
|
||||||
this.autoDispose(this.sortedRows.getKoArray().subscribe(this._update));
|
this.autoDispose(this.sortedRows.getKoArray().subscribe(this._update));
|
||||||
|
this.autoDispose(this._formatterComp.subscribe(this._update));
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepareToPrint(onOff: boolean) {
|
public prepareToPrint(onOff: boolean) {
|
||||||
@ -208,10 +238,14 @@ export class ChartView extends Disposable {
|
|||||||
let plotData: PlotData = {data: []};
|
let plotData: PlotData = {data: []};
|
||||||
|
|
||||||
const sortSpec = this.viewSection.activeSortSpec.peek();
|
const sortSpec = this.viewSection.activeSortSpec.peek();
|
||||||
if (this._chartType.peek() === 'pie' && sortSpec?.length) {
|
if (isPieLike(this._chartType.peek()) && sortSpec?.length) {
|
||||||
dataOptions.sort = false;
|
dataOptions.sort = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._chartType.peek() === 'donut') {
|
||||||
|
dataOptions.totalFormatter = this._formatterComp.peek();
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.multiseries) {
|
if (!options.multiseries) {
|
||||||
plotData = chartFunc(series, options, dataOptions);
|
plotData = chartFunc(series, options, dataOptions);
|
||||||
} else if (series.length > 1) {
|
} else if (series.length > 1) {
|
||||||
@ -419,7 +453,7 @@ export class ChartConfig extends GrainJSDisposable {
|
|||||||
|
|
||||||
// The label to show for the first field in the axis configurator.
|
// The label to show for the first field in the axis configurator.
|
||||||
private _firstFieldLabel = Computed.create(this, fromKo(this._section.chartTypeDef), (
|
private _firstFieldLabel = Computed.create(this, fromKo(this._section.chartTypeDef), (
|
||||||
(_use, chartType) => chartType === 'pie' ? 'LABEL' : 'X-AXIS'
|
(_use, chartType) => isPieLike(chartType) ? 'LABEL' : 'X-AXIS'
|
||||||
));
|
));
|
||||||
|
|
||||||
// A computed that returns `this._section.chartTypeDef` and that takes care of removing the group
|
// A computed that returns `this._section.chartTypeDef` and that takes care of removing the group
|
||||||
@ -429,7 +463,7 @@ export class ChartConfig extends GrainJSDisposable {
|
|||||||
return this._gristDoc.docData.bundleActions('switched chart type', async () => {
|
return this._gristDoc.docData.bundleActions('switched chart type', async () => {
|
||||||
await this._section.chartTypeDef.saveOnly(val);
|
await this._section.chartTypeDef.saveOnly(val);
|
||||||
// When switching chart type to 'pie' makes sure to remove the group data option.
|
// When switching chart type to 'pie' makes sure to remove the group data option.
|
||||||
if (val === 'pie') {
|
if (isPieLike(val)) {
|
||||||
await this._setGroupDataColumn(-1);
|
await this._setGroupDataColumn(-1);
|
||||||
this._groupDataForce.set(false);
|
this._groupDataForce.set(false);
|
||||||
}
|
}
|
||||||
@ -447,11 +481,14 @@ export class ChartConfig extends GrainJSDisposable {
|
|||||||
|
|
||||||
if (this._section.parentKey() !== 'chart') { return null; }
|
if (this._section.parentKey() !== 'chart') { return null; }
|
||||||
|
|
||||||
|
const owner = new MultiHolder();
|
||||||
return [
|
return [
|
||||||
|
dom.autoDispose(owner),
|
||||||
cssRow(
|
cssRow(
|
||||||
select(this._chartType, [
|
select(this._chartType, [
|
||||||
{value: 'bar', label: 'Bar Chart', icon: 'ChartBar' },
|
{value: 'bar', label: 'Bar Chart', icon: 'ChartBar' },
|
||||||
{value: 'pie', label: 'Pie Chart', icon: 'ChartPie' },
|
{value: 'pie', label: 'Pie Chart', icon: 'ChartPie' },
|
||||||
|
{value: 'donut', label: 'Donut Chart', icon: 'ChartDonut' },
|
||||||
{value: 'area', label: 'Area Chart', icon: 'ChartArea' },
|
{value: 'area', label: 'Area Chart', icon: 'ChartArea' },
|
||||||
{value: 'line', label: 'Line Chart', icon: 'ChartLine' },
|
{value: 'line', label: 'Line Chart', icon: 'ChartLine' },
|
||||||
{value: 'scatter', label: 'Scatter Plot', icon: 'ChartLine' },
|
{value: 'scatter', label: 'Scatter Plot', icon: 'ChartLine' },
|
||||||
@ -459,12 +496,29 @@ export class ChartConfig extends GrainJSDisposable {
|
|||||||
]),
|
]),
|
||||||
testId("type"),
|
testId("type"),
|
||||||
),
|
),
|
||||||
dom.maybe((use) => use(this._section.chartTypeDef) !== 'pie', () => [
|
dom.maybe((use) => !isPieLike(use(this._section.chartTypeDef)), () => [
|
||||||
// These options don't make much sense for a pie chart.
|
// These options don't make much sense for a pie chart.
|
||||||
cssCheckboxRowObs('Group data', this._groupData),
|
cssCheckboxRowObs('Group data', this._groupData),
|
||||||
cssCheckboxRow('Invert Y-axis', this._optionsObj.prop('invertYAxis')),
|
cssCheckboxRow('Invert Y-axis', this._optionsObj.prop('invertYAxis')),
|
||||||
cssCheckboxRow('Log scale Y-axis', this._optionsObj.prop('logYAxis')),
|
cssCheckboxRow('Log scale Y-axis', this._optionsObj.prop('logYAxis')),
|
||||||
]),
|
]),
|
||||||
|
dom.maybe((use) => use(this._section.chartTypeDef) === 'donut', () => [
|
||||||
|
cssSlideRow(
|
||||||
|
'Hole Size',
|
||||||
|
Computed.create(owner, (use) => use(this._optionsObj.prop('donutHoleSize')) ?? DONUT_DEFAULT_HOLE_SIZE),
|
||||||
|
(val: number) => this._optionsObj.prop('donutHoleSize').saveOnly(val),
|
||||||
|
testId('option')
|
||||||
|
),
|
||||||
|
cssCheckboxRow('Show Total', this._optionsObj.prop('showTotal')),
|
||||||
|
dom.maybe(this._optionsObj.prop('showTotal'), () => (
|
||||||
|
cssNumberWithSpinnerRow(
|
||||||
|
'Text Size',
|
||||||
|
Computed.create(owner, (use) => use(this._optionsObj.prop('textSize')) ?? DONUT_DEFAULT_TEXT_SIZE),
|
||||||
|
(val: number) => this._optionsObj.prop('textSize').saveOnly(val),
|
||||||
|
testId('option')
|
||||||
|
)
|
||||||
|
))
|
||||||
|
]),
|
||||||
dom.maybe((use) => use(this._section.chartTypeDef) === 'line', () => [
|
dom.maybe((use) => use(this._section.chartTypeDef) === 'line', () => [
|
||||||
cssCheckboxRow('Connect gaps', this._optionsObj.prop('lineConnectGaps')),
|
cssCheckboxRow('Connect gaps', this._optionsObj.prop('lineConnectGaps')),
|
||||||
cssCheckboxRow('Show markers', this._optionsObj.prop('lineMarkers')),
|
cssCheckboxRow('Show markers', this._optionsObj.prop('lineMarkers')),
|
||||||
@ -622,6 +676,105 @@ export class ChartConfig extends GrainJSDisposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Row for a numeric option. User can change value using spinners or directly using keyboard. In
|
||||||
|
// case of invalid values, the field reverts to the saved one.
|
||||||
|
function cssNumberWithSpinnerRow(label: string, value: Computed<number>, save: (val: number) => Promise<void>,
|
||||||
|
...args: DomElementArg[]) {
|
||||||
|
const minValue = 1;
|
||||||
|
let input: HTMLInputElement;
|
||||||
|
|
||||||
|
// Set the input's value to the value that's saved on the server.
|
||||||
|
function reset() {
|
||||||
|
input.value = value.get() + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onChange(val: string, func: (val: number) => number = (v) => v) {
|
||||||
|
let fvalue = parseFloat(val);
|
||||||
|
if (isFinite(fvalue)) {
|
||||||
|
fvalue = clamp(func(fvalue), minValue, Infinity);
|
||||||
|
await save(fvalue);
|
||||||
|
}
|
||||||
|
// Reset is needed if value were not a valid number.
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cssRow(
|
||||||
|
cssRowLabel(label),
|
||||||
|
cssNumberWithSpinner(
|
||||||
|
input = cssNumberInput(
|
||||||
|
{type: 'text'},
|
||||||
|
dom.prop('value', (use) => use(value) + "px"),
|
||||||
|
dom.on('change', (_ev, el) => onChange(el.value)),
|
||||||
|
dom.onKeyDown({
|
||||||
|
ArrowDown: (_ev, el) => onChange(el.value, (val) => val - 1),
|
||||||
|
ArrowUp: (_ev, el) => onChange(el.value, (val) => val + 1),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
|
||||||
|
// We add spinners as overlay in order to support showing the unit 'px' next to the value.
|
||||||
|
cssSpinners(
|
||||||
|
'input',
|
||||||
|
{type: 'number', step: '1', min: String(minValue)},
|
||||||
|
dom.prop('value', value),
|
||||||
|
dom.on('change', (_ev, el) => onChange(el.value)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...args
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row for a numeric option that leaves between 0 and 1. User can change value using a slider, or
|
||||||
|
// spinners or by directly using keyboard. Value is shown as percent. If user enter an invalid
|
||||||
|
// value, field reverts to the saved value.
|
||||||
|
function cssSlideRow(label: string, value: Computed<number>, save: (val: number) => Promise<void>,
|
||||||
|
...args: DomElementArg[]) {
|
||||||
|
let input: HTMLInputElement;
|
||||||
|
|
||||||
|
// Set the input's value to the value that's saved on the server.
|
||||||
|
function reset() {
|
||||||
|
input.value = formatPercent(value.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onChange(val: string, func: (val: number) => number = (v) => v) {
|
||||||
|
let fvalue = parseFloat(val);
|
||||||
|
if (isFinite(fvalue)) {
|
||||||
|
fvalue = clamp(func(fvalue), 0, 99) / 100;
|
||||||
|
await save(fvalue);
|
||||||
|
}
|
||||||
|
// Reset is needed if value were not a valid number.
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cssRow(
|
||||||
|
cssRowLabel(label),
|
||||||
|
cssRangeInput(
|
||||||
|
{type: 'range', min: "0", max: "1", step: "0.01"},
|
||||||
|
dom.prop('value', value),
|
||||||
|
dom.on('change', (_ev, el) => save(Number(el.value)))
|
||||||
|
),
|
||||||
|
cssNumberWithSpinner(
|
||||||
|
input = cssNumberInput(
|
||||||
|
{type: 'text'},
|
||||||
|
dom.prop('value', (use) => formatPercent(use(value))),
|
||||||
|
dom.on('change', (_ev, el) => onChange(el.value)),
|
||||||
|
dom.onKeyDown({
|
||||||
|
ArrowDown: (_ev, el) => onChange(el.value, (val) => val - 1),
|
||||||
|
ArrowUp: (_ev, el) => onChange(el.value, (val) => val + 1),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
|
||||||
|
// We add spinners as overlay in order to support showing the unit '%' next to the value.
|
||||||
|
cssSpinners(
|
||||||
|
'input',
|
||||||
|
{type: 'number', step: '0.01', min: '0', max: '0.99'},
|
||||||
|
dom.prop('value', value),
|
||||||
|
dom.on('change', (_ev, el) => save(Number(el.value))),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
...args
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function cssCheckboxRow(label: string, value: KoSaveableObservable<unknown>, ...args: DomElementArg[]) {
|
function cssCheckboxRow(label: string, value: KoSaveableObservable<unknown>, ...args: DomElementArg[]) {
|
||||||
return cssCheckboxRowObs(label, fromKoSave(value), ...args);
|
return cssCheckboxRowObs(label, fromKoSave(value), ...args);
|
||||||
}
|
}
|
||||||
@ -633,7 +786,7 @@ function cssCheckboxRowObs(label: string, value: Observable<boolean>, ...args: D
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function basicPlot(series: Series[], options: ChartOptions, dataOptions: Partial<Data>): PlotData {
|
function basicPlot(series: Series[], options: ChartOptions, dataOptions: Data): PlotData {
|
||||||
trimNonNumericData(series);
|
trimNonNumericData(series);
|
||||||
const errorBars = extractErrorBars(series, options);
|
const errorBars = extractErrorBars(series, options);
|
||||||
|
|
||||||
@ -722,6 +875,39 @@ export const chartTypes: {[name: string]: ChartFunc} = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
donut(series: Series[], options: ChartOptions, dataOptions: DataOptions = {}): PlotData {
|
||||||
|
const hole = isNumber(options.donutHoleSize) ? options.donutHoleSize : DONUT_DEFAULT_HOLE_SIZE;
|
||||||
|
const annotations: Array<Partial<Annotations>> = [];
|
||||||
|
const plotData: PlotData = chartTypes.pie(series, options, {...dataOptions, hole});
|
||||||
|
|
||||||
|
function format(val: number) {
|
||||||
|
if (dataOptions.totalFormatter) {
|
||||||
|
return dataOptions.totalFormatter.format(val);
|
||||||
|
}
|
||||||
|
return String(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.showTotal) {
|
||||||
|
annotations.push({
|
||||||
|
text: format(
|
||||||
|
series.length > 1 ?
|
||||||
|
sum(series[1].values.filter(isNumber)) :
|
||||||
|
plotData.data[0].labels!.length,
|
||||||
|
),
|
||||||
|
showarrow: false,
|
||||||
|
font: {
|
||||||
|
size: options.textSize ?? DONUT_DEFAULT_TEXT_SIZE,
|
||||||
|
}
|
||||||
|
} as any);
|
||||||
|
}
|
||||||
|
return defaultsDeep(
|
||||||
|
plotData,
|
||||||
|
{layout: {annotations}}
|
||||||
|
);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
kaplan_meier(series: Series[]): PlotData {
|
kaplan_meier(series: Series[]): PlotData {
|
||||||
// For this plot, the first series names the category of each point, and the second the
|
// For this plot, the first series names the category of each point, and the second the
|
||||||
// survival time for that point. We turn that into as many series as there are categories.
|
// survival time for that point. We turn that into as many series as there are categories.
|
||||||
@ -838,3 +1024,41 @@ const cssHintRow = styled('div', `
|
|||||||
margin: -4px 16px 8px 16px;
|
margin: -4px 16px 8px 16px;
|
||||||
color: ${colors.slate};
|
color: ${colors.slate};
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const cssRangeInput = styled('input', `
|
||||||
|
input& {
|
||||||
|
width: 82px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const cssNumberWithSpinner = styled('div', `
|
||||||
|
position: relative;
|
||||||
|
`);
|
||||||
|
|
||||||
|
const cssNumberInput = styled('input', `
|
||||||
|
width: 55px;
|
||||||
|
`);
|
||||||
|
|
||||||
|
|
||||||
|
const cssSpinners = styled('input', `
|
||||||
|
width: 19px;
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 1px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
.${cssNumberWithSpinner.className}:hover & {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* needed for chrome to show spinners, indeed the cursor could be outside of spinners' input
|
||||||
|
element */
|
||||||
|
&[type=number]::-webkit-inner-spin-button {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
@ -85,3 +85,7 @@ export function consolidateValues(series: Array<{values: Datum[]}>, xvalues: Dat
|
|||||||
}
|
}
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatPercent(val: number) {
|
||||||
|
return Math.floor(val * 100) + " %";
|
||||||
|
}
|
||||||
|
@ -552,6 +552,9 @@ export const cssRow = styled('div', `
|
|||||||
&-top-space {
|
&-top-space {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
&-disabled {
|
||||||
|
color: ${colors.slate};
|
||||||
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
export const cssButtonRow = styled(cssRow, `
|
export const cssButtonRow = styled(cssRow, `
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
export type IconName = "ChartArea" |
|
export type IconName = "ChartArea" |
|
||||||
"ChartBar" |
|
"ChartBar" |
|
||||||
|
"ChartDonut" |
|
||||||
"ChartKaplan" |
|
"ChartKaplan" |
|
||||||
"ChartLine" |
|
"ChartLine" |
|
||||||
"ChartPie" |
|
"ChartPie" |
|
||||||
@ -100,6 +101,7 @@ export const IconList: IconName[] = ["ChartArea",
|
|||||||
"ChartBar",
|
"ChartBar",
|
||||||
"ChartKaplan",
|
"ChartKaplan",
|
||||||
"ChartLine",
|
"ChartLine",
|
||||||
|
"ChartDonut",
|
||||||
"ChartPie",
|
"ChartPie",
|
||||||
"TypeCard",
|
"TypeCard",
|
||||||
"TypeCardList",
|
"TypeCardList",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--icon-ChartArea: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTMuMTkwOTgzMDEsOCBMNS4wNTI3ODY0LDQuMjc2MzkzMiBDNS4xODcyODU0NCw0LjAwNzM5NTEyIDUuNTI3MTExODEsMy45MTcxNDkzMyA1Ljc3NzM1MDEsNC4wODM5NzQ4NSBMMTEuMzMxNjQ1NCw3Ljc4NjgzODM3IEwxNS4wNjU4Nzg0LDEuMjUxOTMwNTMgQzE1LjIwMjg4MzQsMS4wMTIxNzE4MSAxNS41MDgzMTA3LDAuOTI4ODczNDQ0IDE1Ljc0ODA2OTUsMS4wNjU4Nzg0MyBDMTUuOTg3ODI4MiwxLjIwMjg4MzQxIDE2LjA3MTEyNjYsMS41MDgzMTA3NSAxNS45MzQxMjE2LDEuNzQ4MDY5NDcgTDExLjkzNDEyMTYsOC43NDgwNjk0NyBDMTEuNzkwMzk3NCw4Ljk5OTU4Njc4IDExLjQ2MzY4MjcsOS4wNzY3MTM2NiAxMS4yMjI2NDk5LDguOTE2MDI1MTUgTDUuNjkzOTE1NzksNS4yMzAyMDI0MSBMNC4xMzgyODQyNCw4LjM0MTQ2NTUxIEwxMC40NDU5NTEzLDEyLjg0Njk0MiBMMTUuMTQ2NDQ2Niw4LjE0NjQ0NjYxIEMxNS40NjE0MjksNy44MzE0NjQxOCAxNiw4LjA1NDU0NzU3IDE2LDguNSBMMTYsMTUuMDAwMTA5NSBDMTYsMTUuMjc2MjUzMyAxNS43NzYxNDAxLDE1LjUwMDExMTUgMTUuNDk5OTk2MywxNS41MDAxMDk1IEwwLjQ5OTk5NjM0OSwxNS41IEMwLjIyMzg1NTQsMTUuNDk5OTk4IDAsMTUuMjc2MTQwOSAwLDE1IEwwLDguNSBDMCw4LjIyMzg1NzYzIDAuMjIzODU3NjI1LDggMC41LDggTDMuMTkwOTgzMDEsOCBaIiBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=');
|
--icon-ChartArea: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTMuMTkwOTgzMDEsOCBMNS4wNTI3ODY0LDQuMjc2MzkzMiBDNS4xODcyODU0NCw0LjAwNzM5NTEyIDUuNTI3MTExODEsMy45MTcxNDkzMyA1Ljc3NzM1MDEsNC4wODM5NzQ4NSBMMTEuMzMxNjQ1NCw3Ljc4NjgzODM3IEwxNS4wNjU4Nzg0LDEuMjUxOTMwNTMgQzE1LjIwMjg4MzQsMS4wMTIxNzE4MSAxNS41MDgzMTA3LDAuOTI4ODczNDQ0IDE1Ljc0ODA2OTUsMS4wNjU4Nzg0MyBDMTUuOTg3ODI4MiwxLjIwMjg4MzQxIDE2LjA3MTEyNjYsMS41MDgzMTA3NSAxNS45MzQxMjE2LDEuNzQ4MDY5NDcgTDExLjkzNDEyMTYsOC43NDgwNjk0NyBDMTEuNzkwMzk3NCw4Ljk5OTU4Njc4IDExLjQ2MzY4MjcsOS4wNzY3MTM2NiAxMS4yMjI2NDk5LDguOTE2MDI1MTUgTDUuNjkzOTE1NzksNS4yMzAyMDI0MSBMNC4xMzgyODQyNCw4LjM0MTQ2NTUxIEwxMC40NDU5NTEzLDEyLjg0Njk0MiBMMTUuMTQ2NDQ2Niw4LjE0NjQ0NjYxIEMxNS40NjE0MjksNy44MzE0NjQxOCAxNiw4LjA1NDU0NzU3IDE2LDguNSBMMTYsMTUuMDAwMTA5NSBDMTYsMTUuMjc2MjUzMyAxNS43NzYxNDAxLDE1LjUwMDExMTUgMTUuNDk5OTk2MywxNS41MDAxMDk1IEwwLjQ5OTk5NjM0OSwxNS41IEMwLjIyMzg1NTQsMTUuNDk5OTk4IDAsMTUuMjc2MTQwOSAwLDE1IEwwLDguNSBDMCw4LjIyMzg1NzYzIDAuMjIzODU3NjI1LDggMC41LDggTDMuMTkwOTgzMDEsOCBaIiBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=');
|
||||||
--icon-ChartBar: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUsMTQuNSBDNSwxNC43NzYxNDI0IDQuNzc2MTQyMzcsMTUgNC41LDE1IEM0LjIyMzg1NzYzLDE1IDQsMTQuNzc2MTQyNCA0LDE0LjUgTDQsNS41IEM0LDUuMjIzODU3NjMgNC4yMjM4NTc2Myw1IDQuNSw1IEM0Ljc3NjE0MjM3LDUgNSw1LjIyMzg1NzYzIDUsNS41IEw1LDE0LjUgWiBNOCwxNC41IEM4LDE0Ljc3NjE0MjQgNy43NzYxNDIzNywxNSA3LjUsMTUgQzcuMjIzODU3NjMsMTUgNywxNC43NzYxNDI0IDcsMTQuNSBMNyw4LjUgQzcsOC4yMjM4NTc2MyA3LjIyMzg1NzYzLDggNy41LDggQzcuNzc2MTQyMzcsOCA4LDguMjIzODU3NjMgOCw4LjUgTDgsMTQuNSBaIE0xNCwxNC41IEMxNCwxNC43NzYxNDI0IDEzLjc3NjE0MjQsMTUgMTMuNSwxNSBDMTMuMjIzODU3NiwxNSAxMywxNC43NzYxNDI0IDEzLDE0LjUgTDEzLDguNSBDMTMsOC4yMjM4NTc2MyAxMy4yMjM4NTc2LDggMTMuNSw4IEMxMy43NzYxNDI0LDggMTQsOC4yMjM4NTc2MyAxNCw4LjUgTDE0LDE0LjUgWiBNMTEsMTQuNSBDMTEsMTQuNzc2MTQyNCAxMC43NzYxNDI0LDE1IDEwLjUsMTUgQzEwLjIyMzg1NzYsMTUgMTAsMTQuNzc2MTQyNCAxMCwxNC41IEwxMCw1LjUgQzEwLDUuMjIzODU3NjMgMTAuMjIzODU3Niw1IDEwLjUsNSBDMTAuNzc2MTQyNCw1IDExLDUuMjIzODU3NjMgMTEsNS41IEwxMSwxNC41IFogTTIsMTQuNSBDMiwxNC43NzYxNDI0IDEuNzc2MTQyMzcsMTUgMS41LDE1IEMxLjIyMzg1NzYzLDE1IDEsMTQuNzc2MTQyNCAxLDE0LjUgTDEsMi41IEMxLDIuMjIzODU3NjMgMS4yMjM4NTc2MywyIDEuNSwyIEMxLjc3NjE0MjM3LDIgMiwyLjIyMzg1NzYzIDIsMi41IEwyLDE0LjUgWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
--icon-ChartBar: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUsMTQuNSBDNSwxNC43NzYxNDI0IDQuNzc2MTQyMzcsMTUgNC41LDE1IEM0LjIyMzg1NzYzLDE1IDQsMTQuNzc2MTQyNCA0LDE0LjUgTDQsNS41IEM0LDUuMjIzODU3NjMgNC4yMjM4NTc2Myw1IDQuNSw1IEM0Ljc3NjE0MjM3LDUgNSw1LjIyMzg1NzYzIDUsNS41IEw1LDE0LjUgWiBNOCwxNC41IEM4LDE0Ljc3NjE0MjQgNy43NzYxNDIzNywxNSA3LjUsMTUgQzcuMjIzODU3NjMsMTUgNywxNC43NzYxNDI0IDcsMTQuNSBMNyw4LjUgQzcsOC4yMjM4NTc2MyA3LjIyMzg1NzYzLDggNy41LDggQzcuNzc2MTQyMzcsOCA4LDguMjIzODU3NjMgOCw4LjUgTDgsMTQuNSBaIE0xNCwxNC41IEMxNCwxNC43NzYxNDI0IDEzLjc3NjE0MjQsMTUgMTMuNSwxNSBDMTMuMjIzODU3NiwxNSAxMywxNC43NzYxNDI0IDEzLDE0LjUgTDEzLDguNSBDMTMsOC4yMjM4NTc2MyAxMy4yMjM4NTc2LDggMTMuNSw4IEMxMy43NzYxNDI0LDggMTQsOC4yMjM4NTc2MyAxNCw4LjUgTDE0LDE0LjUgWiBNMTEsMTQuNSBDMTEsMTQuNzc2MTQyNCAxMC43NzYxNDI0LDE1IDEwLjUsMTUgQzEwLjIyMzg1NzYsMTUgMTAsMTQuNzc2MTQyNCAxMCwxNC41IEwxMCw1LjUgQzEwLDUuMjIzODU3NjMgMTAuMjIzODU3Niw1IDEwLjUsNSBDMTAuNzc2MTQyNCw1IDExLDUuMjIzODU3NjMgMTEsNS41IEwxMSwxNC41IFogTTIsMTQuNSBDMiwxNC43NzYxNDI0IDEuNzc2MTQyMzcsMTUgMS41LDE1IEMxLjIyMzg1NzYzLDE1IDEsMTQuNzc2MTQyNCAxLDE0LjUgTDEsMi41IEMxLDIuMjIzODU3NjMgMS4yMjM4NTc2MywyIDEuNSwyIEMxLjc3NjE0MjM3LDIgMiwyLjIyMzg1NzYzIDIsMi41IEwyLDE0LjUgWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
||||||
|
--icon-ChartDonut: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNy41IiBzdHJva2U9IiMxYzEzMDMiLz48Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNSIgc3Ryb2tlPSIjMWMxMzAzIi8+PHBhdGggZD0iTTcuODg0MDYxOC41OTk4NzQyN1YzLjM0MjE1NjdNMTEuNjExODUyIDExLjUyNjE1NmwxLjg4NTMxOSAxLjg4NTMxOSIgc3Ryb2tlPSIjMDAwIi8+PC9nPjwvc3ZnPg==');
|
||||||
--icon-ChartKaplan: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTYuMTcxMjgwMjgsMS40MDgzMTgwMSBMMC45MTM0OTQ4MSwxLjQwODMxODAxIEMwLjY2ODg4NDI2MywxLjQwODMxODAxIDAuNDcwNTg4MjM1LDEuMTk3NjI4NDkgMC40NzA1ODgyMzUsMC45Mzc3Mjk3NzkgQzAuNDcwNTg4MjM1LDAuNjc3ODMxMDc0IDAuNjY4ODg0MjYzLDAuNDY3MTQxNTQ0IDAuOTEzNDk0ODEsMC40NjcxNDE1NDQgTDcuMDU3MDkzNDMsMC40NjcxNDE1NDQgQzcuMzMzMjM1OCwwLjQ2NzE0MTU0NCA3LjU1NzA5MzQzLDAuNjkwOTk5MTY5IDcuNTU3MDkzNDMsMC45NjcxNDE1NDQgTDcuNTU3MDkzNDMsMi43OTA2NzA5NiBDNy41NTcwOTM0MywzLjA2NjgxMzMzIDcuNzgwOTUxMDUsMy4yOTA2NzA5NiA4LjA1NzA5MzQzLDMuMjkwNjcwOTYgTDExLjQ4NjE1OTIsMy4yOTA2NzA5NiBDMTEuNzYyMzAxNSwzLjI5MDY3MDk2IDExLjk4NjE1OTIsMy41MTQ1Mjg1OCAxMS45ODYxNTkyLDMuNzkwNjcwOTYgTDExLjk4NjE1OTIsNS42MTQyMDAzNyBDMTEuOTg2MTU5Miw1Ljg5MDM0Mjc0IDEyLjIxMDAxNjgsNi4xMTQyMDAzNyAxMi40ODYxNTkyLDYuMTE0MjAwMzcgTDE1LjA4NjUwNTIsNi4xMTQyMDAzNyBDMTUuMzMxMTE1Nyw2LjExNDIwMDM3IDE1LjUyOTQxMTgsNi4zMjQ4ODk5IDE1LjUyOTQxMTgsNi41ODQ3ODg2IEMxNS41Mjk0MTE4LDYuODQ0Njg3MzEgMTUuMzMxMTE1Nyw3LjA1NTM3Njg0IDE1LjA4NjUwNTIsNy4wNTUzNzY4NCBMMTEuNjAwMzQ2LDcuMDU1Mzc2ODQgQzExLjMyNDIwMzYsNy4wNTUzNzY4NCAxMS4xMDAzNDYsNi44MzE1MTkyMSAxMS4xMDAzNDYsNi41NTUzNzY4NCBMMTEuMTAwMzQ2LDQuNzMxODQ3NDMgQzExLjEwMDM0Niw0LjQ1NTcwNTA1IDEwLjg3NjQ4ODQsNC4yMzE4NDc0MyAxMC42MDAzNDYsNC4yMzE4NDc0MyBMNy4xNzEyODAyOCw0LjIzMTg0NzQzIEM2Ljg5NTEzNzksNC4yMzE4NDc0MyA2LjY3MTI4MDI4LDQuMDA3OTg5OCA2LjY3MTI4MDI4LDMuNzMxODQ3NDMgTDYuNjcxMjgwMjgsMS45MDgzMTgwMSBDNi42NzEyODAyOCwxLjYzMjE3NTY0IDYuNDQ3NDIyNjUsMS40MDgzMTgwMSA2LjE3MTI4MDI4LDEuNDA4MzE4MDEgWiBNMi43OTQxMTc2NSwzLjI5MDY3MDk2IEwwLjk0MTE3NjQ3MSwzLjI5MDY3MDk2IEMwLjY4MTI3Nzc2NSwzLjI5MDY3MDk2IDAuNDcwNTg4MjM1LDMuMDc5OTgxNDMgMC40NzA1ODgyMzUsMi44MjAwODI3MiBDMC40NzA1ODgyMzUsMi41NjAxODQwMSAwLjY4MTI3Nzc2NSwyLjM0OTQ5NDQ5IDAuOTQxMTc2NDcxLDIuMzQ5NDk0NDkgTDMuNzM1Mjk0MTIsMi4zNDk0OTQ0OSBDNC4wMTE0MzY0OSwyLjM0OTQ5NDQ5IDQuMjM1Mjk0MTIsMi41NzMzNTIxMSA0LjIzNTI5NDEyLDIuODQ5NDk0NDkgTDQuMjM1Mjk0MTIsNy40OTY1NTMzMSBDNC4yMzUyOTQxMiw3Ljc3MjY5NTY4IDQuNDU5MTUxNzQsNy45OTY1NTMzMSA0LjczNTI5NDEyLDcuOTk2NTUzMzEgTDEwLjMyMzUyOTQsNy45OTY1NTMzMSBDMTAuNTk5NjcxOCw3Ljk5NjU1MzMxIDEwLjgyMzUyOTQsOC4yMjA0MTA5MyAxMC44MjM1Mjk0LDguNDk2NTUzMzEgTDEwLjgyMzUyOTQsMTEuMjYxMjU5MiBDMTAuODIzNTI5NCwxMS41Mzc0MDE2IDExLjA0NzM4NywxMS43NjEyNTkyIDExLjMyMzUyOTQsMTEuNzYxMjU5MiBMMTMuMTQ3MDU4OCwxMS43NjEyNTkyIEMxMy40MjMyMDEyLDExLjc2MTI1OTIgMTMuNjQ3MDU4OCwxMS45ODUxMTY4IDEzLjY0NzA1ODgsMTIuMjYxMjU5MiBMMTMuNjQ3MDU4OCwxNS4wNTUzNzY4IEMxMy42NDcwNTg4LDE1LjMxNTI3NTUgMTMuNDM2MzY5MywxNS41MjU5NjUxIDEzLjE3NjQ3MDYsMTUuNTI1OTY1MSBDMTIuOTE2NTcxOSwxNS41MjU5NjUxIDEyLjcwNTg4MjQsMTUuMzE1Mjc1NSAxMi43MDU4ODI0LDE1LjA1NTM3NjggTDEyLjcwNTg4MjQsMTMuMjAyNDM1NyBDMTIuNzA1ODgyNCwxMi45MjYyOTMzIDEyLjQ4MjAyNDcsMTIuNzAyNDM1NyAxMi4yMDU4ODI0LDEyLjcwMjQzNTcgTDEwLjM4MjM1MjksMTIuNzAyNDM1NyBDMTAuMTA2MjEwNiwxMi43MDI0MzU3IDkuODgyMzUyOTQsMTIuNDc4NTc4IDkuODgyMzUyOTQsMTIuMjAyNDM1NyBMOS44ODIzNTI5NCw5LjQzNzcyOTc4IEM5Ljg4MjM1Mjk0LDkuMTYxNTg3NCA5LjY1ODQ5NTMyLDguOTM3NzI5NzggOS4zODIzNTI5NCw4LjkzNzcyOTc4IEwzLjc5NDExNzY1LDguOTM3NzI5NzggQzMuNTE3OTc1MjcsOC45Mzc3Mjk3OCAzLjI5NDExNzY1LDguNzEzODcyMTUgMy4yOTQxMTc2NSw4LjQzNzcyOTc4IEwzLjI5NDExNzY1LDMuNzkwNjcwOTYgQzMuMjk0MTE3NjUsMy41MTQ1Mjg1OCAzLjA3MDI2MDAyLDMuMjkwNjcwOTYgMi43OTQxMTc2NSwzLjI5MDY3MDk2IFoiIGZpbGw9IiMwMDAiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==');
|
--icon-ChartKaplan: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTYuMTcxMjgwMjgsMS40MDgzMTgwMSBMMC45MTM0OTQ4MSwxLjQwODMxODAxIEMwLjY2ODg4NDI2MywxLjQwODMxODAxIDAuNDcwNTg4MjM1LDEuMTk3NjI4NDkgMC40NzA1ODgyMzUsMC45Mzc3Mjk3NzkgQzAuNDcwNTg4MjM1LDAuNjc3ODMxMDc0IDAuNjY4ODg0MjYzLDAuNDY3MTQxNTQ0IDAuOTEzNDk0ODEsMC40NjcxNDE1NDQgTDcuMDU3MDkzNDMsMC40NjcxNDE1NDQgQzcuMzMzMjM1OCwwLjQ2NzE0MTU0NCA3LjU1NzA5MzQzLDAuNjkwOTk5MTY5IDcuNTU3MDkzNDMsMC45NjcxNDE1NDQgTDcuNTU3MDkzNDMsMi43OTA2NzA5NiBDNy41NTcwOTM0MywzLjA2NjgxMzMzIDcuNzgwOTUxMDUsMy4yOTA2NzA5NiA4LjA1NzA5MzQzLDMuMjkwNjcwOTYgTDExLjQ4NjE1OTIsMy4yOTA2NzA5NiBDMTEuNzYyMzAxNSwzLjI5MDY3MDk2IDExLjk4NjE1OTIsMy41MTQ1Mjg1OCAxMS45ODYxNTkyLDMuNzkwNjcwOTYgTDExLjk4NjE1OTIsNS42MTQyMDAzNyBDMTEuOTg2MTU5Miw1Ljg5MDM0Mjc0IDEyLjIxMDAxNjgsNi4xMTQyMDAzNyAxMi40ODYxNTkyLDYuMTE0MjAwMzcgTDE1LjA4NjUwNTIsNi4xMTQyMDAzNyBDMTUuMzMxMTE1Nyw2LjExNDIwMDM3IDE1LjUyOTQxMTgsNi4zMjQ4ODk5IDE1LjUyOTQxMTgsNi41ODQ3ODg2IEMxNS41Mjk0MTE4LDYuODQ0Njg3MzEgMTUuMzMxMTE1Nyw3LjA1NTM3Njg0IDE1LjA4NjUwNTIsNy4wNTUzNzY4NCBMMTEuNjAwMzQ2LDcuMDU1Mzc2ODQgQzExLjMyNDIwMzYsNy4wNTUzNzY4NCAxMS4xMDAzNDYsNi44MzE1MTkyMSAxMS4xMDAzNDYsNi41NTUzNzY4NCBMMTEuMTAwMzQ2LDQuNzMxODQ3NDMgQzExLjEwMDM0Niw0LjQ1NTcwNTA1IDEwLjg3NjQ4ODQsNC4yMzE4NDc0MyAxMC42MDAzNDYsNC4yMzE4NDc0MyBMNy4xNzEyODAyOCw0LjIzMTg0NzQzIEM2Ljg5NTEzNzksNC4yMzE4NDc0MyA2LjY3MTI4MDI4LDQuMDA3OTg5OCA2LjY3MTI4MDI4LDMuNzMxODQ3NDMgTDYuNjcxMjgwMjgsMS45MDgzMTgwMSBDNi42NzEyODAyOCwxLjYzMjE3NTY0IDYuNDQ3NDIyNjUsMS40MDgzMTgwMSA2LjE3MTI4MDI4LDEuNDA4MzE4MDEgWiBNMi43OTQxMTc2NSwzLjI5MDY3MDk2IEwwLjk0MTE3NjQ3MSwzLjI5MDY3MDk2IEMwLjY4MTI3Nzc2NSwzLjI5MDY3MDk2IDAuNDcwNTg4MjM1LDMuMDc5OTgxNDMgMC40NzA1ODgyMzUsMi44MjAwODI3MiBDMC40NzA1ODgyMzUsMi41NjAxODQwMSAwLjY4MTI3Nzc2NSwyLjM0OTQ5NDQ5IDAuOTQxMTc2NDcxLDIuMzQ5NDk0NDkgTDMuNzM1Mjk0MTIsMi4zNDk0OTQ0OSBDNC4wMTE0MzY0OSwyLjM0OTQ5NDQ5IDQuMjM1Mjk0MTIsMi41NzMzNTIxMSA0LjIzNTI5NDEyLDIuODQ5NDk0NDkgTDQuMjM1Mjk0MTIsNy40OTY1NTMzMSBDNC4yMzUyOTQxMiw3Ljc3MjY5NTY4IDQuNDU5MTUxNzQsNy45OTY1NTMzMSA0LjczNTI5NDEyLDcuOTk2NTUzMzEgTDEwLjMyMzUyOTQsNy45OTY1NTMzMSBDMTAuNTk5NjcxOCw3Ljk5NjU1MzMxIDEwLjgyMzUyOTQsOC4yMjA0MTA5MyAxMC44MjM1Mjk0LDguNDk2NTUzMzEgTDEwLjgyMzUyOTQsMTEuMjYxMjU5MiBDMTAuODIzNTI5NCwxMS41Mzc0MDE2IDExLjA0NzM4NywxMS43NjEyNTkyIDExLjMyMzUyOTQsMTEuNzYxMjU5MiBMMTMuMTQ3MDU4OCwxMS43NjEyNTkyIEMxMy40MjMyMDEyLDExLjc2MTI1OTIgMTMuNjQ3MDU4OCwxMS45ODUxMTY4IDEzLjY0NzA1ODgsMTIuMjYxMjU5MiBMMTMuNjQ3MDU4OCwxNS4wNTUzNzY4IEMxMy42NDcwNTg4LDE1LjMxNTI3NTUgMTMuNDM2MzY5MywxNS41MjU5NjUxIDEzLjE3NjQ3MDYsMTUuNTI1OTY1MSBDMTIuOTE2NTcxOSwxNS41MjU5NjUxIDEyLjcwNTg4MjQsMTUuMzE1Mjc1NSAxMi43MDU4ODI0LDE1LjA1NTM3NjggTDEyLjcwNTg4MjQsMTMuMjAyNDM1NyBDMTIuNzA1ODgyNCwxMi45MjYyOTMzIDEyLjQ4MjAyNDcsMTIuNzAyNDM1NyAxMi4yMDU4ODI0LDEyLjcwMjQzNTcgTDEwLjM4MjM1MjksMTIuNzAyNDM1NyBDMTAuMTA2MjEwNiwxMi43MDI0MzU3IDkuODgyMzUyOTQsMTIuNDc4NTc4IDkuODgyMzUyOTQsMTIuMjAyNDM1NyBMOS44ODIzNTI5NCw5LjQzNzcyOTc4IEM5Ljg4MjM1Mjk0LDkuMTYxNTg3NCA5LjY1ODQ5NTMyLDguOTM3NzI5NzggOS4zODIzNTI5NCw4LjkzNzcyOTc4IEwzLjc5NDExNzY1LDguOTM3NzI5NzggQzMuNTE3OTc1MjcsOC45Mzc3Mjk3OCAzLjI5NDExNzY1LDguNzEzODcyMTUgMy4yOTQxMTc2NSw4LjQzNzcyOTc4IEwzLjI5NDExNzY1LDMuNzkwNjcwOTYgQzMuMjk0MTE3NjUsMy41MTQ1Mjg1OCAzLjA3MDI2MDAyLDMuMjkwNjcwOTYgMi43OTQxMTc2NSwzLjI5MDY3MDk2IFoiIGZpbGw9IiMwMDAiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==');
|
||||||
--icon-ChartLine: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTMuMTkwOTgzMDEsOCBMNS4wNTI3ODY0LDQuMjc2MzkzMiBDNS4xODcyODU0NCw0LjAwNzM5NTEyIDUuNTI3MTExODEsMy45MTcxNDkzMyA1Ljc3NzM1MDEsNC4wODM5NzQ4NSBMMTEuMzMxNjQ1NCw3Ljc4NjgzODM3IEwxNS4wNjU4Nzg0LDEuMjUxOTMwNTMgQzE1LjIwMjg4MzQsMS4wMTIxNzE4MSAxNS41MDgzMTA3LDAuOTI4ODczNDQ0IDE1Ljc0ODA2OTUsMS4wNjU4Nzg0MyBDMTUuOTg3ODI4MiwxLjIwMjg4MzQxIDE2LjA3MTEyNjYsMS41MDgzMTA3NSAxNS45MzQxMjE2LDEuNzQ4MDY5NDcgTDExLjkzNDEyMTYsOC43NDgwNjk0NyBDMTEuNzkwMzk3NCw4Ljk5OTU4Njc4IDExLjQ2MzY4MjcsOS4wNzY3MTM2NiAxMS4yMjI2NDk5LDguOTE2MDI1MTUgTDUuNjkzOTE1NzksNS4yMzAyMDI0MSBMNC4xMzgyODQyNCw4LjM0MTQ2NTUxIEwxMC40NDU5NTEzLDEyLjg0Njk0MiBMMTUuMTQ2NDQ2Niw4LjE0NjQ0NjYxIEMxNS4zNDE3MDg4LDcuOTUxMTg0NDYgMTUuNjU4MjkxMiw3Ljk1MTE4NDQ2IDE1Ljg1MzU1MzQsOC4xNDY0NDY2MSBDMTYuMDQ4ODE1NSw4LjM0MTcwODc2IDE2LjA0ODgxNTUsOC42NTgyOTEyNCAxNS44NTM1NTM0LDguODUzNTUzMzkgTDEwLjg1MzU1MzQsMTMuODUzNTUzNCBDMTAuNjgwNzIyNywxNC4wMjYzODQxIDEwLjQwODI3MzMsMTQuMDQ4OTMyNyAxMC4yMDkzODA5LDEzLjkwNjg2NjcgTDMuMzM5NzY3NDcsOSBMMC41LDkgQzAuMjIzODU3NjI1LDkgMS4xMTAyMjMwMmUtMTQsOC43NzYxNDIzNyAxLjExMDIyMzAyZS0xNCw4LjUgQzEuMTEwMjIzMDJlLTE0LDguMjIzODU3NjMgMC4yMjM4NTc2MjUsOCAwLjUsOCBMMy4xOTA5ODMwMSw4IFogTTAuOTQ3MjEzNTk1LDE0LjcyMzYwNjggQzAuODIzNzE4OTcxLDE0Ljk3MDU5NiAwLjUyMzM4MjQ1MSwxNS4wNzA3MDgyIDAuMjc2MzkzMjAyLDE0Ljk0NzIxMzYgQzAuMDI5NDAzOTUzNSwxNC44MjM3MTkgLTAuMDcwNzA4MjE5OSwxNC41MjMzODI1IDAuMDUyNzg2NDA0NSwxNC4yNzYzOTMyIEwxLjgwMjc4NjQsMTAuNzc2MzkzMiBDMS45MjYyODEwMywxMC41Mjk0MDQgMi4yMjY2MTc1NSwxMC40MjkyOTE4IDIuNDczNjA2OCwxMC41NTI3ODY0IEMyLjcyMDU5NjA1LDEwLjY3NjI4MSAyLjgyMDcwODIyLDEwLjk3NjYxNzUgMi42OTcyMTM2LDExLjIyMzYwNjggTDAuOTQ3MjEzNTk1LDE0LjcyMzYwNjggWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
--icon-ChartLine: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTMuMTkwOTgzMDEsOCBMNS4wNTI3ODY0LDQuMjc2MzkzMiBDNS4xODcyODU0NCw0LjAwNzM5NTEyIDUuNTI3MTExODEsMy45MTcxNDkzMyA1Ljc3NzM1MDEsNC4wODM5NzQ4NSBMMTEuMzMxNjQ1NCw3Ljc4NjgzODM3IEwxNS4wNjU4Nzg0LDEuMjUxOTMwNTMgQzE1LjIwMjg4MzQsMS4wMTIxNzE4MSAxNS41MDgzMTA3LDAuOTI4ODczNDQ0IDE1Ljc0ODA2OTUsMS4wNjU4Nzg0MyBDMTUuOTg3ODI4MiwxLjIwMjg4MzQxIDE2LjA3MTEyNjYsMS41MDgzMTA3NSAxNS45MzQxMjE2LDEuNzQ4MDY5NDcgTDExLjkzNDEyMTYsOC43NDgwNjk0NyBDMTEuNzkwMzk3NCw4Ljk5OTU4Njc4IDExLjQ2MzY4MjcsOS4wNzY3MTM2NiAxMS4yMjI2NDk5LDguOTE2MDI1MTUgTDUuNjkzOTE1NzksNS4yMzAyMDI0MSBMNC4xMzgyODQyNCw4LjM0MTQ2NTUxIEwxMC40NDU5NTEzLDEyLjg0Njk0MiBMMTUuMTQ2NDQ2Niw4LjE0NjQ0NjYxIEMxNS4zNDE3MDg4LDcuOTUxMTg0NDYgMTUuNjU4MjkxMiw3Ljk1MTE4NDQ2IDE1Ljg1MzU1MzQsOC4xNDY0NDY2MSBDMTYuMDQ4ODE1NSw4LjM0MTcwODc2IDE2LjA0ODgxNTUsOC42NTgyOTEyNCAxNS44NTM1NTM0LDguODUzNTUzMzkgTDEwLjg1MzU1MzQsMTMuODUzNTUzNCBDMTAuNjgwNzIyNywxNC4wMjYzODQxIDEwLjQwODI3MzMsMTQuMDQ4OTMyNyAxMC4yMDkzODA5LDEzLjkwNjg2NjcgTDMuMzM5NzY3NDcsOSBMMC41LDkgQzAuMjIzODU3NjI1LDkgMS4xMTAyMjMwMmUtMTQsOC43NzYxNDIzNyAxLjExMDIyMzAyZS0xNCw4LjUgQzEuMTEwMjIzMDJlLTE0LDguMjIzODU3NjMgMC4yMjM4NTc2MjUsOCAwLjUsOCBMMy4xOTA5ODMwMSw4IFogTTAuOTQ3MjEzNTk1LDE0LjcyMzYwNjggQzAuODIzNzE4OTcxLDE0Ljk3MDU5NiAwLjUyMzM4MjQ1MSwxNS4wNzA3MDgyIDAuMjc2MzkzMjAyLDE0Ljk0NzIxMzYgQzAuMDI5NDAzOTUzNSwxNC44MjM3MTkgLTAuMDcwNzA4MjE5OSwxNC41MjMzODI1IDAuMDUyNzg2NDA0NSwxNC4yNzYzOTMyIEwxLjgwMjc4NjQsMTAuNzc2MzkzMiBDMS45MjYyODEwMywxMC41Mjk0MDQgMi4yMjY2MTc1NSwxMC40MjkyOTE4IDIuNDczNjA2OCwxMC41NTI3ODY0IEMyLjcyMDU5NjA1LDEwLjY3NjI4MSAyLjgyMDcwODIyLDEwLjk3NjYxNzUgMi42OTcyMTM2LDExLjIyMzYwNjggTDAuOTQ3MjEzNTk1LDE0LjcyMzYwNjggWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
||||||
--icon-ChartPie: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0LjUyODEyNzMsMTMuMjgxNjQ4NCBDMTQuMzcyNjg4LDEzLjUwOTY0OTcgMTQuMDYxOTI1OSwxMy41Njg2MjA0IDEzLjgzMzc2ODEsMTMuNDEzNDEwOSBMNy4yMTg3NjgwNyw4LjkxMzQxMDk0IEM3LjA4MTkxMjk3LDguODIwMzEyMjMgNyw4LjY2NTUxOTQ1IDcsOC41IEw3LDAuNSBDNywwLjIyMzg1NzYyNSA3LjIyMzg1NzYzLDEuOTUzOTkyNTJlLTE0IDcuNSwxLjk1Mzk5MjUyZS0xNCBDMTIuMTk0MTQyNCwxLjk1Mzk5MjUyZS0xNCAxNiwzLjgwNTg1NzYzIDE2LDguNSBDMTYsMTAuMjI4OTkzOCAxNS40ODE2NTQ5LDExLjg4Mjk5NTggMTQuNTI4MTI3MywxMy4yODE2NDg0IFogTTE1LDguNSBDMTUsNC41MjYxNTU5MyAxMS45MDg3NzY0LDEuMjczNzM0MjMgOCwxLjAxNjQwNTY0IEw4LDguMjM1NDEwODggTDEzLjk2OTUxLDEyLjI5NjMwMjEgQzE0LjYzOTUzNDIsMTEuMTU3NTgxNSAxNSw5Ljg1NTc3OTE2IDE1LDguNSBaIE0xMC42OTIxMTU2LDEzLjczMDAzNjYgQzEwLjkwOTY5NTYsMTMuNTU5OTk2NyAxMS4yMjM5MjM2LDEzLjU5ODUzNTYgMTEuMzkzOTYzNCwxMy44MTYxMTU2IEMxMS41NjQwMDMzLDE0LjAzMzY5NTYgMTEuNTI1NDY0NCwxNC4zNDc5MjM2IDExLjMwNzg4NDQsMTQuNTE3OTYzNCBDMTAuMDg2MjU5NiwxNS40NzI2NjkzIDguNTgyOTQ4NjMsMTYgNywxNiBDMy4xMzM4NTc2MywxNiA4LjQzNzY5NDk5ZS0xNCwxMi44NjYxNDI0IDguNDM3Njk0OTllLTE0LDkgQzguNDM3Njk0OTllLTE0LDUuOTQwODEwMzkgMS45ODA0ODY2OSwzLjI2MzQ4MDA1IDQuODQ2Mzc2MTUsMi4zMzgxODUyMSBDNS4xMDkxNjE0LDIuMjUzMzQxMSA1LjM5MDk3MDY4LDIuMzk3NTkwOSA1LjQ3NTgxNDc5LDIuNjYwMzc2MTUgQzUuNTYwNjU4OSwyLjkyMzE2MTQgNS40MTY0MDkxLDMuMjA0OTcwNjggNS4xNTM2MjM4NSwzLjI4OTgxNDc5IEMyLjY5Nzc1MTc3LDQuMDgyNzI5NDQgMSw2LjM3Nzg0MzI0IDEsOSBDMSwxMi4zMTM4NTc2IDMuNjg2MTQyMzcsMTUgNywxNSBDOC4zNTc3NDM0MywxNSA5LjY0NDc4MTQsMTQuNTQ4NTMzNSAxMC42OTIxMTU2LDEzLjczMDAzNjYgWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
--icon-ChartPie: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0LjUyODEyNzMsMTMuMjgxNjQ4NCBDMTQuMzcyNjg4LDEzLjUwOTY0OTcgMTQuMDYxOTI1OSwxMy41Njg2MjA0IDEzLjgzMzc2ODEsMTMuNDEzNDEwOSBMNy4yMTg3NjgwNyw4LjkxMzQxMDk0IEM3LjA4MTkxMjk3LDguODIwMzEyMjMgNyw4LjY2NTUxOTQ1IDcsOC41IEw3LDAuNSBDNywwLjIyMzg1NzYyNSA3LjIyMzg1NzYzLDEuOTUzOTkyNTJlLTE0IDcuNSwxLjk1Mzk5MjUyZS0xNCBDMTIuMTk0MTQyNCwxLjk1Mzk5MjUyZS0xNCAxNiwzLjgwNTg1NzYzIDE2LDguNSBDMTYsMTAuMjI4OTkzOCAxNS40ODE2NTQ5LDExLjg4Mjk5NTggMTQuNTI4MTI3MywxMy4yODE2NDg0IFogTTE1LDguNSBDMTUsNC41MjYxNTU5MyAxMS45MDg3NzY0LDEuMjczNzM0MjMgOCwxLjAxNjQwNTY0IEw4LDguMjM1NDEwODggTDEzLjk2OTUxLDEyLjI5NjMwMjEgQzE0LjYzOTUzNDIsMTEuMTU3NTgxNSAxNSw5Ljg1NTc3OTE2IDE1LDguNSBaIE0xMC42OTIxMTU2LDEzLjczMDAzNjYgQzEwLjkwOTY5NTYsMTMuNTU5OTk2NyAxMS4yMjM5MjM2LDEzLjU5ODUzNTYgMTEuMzkzOTYzNCwxMy44MTYxMTU2IEMxMS41NjQwMDMzLDE0LjAzMzY5NTYgMTEuNTI1NDY0NCwxNC4zNDc5MjM2IDExLjMwNzg4NDQsMTQuNTE3OTYzNCBDMTAuMDg2MjU5NiwxNS40NzI2NjkzIDguNTgyOTQ4NjMsMTYgNywxNiBDMy4xMzM4NTc2MywxNiA4LjQzNzY5NDk5ZS0xNCwxMi44NjYxNDI0IDguNDM3Njk0OTllLTE0LDkgQzguNDM3Njk0OTllLTE0LDUuOTQwODEwMzkgMS45ODA0ODY2OSwzLjI2MzQ4MDA1IDQuODQ2Mzc2MTUsMi4zMzgxODUyMSBDNS4xMDkxNjE0LDIuMjUzMzQxMSA1LjM5MDk3MDY4LDIuMzk3NTkwOSA1LjQ3NTgxNDc5LDIuNjYwMzc2MTUgQzUuNTYwNjU4OSwyLjkyMzE2MTQgNS40MTY0MDkxLDMuMjA0OTcwNjggNS4xNTM2MjM4NSwzLjI4OTgxNDc5IEMyLjY5Nzc1MTc3LDQuMDgyNzI5NDQgMSw2LjM3Nzg0MzI0IDEsOSBDMSwxMi4zMTM4NTc2IDMuNjg2MTQyMzcsMTUgNywxNSBDOC4zNTc3NDM0MywxNSA5LjY0NDc4MTQsMTQuNTQ4NTMzNSAxMC42OTIxMTU2LDEzLjczMDAzNjYgWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
|
||||||
|
56
static/ui-icons/Charts/ChartDonut.svg
Normal file
56
static/ui-icons/Charts/ChartDonut.svg
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg874"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<defs
|
||||||
|
id="defs878" />
|
||||||
|
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title
|
||||||
|
id="title868">Icons / Charts / ChartPie</title>
|
||||||
|
<desc
|
||||||
|
id="desc870">Created with Sketch.</desc>
|
||||||
|
<g
|
||||||
|
id="Icons-/-Charts-/-ChartPie"
|
||||||
|
stroke="none"
|
||||||
|
stroke-width="1"
|
||||||
|
fill="none"
|
||||||
|
fill-rule="evenodd">
|
||||||
|
<circle
|
||||||
|
style="fill:none;stroke:#1c1303;stroke-width:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
id="path1001"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="7.5" />
|
||||||
|
<circle
|
||||||
|
style="fill:none;stroke:#1c1303;stroke-width:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
id="circle1473"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="5" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 7.8840618,0.59987427 V 3.3421567"
|
||||||
|
id="path1508" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 11.611852,11.526156 1.885319,1.885319"
|
||||||
|
id="path1510" />
|
||||||
|
</g>
|
||||||
|
<metadata
|
||||||
|
id="metadata1113">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:title>Icons / Charts / ChartPie</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in New Issue
Block a user