minesweeper = {
const { margin, cellSize, statusSize, buttonSize, displayWidth, gridWidth, gridHeight, bombs } = constants
const svg = d3
.create('svg')
.attr('width', gridWidth * cellSize + margin * 2)
.attr('height', gridHeight * cellSize + statusSize + margin * 2)
const scoreBoard = svg.append('g').attr('transform', `translate(${margin},${margin - 10})`)
const gameBoard = svg.append('g').attr('transform', `translate(${margin},${statusSize + margin})`)
const grid = gameBoard.append('g')
const buttons = gameBoard.append('g')
scoreBoard
.append('rect')
.attr('width', gridWidth * cellSize)
.attr('height', statusSize)
.attr('fill', '#d1d1d1')
scoreBoard
.append('rect')
.attr('x', gridWidth * cellSize - displayWidth - 5)
.attr('y', (statusSize - buttonSize) / 2)
.attr('width', displayWidth)
.attr('height', buttonSize)
.attr('fill', '#000')
scoreBoard
.append('text')
.attr('fill', 'red')
scoreBoard
.append('rect')
.attr('id', 'reset')
.attr('x', (gridWidth * cellSize) / 2 - buttonSize / 2)
.attr('y', (statusSize - buttonSize) / 2)
.attr('width', buttonSize)
.attr('height', buttonSize)
.attr('fill', 'darkgrey')
scoreBoard
.append('rect')
.attr('x', 5)
.attr('y', (statusSize - buttonSize) / 2)
.attr('width', displayWidth)
.attr('height', buttonSize)
.attr('fill', '#000')
scoreBoard
.append('text')
.attr('fill', 'red')
grid
.selectAll('rect')
.attr('width', gridWidth * cellSize)
.attr('height', cellSize)
.attr('fill', '#d1d1d1')
grid
.selectAll('text')
buttons
.selectAll('rect')
.join('rect')
.attr('x', d => d.x)
.attr('y', d => d.y)
.attr('width', cellSize)
.attr('height', cellSize)
.attr('fill', 'darkgrey')
const frame = createFrame()
return html`<div style="position: relative;">${frame}${svg.node()}</div>`
}