Обновлены пакеты

This commit is contained in:
goodmice 2022-10-03 20:17:58 +05:00
parent 01f499b85d
commit b2feb95e82
No known key found for this signature in database
GPG Key ID: 63EA771203189CF1
15 changed files with 7404 additions and 5180 deletions

12463
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ import {
D3TooltipSettings, D3TooltipSettings,
} from './plugins' } from './plugins'
import type { import type {
BaseDataType,
ChartAxis, ChartAxis,
ChartDataset, ChartDataset,
ChartDomain, ChartDomain,
@ -50,13 +51,13 @@ export const getByAccessor = <DataType extends Record<any, any>, R>(accessor: ke
return (d) => d[accessor] return (d) => d[accessor]
} }
const createAxis = <DataType,>(config: ChartAxis<DataType>) => { const createAxis = <DataType extends BaseDataType>(config: ChartAxis<DataType>) => {
if (config.type === 'time') if (config.type === 'time')
return d3.scaleTime() return d3.scaleTime()
return d3.scaleLinear() return d3.scaleLinear()
} }
export type D3ChartProps<DataType> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & { export type D3ChartProps<DataType extends BaseDataType> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
/** Параметры общей горизонтальной оси */ /** Параметры общей горизонтальной оси */
xAxis: ChartAxis<DataType> xAxis: ChartAxis<DataType>
/** Параметры графиков */ /** Параметры графиков */
@ -94,7 +95,7 @@ export type D3ChartProps<DataType> = React.DetailedHTMLProps<React.HTMLAttribute
} }
} }
const getDefaultXAxisConfig = <DataType,>(): ChartAxis<DataType> => ({ const getDefaultXAxisConfig = <DataType extends BaseDataType>(): ChartAxis<DataType> => ({
type: 'time', type: 'time',
accessor: (d: any) => new Date(d.date) accessor: (d: any) => new Date(d.date)
}) })

View File

