/** * @upsetjs/react * https://github.com/upsetjs/upsetjs * * Copyright (c) 2021 Samuel Gratzl */ import React, { Ref, useMemo } from 'react'; import { fillKarnaughMapDefaults } from '../fillDefaults'; import useHandler from '../hooks/useHandler'; import type { KarnaughMapProps } from '../interfaces'; import { baseRules } from '../rules'; import { generateId, generateSelectionName, parseFontSize } from '../utils'; import SVGWrapper from '../venn/components/SVGWrapper'; import deriveVennSizeDependent from '../venn/derive/deriveVennSizeDependent'; import { useExportChart } from '../venn/hooks'; import KMapChart from './components/KMapChart'; import KMapQueries from './components/KMapQueries'; import KMapSelection from './components/KMapSelection'; import deriveKarnaughDataDependent from './derive/deriveDataDependent'; import deriveKarnaughStyleDependent from './derive/deriveStyleDependent'; import UpSetTitle from '../components/UpSetTitle'; export const KarnaughMap = /*!#__PURE__*/ React.forwardRef(function KarnaughMap( props: KarnaughMapProps, ref: Ref ) { const p = fillKarnaughMapDefaults(props); const { queries = [], fontSizes, selection = null } = p; // generate a "random" but attribute stable id to avoid styling conflicts const styleId = useMemo( () => p.id ? p.id : generateId([ p.fontFamily, fontSizes.axisTick, fontSizes.barLabel, fontSizes.legend, fontSizes.setLabel, fontSizes.title, fontSizes.exportLabel, fontSizes.description, p.textColor, p.color, p.hasSelectionColor, p.strokeColor, p.selectionColor, p.opacity, p.hasSelectionOpacity, ]), [ p.id, p.fontFamily, fontSizes.axisTick, fontSizes.barLabel, fontSizes.legend, fontSizes.setLabel, fontSizes.title, fontSizes.exportLabel, fontSizes.description, p.textColor, p.color, p.hasSelectionColor, p.strokeColor, p.selectionColor, p.opacity, p.hasSelectionOpacity, ] ); const style = useMemo( () => deriveKarnaughStyleDependent( p.theme, p.styles, p.classNames, p.combinationName, p.combinationNameAxisOffset, styleId, p.barLabelOffset, p.selectionColor, p.emptySelection, p.title, p.description, p.tooltips ), [ p.theme, p.styles, p.classNames, p.combinationName, p.combinationNameAxisOffset, styleId, p.barLabelOffset, p.selectionColor, p.emptySelection, p.title, p.description, p.tooltips, ] ); const size = useMemo( () => deriveVennSizeDependent(p.width, p.height, p.padding, p.id), [p.width, p.height, p.padding, p.id] ); const data = useMemo( () => deriveKarnaughDataDependent( p.sets, p.combinations, size, p.numericScale, p.barLabelOffset + parseFontSize(fontSizes.barLabel), p.barPadding, parseFontSize(fontSizes.setLabel), parseFontSize(fontSizes.axisTick), p.toKey, p.toElemKey, p.id, p.combinationMaxScale ), [ p.sets, p.combinations, size, p.numericScale, p.barLabelOffset, fontSizes.barLabel, p.barPadding, fontSizes.axisTick, fontSizes.setLabel, p.toKey, p.toElemKey, p.id, p.combinationMaxScale, ] ); const h = useHandler(p); const selectionName = generateSelectionName(selection); const rulesHelper = baseRules(styleId, p, p.fontFamily, fontSizes); const rules = ` ${rulesHelper.root} ${rulesHelper.text} .axisTextStyle-${styleId} { fill: ${p.textColor}; ${rulesHelper.p(fontSizes.axisTick)} text-anchor: end; } .barTextStyle-${styleId} { fill: ${p.textColor}; ${rulesHelper.p(fontSizes.barLabel)} text-anchor: middle; } .setTextStyle-${style.id} { fill: ${p.textColor}; ${rulesHelper.p(fontSizes.setLabel)} text-anchor: middle; dominant-baseline: central; } .cChartTextStyle-${styleId} { fill: ${p.textColor}; ${rulesHelper.p(fontSizes.chartLabel)} } .not-${style.id} { text-decoration: overline; } .axisLine-${styleId} { fill: none; stroke: ${p.textColor}; } .gridStyle-${style.id} { fill: none; stroke: ${p.strokeColor}; stroke-linecap: round; } .gridStyle-${style.id}-1 { stroke-width: 2; } .gridStyle-${style.id}-2 { stroke-width: 3; } ${rulesHelper.fill} ${rulesHelper.export} ${queries .map( (q, i) => `.fillQ${i}-${data.id} { fill: ${q.color}; }` ) .join('\n')} `; const exportChart = useExportChart(data, p, 'kmap'); const maxWidth = data.sets.l.reduce((acc, d) => Math.min(acc, d.text[0].x - data.sets.labelHeight), size.area.w); return ( ); }); /** * KarnaughMap main pure functional stateless React component, the generic argument T refers to the type of the elements * * with React.forwardRef support to specify a reference to the SVG element */ export default KarnaughMap as (p: KarnaughMapProps & React.RefAttributes) => React.ReactElement;