Newer
Older
CrypticOreWallet / src / shared-components / list-view / ListTableSkeletonRows.tsx
@Drew Lemmy Drew Lemmy on 23 Sep 2020 1 KB feat: table data providers
import React, { Component, ReactNode } from "react";

import { Columns } from "./DataProvider";
import { SkeletonText } from "@components/skeleton/SkeletonText";

// Default widths for the skeleton elements that look good enough
const SKELETON_EM_WIDTHS = [10, 7, 5, 4, 8, 10];
const SKELETON_ROWS = 5;

interface Props<T> {  
  columns?: Columns<T>;
}

export class ListTableSkeletonRows<T> extends Component<Props<T>> {
  generateSkeletonSizes(): Array<number | undefined> | undefined {
    const { columns } = this.props;

    // Generate the sizes of skeleton text
    const skeletonSizes = columns
      ? Array.from(columns, ([, columnSpec]) => 
        columnSpec.skeletonEmWidth || undefined) // If no width was defined, use undefined
      : undefined;

    // Fill any missing sizes with defaults
    if (skeletonSizes !== undefined) {
      for (let i = 0; i < Math.min(skeletonSizes.length, SKELETON_EM_WIDTHS.length); i++) {
        if (skeletonSizes[i] !== undefined) continue;
        skeletonSizes[i] = SKELETON_EM_WIDTHS[i];
      }
    }

    return skeletonSizes;
  }

  generateSkeletonRow(skeletonSizes: Array<number | undefined>): Array<ReactNode> {
    return skeletonSizes.map((width, i) =>
      <td key={i}><SkeletonText emWidth={width} /></td>);
  }

  generateSkeletonRows(skeletonSizes: Array<number | undefined>): Array<ReactNode> {
    return new Array(SKELETON_ROWS).fill(null).map((_, i) => 
      <tr key={i}>{this.generateSkeletonRow(skeletonSizes)}</tr>);
  }

  render(): ReactNode {
    const skeletonSizes = this.generateSkeletonSizes();
    return skeletonSizes ? this.generateSkeletonRows(skeletonSizes) : null;
  }
}