{"version":3,"file":"VizRepeater.mjs","sources":["../../../../src/components/VizRepeater/VizRepeater.tsx"],"sourcesContent":["import { clamp } from 'lodash';\nimport { PureComponent, CSSProperties } from 'react';\nimport * as React from 'react';\n\nimport { VizOrientation } from '@grafana/data';\n\nimport { calculateGridDimensions } from '../../utils/squares';\n\ninterface Props<V, D> {\n  /**\n   * Optionally precalculate dimensions to support consistent behavior between repeated\n   * values.  Two typical patterns are:\n   * 1) Calculate raw values like font size etc and pass them to each vis\n   * 2) find the maximum input values and pass that to the vis\n   */\n  getAlignmentFactors?: (values: V[], width: number, height: number) => D;\n\n  /**\n   * Render a single value\n   */\n  renderValue: (props: VizRepeaterRenderValueProps<V, D>) => JSX.Element;\n  height: number;\n  width: number;\n  source: unknown; // If this changes, new values will be requested\n  getValues: () => V[];\n  renderCounter: number; // force update of values & render\n  orientation: VizOrientation;\n  itemSpacing?: number;\n  /** When orientation is set to auto layout items in a grid */\n  autoGrid?: boolean;\n  minVizWidth?: number;\n  minVizHeight?: number;\n  maxVizHeight?: number;\n}\n\nexport interface VizRepeaterRenderValueProps<V, D = {}> {\n  value: V;\n  width: number;\n  height: number;\n  orientation: VizOrientation;\n  alignmentFactors: D;\n  /**\n   * Total number of values being shown in repeater\n   */\n  count: number;\n}\n\ninterface DefaultProps {\n  itemSpacing: number;\n}\n\ntype PropsWithDefaults<V, D> = Props<V, D> & DefaultProps;\n\ninterface State<V> {\n  values: V[];\n}\n\nexport class VizRepeater<V, D = {}> extends PureComponent<PropsWithDefaults<V, D>, State<V>> {\n  static defaultProps: DefaultProps = {\n    itemSpacing: 8,\n  };\n\n  constructor(props: PropsWithDefaults<V, D>) {\n    super(props);\n\n    this.state = {\n      values: props.getValues(),\n    };\n  }\n\n  componentDidUpdate(prevProps: Props<V, D>) {\n    const { renderCounter, source } = this.props;\n    if (renderCounter !== prevProps.renderCounter || source !== prevProps.source) {\n      this.setState({ values: this.props.getValues() });\n    }\n  }\n\n  getOrientation(): VizOrientation {\n    const { orientation, width, height } = this.props;\n\n    if (orientation === VizOrientation.Auto) {\n      if (width > height) {\n        return VizOrientation.Vertical;\n      } else {\n        return VizOrientation.Horizontal;\n      }\n    }\n\n    return orientation;\n  }\n\n  renderGrid() {\n    const { renderValue, height, width, itemSpacing, getAlignmentFactors, orientation } = this.props;\n\n    const { values } = this.state;\n    const grid = calculateGridDimensions(width, height, itemSpacing, values.length);\n    const alignmentFactors = getAlignmentFactors ? getAlignmentFactors(values, grid.width, grid.height) : ({} as D);\n\n    let xGrid = 0;\n    let yGrid = 0;\n    let items: JSX.Element[] = [];\n\n    for (let i = 0; i < values.length; i++) {\n      const value = values[i];\n      const isLastRow = yGrid === grid.yCount - 1;\n\n      const itemWidth = isLastRow ? grid.widthOnLastRow : grid.width;\n      const itemHeight = grid.height;\n\n      const xPos = xGrid * itemWidth + itemSpacing * xGrid;\n      const yPos = yGrid * itemHeight + itemSpacing * yGrid;\n\n      const itemStyles: CSSProperties = {\n        position: 'absolute',\n        left: xPos,\n        top: yPos,\n        width: `${itemWidth}px`,\n        height: `${itemHeight}px`,\n      };\n\n      items.push(\n        <div key={i} style={itemStyles}>\n          {renderValue({\n            value,\n            width: itemWidth,\n            height: itemHeight,\n            alignmentFactors,\n            orientation,\n            count: values.length,\n          })}\n        </div>\n      );\n\n      xGrid++;\n\n      if (xGrid === grid.xCount) {\n        xGrid = 0;\n        yGrid++;\n      }\n    }\n\n    return <div style={{ position: 'relative' }}>{items}</div>;\n  }\n\n  render() {\n    const {\n      renderValue,\n      height,\n      width,\n      itemSpacing,\n      getAlignmentFactors,\n      autoGrid,\n      orientation,\n      maxVizHeight,\n      minVizWidth,\n      minVizHeight,\n    } = this.props;\n    const { values } = this.state;\n\n    if (autoGrid && orientation === VizOrientation.Auto) {\n      return this.renderGrid();\n    }\n\n    const itemStyles: React.CSSProperties = {\n      display: 'flex',\n    };\n\n    const repeaterStyle: React.CSSProperties = {\n      display: 'flex',\n      overflow: `${minVizWidth ? 'auto' : 'hidden'} ${minVizHeight ? 'auto' : 'hidden'}`,\n    };\n\n    let vizHeight = height;\n    let vizWidth = width;\n\n    const resolvedOrientation = this.getOrientation();\n\n    switch (resolvedOrientation) {\n      case VizOrientation.Horizontal:\n        const defaultVizHeight = (height + itemSpacing) / values.length - itemSpacing;\n        repeaterStyle.flexDirection = 'column';\n        repeaterStyle.height = `${height}px`;\n        repeaterStyle.overflowX = 'hidden';\n        repeaterStyle.scrollbarWidth = 'thin';\n        itemStyles.marginBottom = `${itemSpacing}px`;\n        vizWidth = width;\n        vizHeight = clamp(defaultVizHeight, minVizHeight ?? 0, maxVizHeight ?? defaultVizHeight);\n        break;\n      case VizOrientation.Vertical:\n        repeaterStyle.flexDirection = 'row';\n        repeaterStyle.justifyContent = 'space-between';\n        repeaterStyle.overflowY = 'hidden';\n        itemStyles.marginRight = `${itemSpacing}px`;\n        vizHeight = height;\n        vizWidth = Math.max(width / values.length - itemSpacing + itemSpacing / values.length, minVizWidth ?? 0);\n    }\n\n    itemStyles.width = `${vizWidth}px`;\n    itemStyles.height = `${vizHeight}px`;\n\n    const alignmentFactors = getAlignmentFactors ? getAlignmentFactors(values, vizWidth, vizHeight) : ({} as D);\n\n    return (\n      <div style={repeaterStyle}>\n        {values.map((value, index) => {\n          return (\n            <div key={index} style={getItemStylesForIndex(itemStyles, index, values.length)}>\n              {renderValue({\n                value,\n                width: vizWidth,\n                height: vizHeight,\n                alignmentFactors,\n                orientation: resolvedOrientation,\n                count: values.length,\n              })}\n            </div>\n          );\n        })}\n      </div>\n    );\n  }\n}\n\n/*\n * Removes any padding on the last item\n */\nfunction getItemStylesForIndex(itemStyles: CSSProperties, index: number, length: number): CSSProperties {\n  if (index === length - 1) {\n    return {\n      ...itemStyles,\n      marginRight: 0,\n      marginBottom: 0,\n    };\n  }\n  return itemStyles;\n}\n"],"names":[],"mappings":"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"}