JSFiddle - React, Tailwind, and code Playground

by Chris Maloney

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.2/tinycolor.min.js"></script>
<div id='svg'></div>

JavaScript

const range = n => [...Array(n)].map((_, i) => i);

const svg = d3.select('#svg').append('svg').attrs({
  width: 600,
  height: 600,
});
svg.append('rect').attrs({
  width: 600,
  height: 600,
  x: 0,
  y: 0,
  fill: 'gray',
});

const allCards = [];
for (const number of [1, 2, 3]) {
  for (const symbol of ['circle', 'diamond', 'rect']) {
    for (const color of ['red', 'green', 'purple']) {
      for (const line of ['solid', 'dashed', 'dot-dash']) {
				allCards.push({number, symbol, color, line});
      }
    }
  }
}

const deck = new Set(allCards);
console.log(deck.size);
const dealOne = () => {
  const num = Math.floor(deck.size * Math.random());
  const card = [...deck.values()][num];
  deck.delete(card);
  return card;
};
const dealN = n => range(n).map(dealOne);
//const c1 = dealOne();
//console.log('c1: ', c1);
//console.log('cards left: ', cards.size);

const cardWidth = 90;
const cardHeight = 60;
const cardSpacing = 10;
const rows = 3;
const cols = 4;
const board = range(rows).map(row =>
  range(cols).map(dealOne)
);

const drawCard = (row, col, card) => {
  const x = col * cardWidth + (col + 1) * cardSpacing;
  const y = row * cardHeight + (row + 1) * cardSpacing;
  const cardG = svg.append('g').attrs({
    transform: `translate(${x} ${y})`,
  });
  cardG.append('rect').attrs({fill: 'white', 
    x: 0, y: 0,
    width: cardWidth, height: cardHeight,
    rx: 5, ry: 5,
  });
  const {number, symbol, color, line} = card;
  for (let i = 0; i < number; ++i) {
    const x = cardWidth * (1/2 + (1 - number + 2*i)/7);
    const symG = cardG.append('g').attrs({
      transform: `translate(${x} ${cardHeight / 2})`,
    });
    const fillColor = tinycolor(color).toHsl();
    fillColor.l = 1 - (1 - fillColor.l) / 8;
    const attrs = {
      fill: tinycolor(fillColor),
      stroke: color,
      'stroke-width': 2,
    };
    if (line === 'dashed') {
      attrs['stroke-dasharray'] = '6 6';
    }
    else if (line === 'dot-dash') {
      attrs['stroke-dasharray'] =...