UNPKG

@aptpod/data-viz-create-visual-parts-react

Version:

template of npm project with typescript

147 lines (128 loc) 4.59 kB
import { FontFamilies, ViewGrid, DataSpecification, Value, } from '@aptpod/data-viz-visual-parts-sdk' import { ComponentProps, useMemo } from 'react' import { BIND_DATA_COUNT_MAX } from './constant' import { HorizontalBars } from './component' import { shouldDisplayedSmall, calcRatio } from './utils' import { canDisplayNumber } from 'src/utils/validator' import { memoize } from 'src/utils/memoize' import { buildEmptyArray, selectNonNullables } from 'src/utils/array' /** * HorizontalBars Componentの Props型 */ type HorizontalBarsProps = ComponentProps<typeof HorizontalBars> type HorizontalBarsPropsValue = HorizontalBarsProps['values'][0] /** * DataSpecificationで使用するフィールドの型のみで再定義 */ type UsedDataSpecification = Pick< DataSpecification, 'rangeMin' | 'rangeMax' | 'dataName' | 'decimalDigits' > /** * Valueで使用するフィールドの型のみで再定義 */ type UsedValue = Pick<Value, 'baseIdx' | 'data'> /** * HorizontalBars ComponentのPropsに変換します。 * メモ化のため、useMemo、memoize を使用しています。 * memoizeは、可変引数、loop内で使用するfunctionのメモ化で使用しています。 */ export const useSelectProps = (params: { fontFamilies: FontFamilies viewGrid: ViewGrid dataSpecifications: UsedDataSpecification[] values: UsedValue[] }): HorizontalBarsProps => { const { fontFamilies, viewGrid, dataSpecifications, values } = params // 小さい表示にするかViewGridを使用して判定します。 // メモ化のため、useMemoを使用します。 const showSmall = useMemo(() => { return shouldDisplayedSmall(viewGrid.colSpan, viewGrid.rowSpan) }, [viewGrid.colSpan, viewGrid.rowSpan]) // 使用するFontFamilyを取得します。 // メモ化のため、useMemoを使用します。 const propsFontFamilies = useMemo(() => { return { name: fontFamilies.yotsuyaSansJPRegular, value: fontFamilies.apt7seg, } }, [fontFamilies.yotsuyaSansJPRegular, fontFamilies.apt7seg]) // selectNonNullablesのメモ化 const memoizedSelectNonNullables = useMemo( () => memoize(selectNonNullables), [], ) // PropsValueを生成するためのメモ化済みfunctionの初期化 const memoizedPropsValues = useMemo(() => { return buildEmptyArray(BIND_DATA_COUNT_MAX).map(() => ({ buildPropsValue: memoize(buildPropsValue), })) }, []) // Props Values を取得します。 // メモ化したfunctionを使用します。 const propsValues = memoizedSelectNonNullables( ...buildEmptyArray(BIND_DATA_COUNT_MAX).map((_, i) => selectPropsValue( dataSpecifications[i], values[i], memoizedPropsValues[i].buildPropsValue, ), ), ) return { showSmall, fontFamilies: propsFontFamilies, values: propsValues, } } /** * HorizontalBarsのValueに変換します。 * dataSpecification, value が未定義の場合はnullを返します。 */ const selectPropsValue = ( dataSpecification: UsedDataSpecification | undefined, value: UsedValue | undefined, funcBuildPropsValue: typeof buildPropsValue, ): HorizontalBarsPropsValue | null => { // dataSpecification, value のいずれかが無効の場合はnullを返します。 if (!dataSpecification || !value) { return null } // baseIdx に該当するデータポイントの値を取得します。 // 取得できない場合は空文字列とみなします。 const v = value.data[value.baseIdx]?.v ?? '' // dataSpecification から変換に必要な項目を取得します。 const { dataName, rangeMin, rangeMax, decimalDigits } = dataSpecification // HorizontalBarsのバー表示するためのratioを計算します。 // データポイントの値が数値として判定できない場合は0とします。 const ratio = canDisplayNumber(v) ? calcRatio({ min: rangeMin, max: rangeMax, value: Number(v), }) : 0 // HorizontalBarsに表示するテキストに変換します。 // データポイントの値が数値として判定できない場合は、小数点の有効桁数を使用せずに文字列に変換します。 const text = canDisplayNumber(v) ? Number(v).toFixed(decimalDigits) : String(v) return funcBuildPropsValue(dataName, ratio, text) } /** * HorizontalBarsPropsValueのObjectを作成します。 */ const buildPropsValue = ( name: string, ratio: number, text: string, ): HorizontalBarsPropsValue => ({ name, ratio, text, })