= ({
34 | x_min = 0,
35 | x_max = 1,
36 | y_min = 0,
37 | y_max = 1,
38 | width = 200,
39 | height = 150,
40 | max = 100,
41 | padding_inner = 0.4,
42 | data,
43 | caption = '',
44 | sortable = false,
45 | refresh = false,
46 | }) => {
47 | const [activeLabel, setActiveLabel] = useState('')
48 | const handleClick = (label: string) => {
49 | activeLabel === label ? setActiveLabel('') : setActiveLabel(label)
50 | }
51 |
52 | const [chart_data, setChartData] = useState(data)
53 | const [sort, setSort] = useState(0) // 0: default, 1: desc, 2: asc
54 | const handleSort = () => {
55 | setSort((sort + 1) % 3)
56 | }
57 |
58 | const sortStyle = {
59 | marginTop: '-0.2rem',
60 | marginLeft: '-0.2rem',
61 | transform: 'scaleX(0.8) scaleY(0.77)',
62 | }
63 |
64 | useMemo(() => {
65 | const org_data = [...data].sort((a, b) => {
66 | if (sort === 1) {
67 | return b.value - a.value
68 | }
69 | if (sort === 2) {
70 | return a.value - b.value
71 | }
72 | return 0
73 | })
74 | setChartData(org_data)
75 | }, [data, sort])
76 |
77 | useEffect(() => {
78 | if (refresh === true) {
79 | setActiveLabel('')
80 | }
81 | }, [refresh])
82 |
83 | const yScale = d3
84 | .scaleBand()
85 | .paddingInner(padding_inner)
86 | .domain(chart_data.map((d) => d.label))
87 | .range([y_min * height, y_max * height])
88 |
89 | const xScale = d3
90 | .scaleLinear()
91 | .domain([x_min * max, x_max * max])
92 | .range([x_min * width, x_max * width])
93 |
94 | return (
95 | <>
96 | {!!chart_data.length && (
97 | <>
98 |
99 |
173 |
174 |
175 | {x_min * max}
176 | {Math.round(((x_min + x_max) * max) / 2)}
177 | {x_max * max}
178 |
179 | {!!caption && (
180 |
181 | {caption}
182 | {!!sortable && (
183 |
187 | {sort === 0 ? (
188 |
189 | ) : sort === 1 ? (
190 |
191 | ) : (
192 |
193 | )}
194 |
195 | )}
196 |
197 | )}
198 | >
199 | )}
200 | >
201 | )
202 | }
203 |
--------------------------------------------------------------------------------
/src/components/d3/MultiLineChart.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react'
2 | import * as d3 from 'd3'
3 | import {
4 | TypeNews,
5 | TypeTopicData,
6 | TypeFormatedTopicData,
7 | } from '../../types/Type'
8 |
9 | interface props {
10 | data: TypeNews[] | any
11 | wrap_width: number
12 | }
13 |
14 | export const MultiLineChart: React.FC = ({ data, wrap_width }) => {
15 | useEffect(() => {
16 | data.length && renderChart()
17 | }, [data])
18 |
19 | const renderChart = () => {
20 | const width = wrap_width
21 | const height = 200
22 | const margin = 50
23 |
24 | const lineOpacity = '1'
25 | const lineOpacityHover = '0.85'
26 | const otherLinesOpacityHover = '0.1'
27 | const lineStroke = '0.2rem'
28 | const lineStrokeHover = '2.5px'
29 |
30 | /* Add SVG */
31 | d3.selectAll('.new-sentiment').remove()
32 | const svg = d3
33 | .select('#chart')
34 | .append('svg')
35 | .attr('class', 'new-sentiment')
36 | .attr('width', width + margin + 'px')
37 | .attr('height', height + margin + 'px')
38 | .append('g')
39 | .attr('transform', `translate(${margin}, 0)`)
40 |
41 | /* Format Data */
42 | const formatedData = data.map((d: any) => {
43 | return {
44 | ...d,
45 | topic_datas: d.topic_datas.map((topic: TypeTopicData) => {
46 | return { ...topic, day: new Date(topic.day) }
47 | }),
48 | }
49 | })
50 |
51 | //Accessors
52 | const x = (d: TypeFormatedTopicData): Date => d.day
53 | const y = (d: TypeFormatedTopicData): number => d.cumulative_score
54 |
55 | const x_min = d3.min([
56 | (formatedData[0]?.topic_datas
57 | ? d3.min(formatedData[0]?.topic_datas, x)
58 | : 0) as number,
59 | (formatedData[1]?.topic_datas
60 | ? d3.min(formatedData[1]?.topic_datas, x)
61 | : 0) as number,
62 | (formatedData[2]?.topic_datas
63 | ? d3.min(formatedData[2]?.topic_datas, x)
64 | : 0) as number,
65 | ])
66 |
67 | const x_max = d3.max([
68 | (formatedData[0]?.topic_datas
69 | ? d3.max(formatedData[0]?.topic_datas, x)
70 | : 0) as number,
71 | (formatedData[1]?.topic_datas
72 | ? d3.max(formatedData[1]?.topic_datas, x)
73 | : 0) as number,
74 | (formatedData[2]?.topic_datas
75 | ? d3.max(formatedData[2]?.topic_datas, x)
76 | : 0) as number,
77 | ])
78 | const y_min = d3.min([
79 | (formatedData[0]?.topic_datas
80 | ? d3.min(formatedData[0]?.topic_datas, y)
81 | : 0) as number,
82 | (formatedData[1]?.topic_datas
83 | ? d3.min(formatedData[1]?.topic_datas, y)
84 | : 0) as number,
85 | (formatedData[2]?.topic_datas
86 | ? d3.min(formatedData[2]?.topic_datas, y)
87 | : 0) as number,
88 | ])
89 |
90 | const y_max = d3.max([
91 | (formatedData[0]?.topic_datas
92 | ? d3.max(formatedData[0]?.topic_datas, y)
93 | : 0) as number,
94 | (formatedData[1]?.topic_datas
95 | ? d3.max(formatedData[1]?.topic_datas, y)
96 | : 0) as number,
97 | (formatedData[2]?.topic_datas
98 | ? d3.max(formatedData[2]?.topic_datas, y)
99 | : 0) as number,
100 | ])
101 | /* Scale */
102 | // const xScale = d3
103 | // .scaleLinear()
104 | // .domain(d3.extent(formatedData[0].topic_datas, x) as any)
105 | // .range([0, width - margin])
106 | const xScale = d3
107 | .scaleLinear()
108 | .domain([x_min, x_max] as any)
109 | .range([0, width - margin])
110 |
111 | const yScale = d3
112 | .scaleLinear()
113 | .domain([y_min, y_max] as any)
114 | .range([height, margin])
115 |
116 | const color = d3.scaleOrdinal(d3.schemeCategory10)
117 | /* Add Axis into SVG */
118 | const xAxis = d3
119 | .axisBottom(xScale)
120 | .ticks(3)
121 | .tickFormat((d: any) => `${d3.timeFormat('%B %d, %y')(d)}`)
122 |
123 | const yAxis = d3.axisLeft(yScale).ticks(3)
124 |
125 | svg
126 | .append('g')
127 | .attr('class', 'x axis dark:text-gray-300')
128 | .attr('transform', `translate(0, ${height + 10})`)
129 | .attr('stroke-width', 0)
130 | .style('font-size', '0.8rem')
131 | .call(xAxis)
132 |
133 | svg
134 | .append('g')
135 | .attr('class', 'y axis dark:text-gray-300')
136 | .attr('stroke-width', 0)
137 | .call(yAxis)
138 | .append('text')
139 | .attr('transform', 'rotate(-90)')
140 | .attr('class', 'dark:fill-gray-300')
141 | .attr('y', 0 - margin)
142 | .attr('x', 0 - height / 2)
143 | .attr('fill', '#000')
144 | .attr('dy', '1em')
145 | .style('text-anchor', 'middle')
146 | .text('New Sentiment')
147 | .style('font-size', '0.8rem')
148 |
149 | var div = d3
150 | .select('body')
151 | .append('div')
152 | .attr('class', 'tooltip')
153 | .style('opacity', 0)
154 | /* Add line into SVG */
155 | const line = d3
156 | .line()
157 | .x((d: any) => xScale(d.day))
158 | .y((d: any) => yScale(d.cumulative_score))
159 |
160 | let lines = svg.append('g').attr('class', 'lines')
161 |
162 | lines
163 | .selectAll('.line-group')
164 | .data(formatedData)
165 | .enter()
166 | .append('g')
167 | .attr('class', 'line-group')
168 | .on('mouseover', (event, d: any) => {
169 | svg
170 | .append('text')
171 | .attr('class', 'title-text dark:fill-gray-300')
172 | .text(d.topic)
173 | .attr('text-anchor', 'middle')
174 | .attr('x', (width - margin) / 2)
175 | .attr('y', 30)
176 | })
177 | .on('mouseout', function (d) {
178 | svg.select('.title-text').remove()
179 | })
180 | .append('path')
181 | .attr('class', 'line')
182 | .attr('d', (d: any) => line(d.topic_datas))
183 | .style('stroke', (d: any, i) => {
184 | switch (d.topic) {
185 | case 'environmental':
186 | return 'rgb(89, 161, 79)'
187 | case 'governance':
188 | return 'rgb(176, 122, 161)'
189 | case 'social':
190 | return 'rgb(78, 121, 167)'
191 | }
192 | return 'rgb(89, 161, 79)'
193 | })
194 | .style('stroke-width', '0.2rem')
195 | .style('opacity', lineOpacity)
196 | .on('mouseover', function (d: any) {
197 | d3.selectAll('.line').style('opacity', otherLinesOpacityHover)
198 | d3.select(this)
199 | .style('opacity', lineOpacityHover)
200 | .style('stroke-width', lineStrokeHover)
201 | .style('cursor', 'pointer')
202 | })
203 | .on('mouseout', function (d) {
204 | d3.selectAll('.line').style('opacity', lineOpacity)
205 | d3.select(this)
206 | .style('stroke-width', lineStroke)
207 | .style('cursor', 'none')
208 | })
209 | }
210 | return
211 | }
212 |
--------------------------------------------------------------------------------
/src/pages/Reports/components/TopicScores.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState, useContext, useRef } from 'react'
2 | import { getCompanyScores } from '../../../api/getCompanyScores'
3 | import { getCompanySubTopics } from '../../../api/getCompanySubTopics'
4 | import { getCompanyTopics } from '../../../api/getCompanyTopics'
5 | import { Column } from 'react-table'
6 | import { TypeTopicScores } from '../../../types/Type'
7 | import { ReportTable } from '../../../components/ReportTable'
8 | import { calcScore, getScoreColor } from '../../../utils/Report'
9 | import { TopicContext } from '../../../context/TopicContext'
10 | import { PageLoading } from '../../../components/PageLoading'
11 |
12 | type responseType = {
13 | topic: string
14 | subtopic: string
15 | company_sentiment: number
16 | }
17 |
18 | interface Props {
19 | company_id: string
20 | company_name: string
21 | }
22 |
23 | export const TopicScores: React.FC = ({ company_id, company_name }) => {
24 | const [loading, setLoading] = useState(true)
25 | const [data, setData] = useState([])
26 | const [topics, setTopics] = useState([])
27 | const [sub_topics, setSubTopics] = useState([[]])
28 | const [scores, setScores] = useState([[]])
29 | const [cells, setCells] = useState([])
30 | const { report_topic, setReportTopic } = useContext(TopicContext)
31 | const ref = useRef(null)
32 |
33 | useEffect(() => {
34 | setLoading(true)
35 | getCompanySubTopics(company_id)
36 | .then((response) => {
37 | const res: responseType[] = response.data.data
38 | res.sort((prev, next) => (prev.topic < next.topic ? -1 : 1))
39 |
40 | setData(
41 | res.map((item) => ({
42 | ...item,
43 | company_sentiment: Math.round(
44 | calcScore(item.company_sentiment),
45 | ).toString(),
46 | })),
47 | )
48 | })
49 | .finally(() => {
50 | setLoading(false)
51 | })
52 | }, [company_id])
53 |
54 | const selectTopic = (e: React.MouseEvent) => {
55 | let topic = e.currentTarget.innerText.toLowerCase()
56 | typeof setReportTopic === 'function' &&
57 | setReportTopic(report_topic === topic ? '' : topic)
58 | }
59 |
60 | const columns: Array = React.useMemo(
61 | () => [
62 | {
63 | Header: 'Topic',
64 | accessor: 'topic',
65 | enableRowSpan: true,
66 | Cell: ({ cell: { value } }) => {
67 | return (
68 |
76 | {value}
77 |
78 | )
79 | },
80 | },
81 | {
82 | Header: 'Subtopic',
83 | accessor: 'subtopic',
84 | Cell: ({ cell: { value } }) => (
85 |
97 | {value.replace(/%S%(.*?)(%E%|$)/g, '')}
98 |
99 | ),
100 | },
101 | {
102 | Header: '',
103 | accessor: 'company_sentiment',
104 | Cell: ({ cell: { value } }) => (
105 |
127 | ),
128 | },
129 | ],
130 | [report_topic],
131 | )
132 |
133 | const handleClickOutside = (e: MouseEvent) => {
134 | ref &&
135 | ref.current &&
136 | !ref.current.contains(e.target as Node) &&
137 | typeof setReportTopic === 'function' &&
138 | setReportTopic('')
139 | }
140 |
141 | useEffect(() => {
142 | document.addEventListener('mousedown', handleClickOutside)
143 | return () => {
144 | document.removeEventListener('mousedown', handleClickOutside)
145 | }
146 | }, [])
147 |
148 | return loading ? (
149 |
150 | ) : (
151 | // loading...
152 |
153 |
{company_name}
154 |
155 | {data.length ?
: ''}
156 |
157 |
Score Colors
158 |
159 |
0.0
160 |
165 |
100.0
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | )
193 | }
194 |
--------------------------------------------------------------------------------
/src/components/d3/ScatterPlot.tsx:
--------------------------------------------------------------------------------
1 | import { wbData } from "./data";
2 | import { scaleLinear, scaleLog, scaleSqrt, scaleOrdinal } from "@visx/scale";
3 | import { extent, format, max, min } from "d3";
4 | import * as d3 from "d3";
5 | import { Circle } from "@visx/shape";
6 | import { Text } from "@visx/text";
7 | import { Group } from "@visx/group";
8 | import { Axis, AxisLeft } from "@visx/axis";
9 | import { GridColumns } from "@visx/grid";
10 | import { useTooltip, TooltipWithBounds, defaultStyles } from "@visx/tooltip";
11 | import { useEffect, useContext, useRef, useMemo, useCallback } from "react";
12 | import { localPoint } from "@visx/event";
13 | import { voronoi } from "@visx/voronoi";
14 | import { CompanyContext } from "../../context/CompanyContext";
15 | import { getCompanyName } from "../../utils/getCompanyName";
16 | import { TypeCompany, TypePeerMap } from "../../types/Type";
17 |
18 | interface Props {
19 | wrap_width: number;
20 | data: TypePeerMap[];
21 | companies: TypeCompany[] | [];
22 | }
23 |
24 | export const ScatterPlot: React.FC = ({
25 | wrap_width,
26 | data,
27 | companies,
28 | }) => {
29 | // let data = wbData.data
30 | const { company_id, company_name } = useContext(CompanyContext);
31 |
32 | const width = wrap_width * 0.95;
33 | const height = 360;
34 | const margin = { top: 30, left: 60, right: 40, bottom: 50 };
35 | const innerWidth =
36 | width - margin.left - margin.right > 0
37 | ? width - margin.left - margin.right
38 | : 0;
39 | const innerHeight = height - margin.top - margin.bottom;
40 |
41 | const x = (d: any) => d.signals_count;
42 | const y = (d: any) => d.signals_average;
43 | const radius = (d: any) => d.ticker_market_cap;
44 | const color = (d: any) => d.ticker_name;
45 |
46 | const xScale = scaleLinear({
47 | range: [margin.left, innerWidth + margin.left],
48 | domain: extent(data, x) as any,
49 | });
50 |
51 | const yScale = scaleLinear({
52 | range: [innerHeight + margin.top, margin.top],
53 | domain: [min(data, y), max(data, y)] as any,
54 | nice: true,
55 | });
56 |
57 | const rScale = scaleSqrt({
58 | range: [3, 30],
59 | domain: extent(data, radius) as any,
60 | });
61 |
62 | const {
63 | showTooltip,
64 | hideTooltip,
65 | tooltipData,
66 | tooltipOpen,
67 | tooltipTop = 0,
68 | tooltipLeft = 0,
69 | } = useTooltip();
70 |
71 | const voronoiLayout = useMemo(
72 | () =>
73 | voronoi({
74 | x: (d) => xScale(x(d)) ?? 0,
75 | y: (d) => yScale(y(d)) ?? 0,
76 | width,
77 | height,
78 | })(data),
79 | [data, width, height, xScale, yScale]
80 | );
81 |
82 | let tooltipTimeout: number;
83 | const svgRef = useRef(null);
84 |
85 | const handleMouseMove = useCallback(
86 | (event) => {
87 | if (tooltipTimeout) clearTimeout(tooltipTimeout);
88 | if (!svgRef.current) return;
89 |
90 | // find the nearest polygon to the current mouse position
91 | const point = localPoint(svgRef.current, event);
92 | if (!point) return;
93 | const neighborRadius = 100;
94 | const closest = voronoiLayout.find(point.x, point.y, neighborRadius);
95 | if (closest) {
96 | showTooltip({
97 | tooltipLeft: xScale(x(closest.data)),
98 | tooltipTop: yScale(y(closest.data)),
99 | tooltipData: closest.data as TypePeerMap,
100 | });
101 | }
102 | },
103 | [xScale, yScale, showTooltip, voronoiLayout]
104 | );
105 |
106 | const handleMouseLeave = useCallback(() => {
107 | tooltipTimeout = window.setTimeout(() => {
108 | hideTooltip();
109 | }, 500);
110 | }, [hideTooltip]);
111 |
112 | // Sort the data
113 | const sortedData = useMemo(
114 | () => data.sort((a, b) => b.ticker_market_cap - a.ticker_market_cap),
115 | [data]
116 | );
117 |
118 | const ticker_name = getCompanyName(company_id, companies);
119 |
120 | return (
121 | <>
122 |
228 | {tooltipOpen && tooltipData && tooltipLeft != null && tooltipTop != null && (
229 |
234 |
241 | {color(tooltipData)}
242 |
243 |
250 |
Signals Count
251 |
{`${format("2~s")(
252 | x(tooltipData)
253 | )}`}
254 |
Signals Average
255 |
256 | {/* {Math.round(y(tooltipData))} */}
257 | {y(tooltipData)}
258 |
259 |
Ticker Market Cap
260 |
{`${Math.round(
261 | radius(tooltipData)
262 | )}`}
263 |
264 |
265 | )}
266 | >
267 | );
268 | };
269 |
--------------------------------------------------------------------------------
/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module "react-table" {
2 | // Type definitions for react-table 7.7
3 | // Project: https://github.com/tannerlinsley/react-table
4 | // Definitions by: Guy Gascoigne-Piggford ,
5 | // Michael Stramel
6 | // Rohit Garg
7 | // Jason Clark
8 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
9 | // TypeScript Version: 3.5
10 | // reflects react-table@7.7.0
11 |
12 | // tslint:disable:no-empty-interface
13 | // no-empty-interface is disabled to allow easy extension with declaration merging
14 |
15 | // tslint:disable:no-unnecessary-generics
16 | // no-unnecessary-generics is disabled because many of these definitions are either used in a generic
17 | // context or the signatures are required to match for declaration merging
18 |
19 | // The changelog for the important changes is located in the Readme.md
20 |
21 | import {
22 | ChangeEvent,
23 | ComponentType,
24 | CSSProperties,
25 | DependencyList,
26 | EffectCallback,
27 | MouseEvent,
28 | ReactElement,
29 | ReactFragment,
30 | ReactNode,
31 | ReactText,
32 | } from "react";
33 |
34 | export {};
35 |
36 | /**
37 | * The empty definitions of below provides a base definition for the parts used by useTable, that can then be extended in the users code.
38 | *
39 | * @example
40 | * export interface TableOptions
41 | * extends
42 | * UseExpandedOptions,
43 | * UseFiltersOptions {}
44 | * see https://gist.github.com/ggascoigne/646e14c9d54258e40588a13aabf0102d for more details
45 | */
46 | export interface TableOptions extends UseTableOptions {}
47 |
48 | export interface TableInstance
49 | extends Omit, "columns" | "pageCount">,
50 | UseTableInstanceProps {}
51 |
52 | export interface TableState {
53 | hiddenColumns?: Array> | undefined;
54 | }
55 |
56 | export interface Hooks extends UseTableHooks {}
57 |
58 | export interface Cell
59 | extends UseTableCellProps {}
60 |
61 | export interface ColumnInterface
62 | extends UseTableColumnOptions {}
63 |
64 | export interface ColumnInterfaceBasedOnValue {
65 | Cell?: Renderer> | undefined;
66 | }
67 |
68 | export interface ColumnGroupInterface {
69 | columns: Array>;
70 | }
71 |
72 | export type ColumnGroup = ColumnInterface &
73 | ColumnGroupInterface &
74 | (
75 | | { Header: string }
76 | | ({ id: IdType } & {
77 | Header: Renderer>;
78 | })
79 | ) & { accessor?: Accessor | undefined }; // Not used, but needed for backwards compatibility
80 |
81 | type ValueOf = T[keyof T];
82 |
83 | // The accessors like `foo.bar` are not supported, use functions instead
84 | export type ColumnWithStrictAccessor =
85 | ColumnInterface &
86 | ValueOf<{
87 | [K in keyof D]: {
88 | accessor: K;
89 | } & ColumnInterfaceBasedOnValue;
90 | }>;
91 |
92 | export type ColumnWithLooseAccessor =
93 | ColumnInterface &
94 | ColumnInterfaceBasedOnValue &
95 | (
96 | | { Header: string }
97 | | { id: IdType }
98 | | { accessor: keyof D extends never ? IdType : never }
99 | ) & {
100 | accessor?:
101 | | (keyof D extends never ? IdType | Accessor : Accessor)
102 | | undefined;
103 | };
104 |
105 | export type Column =
106 | | ColumnGroup
107 | | ColumnWithLooseAccessor
108 | | ColumnWithStrictAccessor;
109 |
110 | export interface ColumnInstance
111 | extends Omit, "id">,
112 | ColumnInterfaceBasedOnValue,
113 | UseTableColumnProps {}
114 |
115 | export interface HeaderGroup
116 | extends ColumnInstance,
117 | UseTableHeaderGroupProps {
118 | [x: string]: any;
119 | }
120 |
121 | export interface Row extends UseTableRowProps {}
122 |
123 | export interface TableCommonProps {
124 | style?: CSSProperties | undefined;
125 | className?: string | undefined;
126 | role?: string | undefined;
127 | }
128 |
129 | export interface TableProps extends TableCommonProps {}
130 |
131 | export interface TableBodyProps extends TableCommonProps {}
132 |
133 | export interface TableKeyedProps extends TableCommonProps {
134 | key: React.Key;
135 | }
136 |
137 | export interface TableHeaderGroupProps extends TableKeyedProps {}
138 |
139 | export interface TableFooterGroupProps extends TableKeyedProps {}
140 |
141 | export interface TableHeaderProps extends TableKeyedProps {}
142 |
143 | export interface TableFooterProps extends TableKeyedProps {}
144 |
145 | export interface TableRowProps extends TableKeyedProps {}
146 |
147 | export interface TableCellProps extends TableKeyedProps {}
148 |
149 | export interface TableToggleCommonProps extends TableCommonProps {
150 | onChange?: ((e: ChangeEvent) => void) | undefined;
151 | checked?: boolean | undefined;
152 | title?: string | undefined;
153 | indeterminate?: boolean | undefined;
154 | }
155 |
156 | export interface MetaBase {
157 | instance: TableInstance;
158 | userProps: any;
159 | }
160 |
161 | // inspired by ExtendState in https://github.com/reduxjs/redux/blob/master/src/types/store.ts
162 | export type Meta> = [
163 | Extension
164 | ] extends [never]
165 | ? M
166 | : M & Extension;
167 |
168 | //#region useTable
169 | export function useTable(
170 | options: TableOptions,
171 | ...plugins: Array>
172 | ): TableInstance;
173 |
174 | /**
175 | * NOTE: To use custom options, use "Interface Merging" to add the custom options
176 | */
177 | export type UseTableOptions = {
178 | columns: ReadonlyArray>;
179 | data: readonly D[];
180 | } & Partial<{
181 | initialState: Partial>;
182 | stateReducer: (
183 | newState: TableState,
184 | action: ActionType,
185 | previousState: TableState,
186 | instance?: TableInstance
187 | ) => TableState;
188 | useControlledState: (state: TableState, meta: Meta) => TableState;
189 | defaultColumn: Partial>;
190 | getSubRows: (originalRow: D, relativeIndex: number) => D[];
191 | getRowId: (
192 | originalRow: D,
193 | relativeIndex: number,
194 | parent?: Row
195 | ) => string;
196 | autoResetHiddenColumns: boolean;
197 | }>;
198 |
199 | export type PropGetter<
200 | D extends object,
201 | Props,
202 | T extends object = never,
203 | P = Partial
204 | > = ((props: P, meta: Meta) => P | P[]) | P | P[];
205 |
206 | export type TablePropGetter = PropGetter;
207 |
208 | export type TableBodyPropGetter = PropGetter<
209 | D,
210 | TableBodyProps
211 | >;
212 |
213 | export type HeaderPropGetter = PropGetter<
214 | D,
215 | TableHeaderProps,
216 | { column: HeaderGroup }
217 | >;
218 |
219 | export type FooterGroupPropGetter = PropGetter<
220 | D,
221 | TableFooterGroupProps,
222 | { column: HeaderGroup }
223 | >;
224 |
225 | export type HeaderGroupPropGetter = PropGetter<
226 | D,
227 | TableHeaderGroupProps,
228 | { column: HeaderGroup }
229 | >;
230 |
231 | export type FooterPropGetter = PropGetter<
232 | D,
233 | TableFooterProps,
234 | { column: HeaderGroup }
235 | >;
236 |
237 | export type RowPropGetter = PropGetter<
238 | D,
239 | TableRowProps,
240 | { row: Row }
241 | >;
242 |
243 | export type CellPropGetter = PropGetter<
244 | D,
245 | TableCellProps,
246 | { cell: Cell }
247 | >;
248 |
249 | export interface ReducerTableState
250 | extends TableState,
251 | Record {}
252 |
253 | export interface UseTableHooks extends Record {
254 | useOptions: Array<
255 | (options: TableOptions, args: TableOptions) => TableOptions
256 | >;
257 | stateReducers: Array<
258 | (
259 | newState: TableState,
260 | action: ActionType,
261 | previousState?: TableState,
262 | instance?: TableInstance
263 | ) => ReducerTableState | undefined
264 | >;
265 | columns: Array<
266 | (columns: Array>, meta: Meta) => Array>
267 | >;
268 | columnsDeps: Array<(deps: any[], meta: Meta) => any[]>;
269 | allColumns: Array<
270 | (allColumns: Array>, meta: Meta) => Array>
271 | >;
272 | allColumnsDeps: Array<(deps: any[], meta: Meta) => any[]>;
273 | visibleColumns: Array<
274 | (allColumns: Array>, meta: Meta) => Array>
275 | >;
276 | visibleColumnsDeps: Array<(deps: any[], meta: Meta) => any[]>;
277 | headerGroups: Array<
278 | (
279 | allColumns: Array>,
280 | meta: Meta
281 | ) => Array>
282 | >;
283 | headerGroupsDeps: Array<(deps: any[], meta: Meta) => any[]>;
284 | useInstanceBeforeDimensions: Array<(instance: TableInstance) => void>;
285 | useInstance: Array<(instance: TableInstance) => void>;
286 | prepareRow: Array<(row: Row, meta: Meta) => void>;
287 | useControlledState: Array<
288 | (state: TableState, meta: Meta) => TableState
289 | >;
290 |
291 | getTableProps: Array>;
292 | getTableBodyProps: Array>;
293 | getHeaderGroupProps: Array>;
294 | getFooterGroupProps: Array>;
295 | getHeaderProps: Array>;
296 | getFooterProps: Array>;
297 | getRowProps: Array>;
298 | getCellProps: Array>;
299 | useFinalInstance: Array<(instance: TableInstance) => void>;
300 | }
301 |
302 | export interface UseTableColumnOptions {
303 | id?: IdType | undefined;
304 | Header?: Renderer> | undefined;
305 | Footer?: Renderer> | undefined;
306 | width?: number | string | undefined;
307 | minWidth?: number | undefined;
308 | maxWidth?: number | undefined;
309 | }
310 |
311 | type UpdateHiddenColumns = (
312 | oldHidden: Array>
313 | ) => Array>;
314 |
315 | export interface TableToggleHideAllColumnProps
316 | extends TableToggleCommonProps {}
317 |
318 | export interface UseTableInstanceProps {
319 | state: TableState;
320 | plugins: Array>;
321 | dispatch: TableDispatch;
322 | columns: Array>;
323 | allColumns: Array>;
324 | visibleColumns: Array>;
325 | headerGroups: Array>;
326 | footerGroups: Array>;
327 | headers: Array>;
328 | flatHeaders: Array>;
329 | rows: Array>;
330 | rowsById: Record>;
331 | getTableProps: (propGetter?: TablePropGetter) => TableProps;
332 | getTableBodyProps: (propGetter?: TableBodyPropGetter) => TableBodyProps;
333 | prepareRow: (row: Row) => void;
334 | flatRows: Array>;
335 | totalColumnsWidth: number;
336 | allColumnsHidden: boolean;
337 | toggleHideColumn: (columnId: IdType, value?: boolean) => void;
338 | setHiddenColumns: (
339 | param: Array> | UpdateHiddenColumns
340 | ) => void;
341 | toggleHideAllColumns: (value?: boolean) => void;
342 | getToggleHideAllColumnsProps: (
343 | props?: Partial
344 | ) => TableToggleHideAllColumnProps;
345 | getHooks: () => Hooks;
346 | rowSpanHeaders: any;
347 | }
348 |
349 | export interface UseTableHeaderGroupProps {
350 | headers: Array>;
351 | getHeaderGroupProps: (
352 | propGetter?: HeaderGroupPropGetter
353 | ) => TableHeaderProps;
354 | getFooterGroupProps: (
355 | propGetter?: FooterGroupPropGetter
356 | ) => TableFooterProps;
357 | totalHeaderCount: number; // not documented
358 | }
359 |
360 | export interface UseTableColumnProps {
361 | id: IdType;
362 | columns?: Array> | undefined;
363 | isVisible: boolean;
364 | render: (type: "Header" | "Footer" | string, props?: object) => ReactNode;
365 | totalLeft: number;
366 | totalWidth: number;
367 | getHeaderProps: (propGetter?: HeaderPropGetter) => TableHeaderProps;
368 | getFooterProps: (propGetter?: FooterPropGetter) => TableFooterProps;
369 | toggleHidden: (value?: boolean) => void;
370 | parent?: ColumnInstance | undefined; // not documented
371 | getToggleHiddenProps: (userProps?: any) => any;
372 | depth: number; // not documented
373 | placeholderOf?: ColumnInstance | undefined;
374 | }
375 |
376 | export interface UseTableRowProps {
377 | cells: Array>;
378 | allCells: Array>;
379 | values: Record, CellValue>;
380 | getRowProps: (propGetter?: RowPropGetter) => TableRowProps;
381 | index: number;
382 | original: D;
383 | id: string;
384 | subRows: Array>;
385 | }
386 |
387 | export interface UseTableCellProps {
388 | column: ColumnInstance;
389 | row: Row;
390 | value: CellValue;
391 | isRowSpanned?: boolean;
392 | rowSpan: number;
393 | getCellProps: (propGetter?: CellPropGetter) => TableCellProps;
394 | render: (type: "Cell" | string, userProps?: object) => ReactNode;
395 | }
396 |
397 | export type HeaderProps = TableInstance & {
398 | column: ColumnInstance;
399 | };
400 |
401 | export type FooterProps = TableInstance & {};
402 |
403 | export type CellProps = TableInstance & {
404 | column: ColumnInstance;
405 | row: Row;
406 | cell: Cell;
407 | value: CellValue;
408 | };
409 |
410 | export type Accessor = (
411 | originalRow: D,
412 | index: number,
413 | sub: {
414 | subRows: D[];
415 | depth: number;
416 | data: D[];
417 | }
418 | ) => CellValue;
419 |
420 | //#endregion
421 |
422 | // Plugins
423 |
424 | //#region useAbsoluteLayout
425 | export function useAbsoluteLayout(
426 | hooks: Hooks
427 | ): void;
428 |
429 | export namespace useAbsoluteLayout {
430 | const pluginName = "useAbsoluteLayout";
431 | }
432 | //#endregion
433 |
434 | //#region useBlockLayout
435 | export function useBlockLayout(hooks: Hooks | |