@ -6,13 +6,14 @@ import { useD3MouseZone } from '@components/d3/D3MouseZone'
import { D3TooltipPosition } from '@components/d3/plugins/D3Tooltip' import { D3TooltipPosition } from '@components/d3/plugins/D3Tooltip'
import { getChartIcon, isDev, usePartialProps } from '@utils' import { getChartIcon, isDev, usePartialProps } from '@utils'
import { BaseDataType } from '../types'
import { ChartGroup, ChartSizes } from './D3MonitoringCharts' import { ChartGroup, ChartSizes } from './D3MonitoringCharts'
import '@styles/d3.less' import '@styles/d3.less'
type D3GroupRenderFunction<DataType> = (group: ChartGroup<DataType>, data: DataType[]) => ReactNode type D3GroupRenderFunction<DataType extends BaseDataType> = (group: ChartGroup<DataType>, data: DataType[]) => ReactNode
export type D3HorizontalCursorSettings<DataType> = { export type D3HorizontalCursorSettings<DataType extends BaseDataType> = {
width?: number width?: number
height?: number height?: number
render?: D3GroupRenderFunction<DataType> render?: D3GroupRenderFunction<DataType>
@ -23,7 +24,7 @@ export type D3HorizontalCursorSettings<DataType> = {
lineStyle?: SVGProps<SVGLineElement> lineStyle?: SVGProps<SVGLineElement>
} }
export type D3HorizontalCursorProps<DataType> = D3HorizontalCursorSettings<DataType> & { export type D3HorizontalCursorProps<DataType extends BaseDataType> = D3HorizontalCursorSettings<DataType> & {
groups: ChartGroup<DataType>[] groups: ChartGroup<DataType>[]
data: DataType[] data: DataType[]
sizes: ChartSizes sizes: ChartSizes
@ -37,7 +38,7 @@ const defaultLineStyle: SVGProps<SVGLineElement> = {
const offsetY = 5 const offsetY = 5
const makeDefaultRender = <DataType,>(): D3GroupRenderFunction<DataType> => (group, data) => ( const makeDefaultRender = <DataType extends BaseDataType>(): D3GroupRenderFunction<DataType> => (group, data) => (
<> <>
{data.length > 0 ? group.charts.map((chart) => { {data.length > 0 ? group.charts.map((chart) => {
const xFormat = (d: number | Date) => chart.xAxis.format?.(d) ?? `${(+d).toFixed(2)} ${chart.xAxis.unit ?? ''}` const xFormat = (d: number | Date) => chart.xAxis.format?.(d) ?? `${(+d).toFixed(2)} ${chart.xAxis.unit ?? ''}`
@ -62,7 +63,7 @@ const makeDefaultRender = <DataType,>(): D3GroupRenderFunction<DataType> => (gro
</> </>
) )
const _D3HorizontalCursor = <DataType,>({ const _D3HorizontalCursor = <DataType extends BaseDataType>({
spaceBetweenGroups = 30, spaceBetweenGroups = 30,
height = 200, height = 200,
render = makeDefaultRender<DataType>(), render = makeDefaultRender<DataType>(),

View File

@ -1,7 +1,7 @@
import { Button, Checkbox, Form, FormItemProps, Input, InputNumber, Select, Tooltip } from 'antd' import { Button, Checkbox, Form, FormItemProps, Input, InputNumber, Select, Tooltip } from 'antd'
import { memo, useCallback, useEffect, useMemo } from 'react' import { memo, useCallback, useEffect, useMemo } from 'react'
import { MinMax } from '@components/d3/types' import { BaseDataType, MinMax } from '@components/d3/types'
import { ColorPicker, Color } from '@components/ColorPicker' import { ColorPicker, Color } from '@components/ColorPicker'
import { ExtendedChartDataset } from './D3MonitoringCharts' import { ExtendedChartDataset } from './D3MonitoringCharts'
@ -18,13 +18,13 @@ const lineTypes = [
{ value: 'needle', label: 'Иглы' }, { value: 'needle', label: 'Иглы' },
] ]
export type D3MonitoringChartEditorProps<DataType> = { export type D3MonitoringChartEditorProps<DataType extends BaseDataType> = {
group: ExtendedChartDataset<DataType>[] group: ExtendedChartDataset<DataType>[]
chart: ExtendedChartDataset<DataType> chart: ExtendedChartDataset<DataType>
onChange: (value: ExtendedChartDataset<DataType>) => boolean onChange: (value: ExtendedChartDataset<DataType>) => boolean
} }
const _D3MonitoringChartEditor = <DataType,>({ const _D3MonitoringChartEditor = <DataType extends BaseDataType>({
group, group,
chart: value, chart: value,
onChange, onChange,
@ -93,8 +93,8 @@ const _D3MonitoringChartEditor = <DataType,>({
</Item> </Item>
<Item label={'Диапазон'}> <Item label={'Диапазон'}>
<Input.Group compact> <Input.Group compact>
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.min} onChange={(min) => onDomainChange({ min })} placeholder={'Мин'} /> <InputNumber disabled={!!value.linkedTo} value={value.xDomain?.min} onChange={(min) => onDomainChange({ min: min ?? undefined })} placeholder={'Мин'} />
<InputNumber disabled={!!value.linkedTo} value={value.xDomain?.max} onChange={(max) => onDomainChange({ max })} placeholder={'Макс'} /> <InputNumber disabled={!!value.linkedTo} value={value.xDomain?.max} onChange={(max) => onDomainChange({ max: max ?? undefined })} placeholder={'Макс'} />
<Button <Button
disabled={!!value.linkedTo || (!Number.isFinite(value.xDomain?.min) && !Number.isFinite(value.xDomain?.max))} disabled={!!value.linkedTo || (!Number.isFinite(value.xDomain?.min) && !Number.isFinite(value.xDomain?.max))}
onClick={() => onDomainChange({ min: undefined, max: undefined })} onClick={() => onDomainChange({ min: undefined, max: undefined })}

View File

@ -8,6 +8,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { isDev, usePartialProps, useUserSettings } from '@utils' import { isDev, usePartialProps, useUserSettings } from '@utils'
import { import {
BaseDataType,
ChartAxis, ChartAxis,
ChartDataset, ChartDataset,
ChartOffset, ChartOffset,
@ -51,7 +52,7 @@ const calculateDomain = (mm: MinMax): Required<MinMax> => {
return { min, max } return { min, max }
} }
export type ExtendedChartDataset<DataType> = ChartDataset<DataType> & { export type ExtendedChartDataset<DataType extends BaseDataType> = ChartDataset<DataType> & {
/** Диапазон отображаемых значений по горизонтальной оси */ /** Диапазон отображаемых значений по горизонтальной оси */
xDomain: MinMax xDomain: MinMax
/** Скрыть отображение шкалы графика */ /** Скрыть отображение шкалы графика */
@ -60,9 +61,9 @@ export type ExtendedChartDataset<DataType> = ChartDataset<DataType> & {
showCurrentValue?: boolean showCurrentValue?: boolean
} }
export type ExtendedChartRegistry<DataType> = ChartRegistry<DataType> & ExtendedChartDataset<DataType> export type ExtendedChartRegistry<DataType extends BaseDataType> = ChartRegistry<DataType> & ExtendedChartDataset<DataType>
export type ChartGroup<DataType> = { export type ChartGroup<DataType extends BaseDataType> = {
/** Получить D3 выборку, содержащую корневой G-элемент группы */ /** Получить D3 выборку, содержащую корневой G-элемент группы */
(): d3.Selection<SVGGElement, any, any, any> (): d3.Selection<SVGGElement, any, any, any>
/** Уникальный ключ группы (индекс) */ /** Уникальный ключ группы (индекс) */
@ -86,12 +87,12 @@ const defaultRegulators: TelemetryRegulators = {
5: { color: '#007070', label: 'Расход' }, 5: { color: '#007070', label: 'Расход' },
} }
const getDefaultYAxisConfig = <DataType,>(): ChartAxis<DataType> => ({ const getDefaultYAxisConfig = <DataType extends BaseDataType>(): ChartAxis<DataType> => ({
type: 'time', type: 'time',
accessor: (d: any) => new Date(d.date) accessor: (d: any) => new Date(d.date)
}) })
const getDefaultYTicks = <DataType,>(): Required<ChartTick<DataType>> => ({ const getDefaultYTicks = <DataType extends BaseDataType>(): Required<ChartTick<DataType>> => ({
visible: false, visible: false,
format: (d: d3.NumberValue, idx: number, data?: DataType) => String(d), format: (d: d3.NumberValue, idx: number, data?: DataType) => String(d),
color: 'lightgray', color: 'lightgray',
@ -101,7 +102,7 @@ const getDefaultYTicks = <DataType,>(): Required<ChartTick<DataType>> => ({
/** /**
* @template DataType тип данных отображаемых записей * @template DataType тип данных отображаемых записей
*/ */
export type D3MonitoringChartsProps<DataType extends Record<string, any>> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> & { export type D3MonitoringChartsProps<DataType extends BaseDataType> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> & {
/** Двумерный массив датасетов (группа-график) */ /** Двумерный массив датасетов (группа-график) */
datasetGroups: ExtendedChartDataset<DataType>[][] datasetGroups: ExtendedChartDataset<DataType>[][]
/** Ширина графика числом пикселей или CSS-значением (px/%/em/rem) */ /** Ширина графика числом пикселей или CSS-значением (px/%/em/rem) */

View File

@ -1,9 +1,10 @@
import { memo } from 'react' import { memo } from 'react'
import { BaseDataType } from '@components/d3/types'
import { ChartGroup, ChartSizes } from '@components/d3/monitoring/D3MonitoringCharts' import { ChartGroup, ChartSizes } from '@components/d3/monitoring/D3MonitoringCharts'
import { makeDisplayValue } from '@utils' import { makeDisplayValue } from '@utils'
export type D3MonitoringCurrentValuesProps<DataType> = { export type D3MonitoringCurrentValuesProps<DataType extends BaseDataType> = {
groups: ChartGroup<DataType>[] groups: ChartGroup<DataType>[]
data: DataType[] data: DataType[]
left: number left: number
@ -12,7 +13,7 @@ export type D3MonitoringCurrentValuesProps<DataType> = {
const display = makeDisplayValue({ def: '---', fixed: 2 }) const display = makeDisplayValue({ def: '---', fixed: 2 })
const _D3MonitoringCurrentValues = <DataType,>({ groups, data, left, sizes }: D3MonitoringCurrentValuesProps<DataType>) => ( const _D3MonitoringCurrentValues = <DataType extends BaseDataType>({ groups, data, left, sizes }: D3MonitoringCurrentValuesProps<DataType>) => (
<g transform={`translate(${left}, ${sizes.chartsTop})`} pointerEvents={'none'}> <g transform={`translate(${left}, ${sizes.chartsTop})`} pointerEvents={'none'}>
{groups.map((group) => ( {groups.map((group) => (
<g key={group.key} transform={`translate(${sizes.groupLeft(group.key)}, 0)`}> <g key={group.key} transform={`translate(${sizes.groupLeft(group.key)}, 0)`}>

View File

@ -1,17 +1,18 @@
import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useState } from 'react' import { CSSProperties, Key, memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Button, Divider, Empty, Modal, Popconfirm, Tooltip, Tree } from 'antd' import { Button, Divider, Empty, Modal, Popconfirm, Tooltip, Tree, TreeDataNode } from 'antd'
import { UndoOutlined } from '@ant-design/icons' import { UndoOutlined } from '@ant-design/icons'
import { EventDataNode } from 'antd/lib/tree' import { EventDataNode } from 'antd/lib/tree'
import { notify } from '@components/factory' import { notify } from '@components/factory'
import { getChartIcon } from '@utils' import { getChartIcon } from '@utils'
import { BaseDataType } from '../types'
import { ExtendedChartDataset } from './D3MonitoringCharts' import { ExtendedChartDataset } from './D3MonitoringCharts'
import { TelemetryRegulators } from './D3MonitoringLimitChart' import { TelemetryRegulators } from './D3MonitoringLimitChart'
import D3MonitoringChartEditor from './D3MonitoringChartEditor' import D3MonitoringChartEditor from './D3MonitoringChartEditor'
import D3MonitoringLimitEditor from './D3MonitoringLimitEditor' import D3MonitoringLimitEditor from './D3MonitoringLimitEditor'
export type D3MonitoringGroupsEditorProps<DataType> = { export type D3MonitoringGroupsEditorProps<DataType extends BaseDataType> = {
visible?: boolean visible?: boolean
groups: ExtendedChartDataset<DataType>[][] groups: ExtendedChartDataset<DataType>[][]
regulators: TelemetryRegulators regulators: TelemetryRegulators
@ -20,7 +21,7 @@ export type D3MonitoringGroupsEditorProps<DataType> = {
onReset: () => void onReset: () => void
} }
const getChartLabel = <DataType,>(chart: ExtendedChartDataset<DataType>) => ( const getChartLabel = <DataType extends BaseDataType>(chart: ExtendedChartDataset<DataType>) => (
<Tooltip title={chart.label}> <Tooltip title={chart.label}>
{getChartIcon(chart)} {chart.label} {getChartIcon(chart)} {chart.label}
</Tooltip> </Tooltip>
@ -34,14 +35,14 @@ const divStyle: CSSProperties = {
flexGrow: 1, flexGrow: 1,
} }
const getNodePos = (node: EventDataNode): { group: number, chart?: number } => { const getNodePos = (node: EventDataNode<TreeDataNode>): { group: number, chart?: number } => {
const out = node.pos.split('-').map(Number) const out = node.pos.split('-').map(Number)
return { group: out[1], chart: out[2] } return { group: out[1], chart: out[2] }
} }
type EditingMode = null | 'limit' | 'chart' type EditingMode = null | 'limit' | 'chart'
const _D3MonitoringEditor = <DataType,>({ const _D3MonitoringEditor = <DataType extends BaseDataType>({
visible, visible,
groups: oldGroups, groups: oldGroups,
regulators: oldRegulators, regulators: oldRegulators,
@ -61,8 +62,8 @@ const _D3MonitoringEditor = <DataType,>({
const onModalOk = useCallback(() => onChange(groups, regulators), [groups, regulators]) const onModalOk = useCallback(() => onChange(groups, regulators), [groups, regulators])
const onDrop = useCallback((info: { const onDrop = useCallback((info: {
node: EventDataNode node: EventDataNode<TreeDataNode>
dragNode: EventDataNode dragNode: EventDataNode<TreeDataNode>
dropPosition: number dropPosition: number
}) => { }) => {
const { dragNode, dropPosition, node } = info const { dragNode, dropPosition, node } = info
@ -152,12 +153,12 @@ const _D3MonitoringEditor = <DataType,>({
<Tree <Tree
draggable draggable
selectable selectable
onExpand={(keys) => setExpand(keys)} onExpand={(keys: Key[]) => setExpand(keys)}
expandedKeys={expand} expandedKeys={expand}
selectedKeys={selected} selectedKeys={selected}
treeData={treeItems} treeData={treeItems}
onDrop={onDrop} onDrop={onDrop}
onSelect={(value) => { onSelect={(value: Key[]) => {
setSelected(value) setSelected(value)
setMode('chart') setMode('chart')
}} }}

View File

@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef } from 'react'
import { Property } from 'csstype' import { Property } from 'csstype'
import * as d3 from 'd3' import * as d3 from 'd3'
import { ChartRegistry } from '@components/d3/types' import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { useD3MouseZone } from '@components/d3/D3MouseZone' import { useD3MouseZone } from '@components/d3/D3MouseZone'
import { usePartialProps } from '@utils' import { usePartialProps } from '@utils'
@ -32,12 +32,12 @@ export type D3LegendSettings = {
const defaultOffset = { x: 10, y: 10 } const defaultOffset = { x: 10, y: 10 }
export type D3LegendProps<DataType> = D3LegendSettings & { export type D3LegendProps<DataType extends BaseDataType> = D3LegendSettings & {
/** Массив графиков */ /** Массив графиков */
charts: ChartRegistry<DataType>[] charts: ChartRegistry<DataType>[]
} }
const _D3Legend = <DataType,>({ const _D3Legend = <DataType extends BaseDataType>({
charts, charts,
width, width,
height, height,

View File

@ -4,7 +4,7 @@ import * as d3 from 'd3'
import { isDev } from '@utils' import { isDev } from '@utils'
import { ChartRegistry } from '@components/d3/types' import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { D3MouseState, useD3MouseZone } from '@components/d3/D3MouseZone' import { D3MouseState, useD3MouseZone } from '@components/d3/D3MouseZone'
import { getTouchedElements, wrapPlugin } from './base' import { getTouchedElements, wrapPlugin } from './base'
@ -12,7 +12,7 @@ import '@styles/d3.less'
export type D3TooltipPosition = 'bottom' | 'top' | 'left' | 'right' | 'none' export type D3TooltipPosition = 'bottom' | 'top' | 'left' | 'right' | 'none'
export type D3RenderData<DataType> = { export type D3RenderData<DataType extends BaseDataType> = {
/** Параметры графика */ /** Параметры графика */
chart: ChartRegistry<DataType> chart: ChartRegistry<DataType>
/** Данные графика */ /** Данные графика */
@ -21,9 +21,9 @@ export type D3RenderData<DataType> = {
selection?: d3.Selection<any, DataType, any, any> selection?: d3.Selection<any, DataType, any, any>
} }
export type D3RenderFunction<DataType> = (data: D3RenderData<DataType>[], mouseState: D3MouseState) => ReactNode export type D3RenderFunction<DataType extends BaseDataType> = (data: D3RenderData<DataType>[], mouseState: D3MouseState) => ReactNode
export type D3TooltipSettings<DataType> = { export type D3TooltipSettings<DataType extends BaseDataType> = {
/** Функция отрисоки тултипа */ /** Функция отрисоки тултипа */
render?: D3RenderFunction<DataType> render?: D3RenderFunction<DataType>
/** Ширина тултипа */ /** Ширина тултипа */
@ -39,7 +39,7 @@ export type D3TooltipSettings<DataType> = {
limit?: number limit?: number
} }
export const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (data, mouseState) => ( export const makeDefaultRender = <DataType extends BaseDataType>(): D3RenderFunction<DataType> => (data, mouseState) => (
<> <>
{data.length > 0 ? data.map(({ chart, data }) => { {data.length > 0 ? data.map(({ chart, data }) => {
let Icon let Icon
@ -74,11 +74,11 @@ export const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (d
</> </>
) )
export type D3TooltipProps<DataType> = Partial<D3TooltipSettings<DataType>> & { export type D3TooltipProps<DataType extends BaseDataType> = Partial<D3TooltipSettings<DataType>> & {
charts: ChartRegistry<DataType>[], charts: ChartRegistry<DataType>[],
} }
function _D3Tooltip<DataType extends Record<string, unknown>>({ function _D3Tooltip<DataType extends BaseDataType>({
width = 200, width = 200,
height = 120, height = 120,
render = makeDefaultRender<DataType>(), render = makeDefaultRender<DataType>(),

View File

@ -3,7 +3,7 @@ import * as d3 from 'd3'
import { getDistance, TouchType } from '@utils' import { getDistance, TouchType } from '@utils'
import { ChartRegistry } from '../types' import { BaseDataType, ChartRegistry } from '../types'
export type BasePluginSettings = { export type BasePluginSettings = {
enabled?: boolean enabled?: boolean
@ -16,7 +16,7 @@ export const wrapPlugin = <TProps,>(
const wrappedComponent = ({ enabled, ...props }: TProps & BasePluginSettings) => { const wrappedComponent = ({ enabled, ...props }: TProps & BasePluginSettings) => {
if (!(enabled ?? defaultEnabled)) return <></> if (!(enabled ?? defaultEnabled)) return <></>
return <Component {...(props as TProps)} /> return <Component {...(props as (TProps & JSX.IntrinsicAttributes))} /> // IntrinsicAttributes добавлено как необходимое ограничение
} }
return wrappedComponent return wrappedComponent
@ -89,7 +89,7 @@ const makeIsRectTouched = (x: number, y: number, limit: number, type: TouchType
} }
} }
export const getTouchedElements = <DataType,>( export const getTouchedElements = <DataType extends BaseDataType>(
chart: ChartRegistry<DataType>, chart: ChartRegistry<DataType>,
x: number, x: number,
y: number, y: number,

View File

@ -1,8 +1,8 @@
import * as d3 from 'd3' import * as d3 from 'd3'
import { ChartRegistry } from '../types' import { BaseDataType, ChartRegistry } from '../types'
export const appendTransition = <DataType, BaseType extends d3.BaseType, Datum, PElement extends d3.BaseType, PDatum>( export const appendTransition = <DataType extends BaseDataType, BaseType extends d3.BaseType, Datum, PElement extends d3.BaseType, PDatum>(
elms: d3.Selection<BaseType, Datum, PElement, PDatum>, elms: d3.Selection<BaseType, Datum, PElement, PDatum>,
chart: ChartRegistry<DataType> chart: ChartRegistry<DataType>
): d3.Selection<BaseType, Datum, PElement, PDatum> => { ): d3.Selection<BaseType, Datum, PElement, PDatum> => {

View File

@ -1,4 +1,4 @@
import { ChartRegistry, PointChartDataset } from '@components/d3/types' import { BaseDataType, ChartRegistry, PointChartDataset } from '@components/d3/types'
import { appendTransition } from './base' import { appendTransition } from './base'
@ -12,7 +12,7 @@ const defaultConfig: Required<Omit<PointChartDataset, 'type'>> = {
fillOpacity: 1, fillOpacity: 1,
} }
const getPointsRoot = <DataType,>(chart: ChartRegistry<DataType>, embeded?: boolean): d3.Selection<SVGGElement, any, any, any> => { const getPointsRoot = <DataType extends BaseDataType>(chart: ChartRegistry<DataType>, embeded?: boolean): d3.Selection<SVGGElement, any, any, any> => {
const root = chart() const root = chart()
if (!embeded) return root if (!embeded) return root
if (root.select('.points').empty()) if (root.select('.points').empty())

View File

@ -1,9 +1,9 @@
import { getByAccessor } from '@components/d3/functions' import { getByAccessor } from '@components/d3/functions'
import { ChartRegistry } from '@components/d3/types' import { BaseDataType, ChartRegistry } from '@components/d3/types'
import { appendTransition } from './base' import { appendTransition } from './base'
export const renderRectArea = <DataType extends Record<string, any>>( export const renderRectArea = <DataType extends BaseDataType>(
xAxis: (value: d3.NumberValue) => number, xAxis: (value: d3.NumberValue) => number,
yAxis: (value: d3.NumberValue) => number, yAxis: (value: d3.NumberValue) => number,
chart: ChartRegistry<DataType> chart: ChartRegistry<DataType>

View File

@ -3,9 +3,11 @@ import { Property } from 'csstype'
import { D3TooltipSettings } from './plugins' import { D3TooltipSettings } from './plugins'
export type AxisAccessor<DataType extends Record<string, any>> = keyof DataType | ((d: DataType) => any) export type BaseDataType = Record<string, any>
export type ChartAxis<DataType> = { export type AxisAccessor<DataType extends BaseDataType> = keyof DataType | ((d: DataType) => any)
export type ChartAxis<DataType extends BaseDataType> = {
/** Тип шкалы */ /** Тип шкалы */
type: 'linear' | 'time', type: 'linear' | 'time',
/** Ключ записи или метод по которому будет извлекаться значение оси из массива данных */ /** Ключ записи или метод по которому будет извлекаться значение оси из массива данных */
@ -34,7 +36,7 @@ export type PointChartDataset = {
fillOpacity?: number fillOpacity?: number
} }
export type BaseChartDataset<DataType> = { export type BaseChartDataset<DataType extends BaseDataType> = {
/** Уникальный ключ графика */ /** Уникальный ключ графика */
key: string | number key: string | number
/** Параметры вертикальной оси */ /** Параметры вертикальной оси */
@ -101,7 +103,7 @@ export type NeedleChartDataset = {
type: 'needle' type: 'needle'
} }
export type ChartDataset<DataType> = BaseChartDataset<DataType> & ( export type ChartDataset<DataType extends BaseDataType> = BaseChartDataset<DataType> & (
AreaChartDataset | AreaChartDataset |
LineChartDataset | LineChartDataset |
NeedleChartDataset | NeedleChartDataset |
@ -154,7 +156,7 @@ export type ChartTicks<DataType> = {
y?: ChartTick<DataType> y?: ChartTick<DataType>
} }
export type ChartRegistry<DataType> = ChartDataset<DataType> & { export type ChartRegistry<DataType extends BaseDataType> = ChartDataset<DataType> & {
/** Получить D3 выборку, содержащую корневой G-элемент графика */ /** Получить D3 выборку, содержащую корневой G-элемент графика */
(): d3.Selection<SVGGElement, DataType, any, any> (): d3.Selection<SVGGElement, DataType, any, any>
/** Получить значение по вертикальной оси из предоставленой записи */ /** Получить значение по вертикальной оси из предоставленой записи */

View File

@ -1,9 +1,9 @@
import { BarChartOutlined, LineChartOutlined, DotChartOutlined, AreaChartOutlined, BorderOuterOutlined, } from '@ant-design/icons' import { BarChartOutlined, LineChartOutlined, DotChartOutlined, AreaChartOutlined, BorderOuterOutlined, } from '@ant-design/icons'
import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon' import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon'
import { ChartDataset } from '@components/d3' import { BaseDataType, ChartDataset } from '@components/d3'
export const makePointsOptimizator = <DataType extends Record<string, unknown>>(isEquals: (a: DataType, b: DataType) => boolean) => (points: DataType[]) => { export const makePointsOptimizator = <DataType extends BaseDataType>(isEquals: (a: DataType, b: DataType) => boolean) => (points: DataType[]) => {
if (!Array.isArray(points) || points.length < 3) return points if (!Array.isArray(points) || points.length < 3) return points
const out: DataType[] = [] const out: DataType[] = []
@ -23,7 +23,7 @@ export const getDistance = (x1: number, y1: number, x2: number, y2: number, type
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
} }
export const getChartIcon = <DataType,>(chart: ChartDataset<DataType>, options?: Omit<AntdIconProps, 'ref'>) => { export const getChartIcon = <DataType extends BaseDataType>(chart: ChartDataset<DataType>, options?: Omit<AntdIconProps, 'ref'>) => {
let Icon let Icon
switch (chart.type) { switch (chart.type) {
case 'needle': Icon = BarChartOutlined; break case 'needle': Icon = BarChartOutlined; break