seveibar/keyboard-utils

Based on the code provided, here's a concise summary of the electronic component: A keyboard utility library for parsing and generating keyboard layouts using the Keyboard Layout Editor (KLE) JSON format, with support for generating key matrices, reference designators, and diode routing for keyboard PCBs. Key features: - Parses KLE JSON layouts into key coordinate and metadata objects - Supports various keyboard layouts (60%, ANSI, ISO, Ergodox, etc.) - Generates unique reference designators for keys - Provides utility for adding diode routing in key matrices - TypeScript-based with React and tscircuit integration The library allows keyboard designers to easily convert layout designs into structured, machine-readable keyboard specifications.

Version
0.0.19
License
unset
Stars
3

lib/KeyMatrix.tsx

import React from 'react';
import { parseKLELayout } from "./KLELayout";
import type { KLELayout } from "./KLELayout";
import { A_1N4148WS } from "imports/A1N4148WS";
import { Key } from "../components/Key";

interface KeyMatrixProps {
  layout: KLELayout
  rowToMicroPin?: string[]
  colToMicroPin?: string[]
  name?: string
  pcbX?: number
  pcbY?: number
  schX?: number
  schY?: number
}

export const KeyMatrix = ({
  layout,
  rowToMicroPin,
  colToMicroPin,
  name = "KB",
  pcbX = 0,
  pcbY = 0,
  schX = 0,
  schY = 0,
}: KeyMatrixProps) => {
  const keys = parseKLELayout(layout)

  const minX = Math.min(...keys.map((k) => k.x))
  const maxX = Math.max(...keys.map((k) => k.x + k.width))
  const minY = Math.min(...keys.map((k) => k.y))
  const maxY = Math.max(...keys.map((k) => k.y + k.height))

  // Group keys by rotation and rotation center
  const keyGroups = new Map<string, typeof keys>()

  keys.forEach(key => {
    const groupKey = `${key.rotation}_${key.rotationX}_${key.rotationY}`
    if (!keyGroups.has(groupKey)) {
      keyGroups.set(groupKey, [])
    }
    keyGroups.get(groupKey)!.push(key)
  })

  return (
    <group pcbX={pcbX} pcbY={pcbY} schX={schX} schY={schY}>
      {Array.from(keyGroups.entries()).map(([groupKey, groupKeys]) => {
        const firstKey = groupKeys[0]
        const hasRotation = firstKey.rotation !== 0

        if (hasRotation) {
          // For rotated key groups (thumb clusters), position at absolute rotation center
          const keyboardCenterX = (minX + maxX) / 2
          const keyboardCenterY = (minY + maxY) / 2
          const rotationCenterX = firstKey.rotationX - keyboardCenterX
          const rotationCenterY = firstKey.rotationY - keyboardCenterY

          return (
            <group
              key={groupKey}
              pcbX={rotationCenterX}
              pcbY={rotationCenterY}
              pcbRotation={firstKey.rotation}
            >
              {groupKeys.map((key) => {
                // Position keys relative to their rotation center
                const relX = key.x - key.rotationX
                const relY = key.y - key.rotationY

                return (
                  <group
                    key={key.name}
                    pcbX={relX}
                    pcbY={relY}
                    schX={relX / 5}
                    schY={relY / 7}
                  >
                    <Key name={key.name} />
                    {rowToMicroPin?.[key.row] !== undefined && (
                      <A_1N4148WS
                        name={`${key.name}_DIO`}
                        connections={{
                          A: `.${key.name} .pin1`,
                          C: rowToMicroPin[key.row],
                        }}
                        pcbX={0.5}
                        pcbY={-13.5}
                        schY={-1}
                        layer="bottom"
                      />
                    )}
                    {colToMicroPin?.[key.col] !== undefined && (
                      <trace from={`.${key.name} .pin2`} to={colToMicroPin[key.col]} />
                    )}
                  </group>
                )
              })}
            </group>
          )
        } else {
          // For non-rotated key groups, position relative to keyboard center
          return (
            <group key={groupKey}>
              {groupKeys.map((key) => {
                const relX = key.x - (minX + maxX) / 2
                const relY = key.y - (minY + maxY) / 2

                return (
                  <group
                    key={key.name}
                    pcbX={relX}
                    pcbY={relY}
                    schX={relX / 5}
                    schY={relY / 7}
                  >
                    <Key name={key.name} />
                    {rowToMicroPin?.[key.row] !== undefined && (
                      <A_1N4148WS
                        name={`${key.name}_DIO`}
                        connections={{
                          A: `.${key.name} .pin1`,
                          C: rowToMicroPin[key.row],
                        }}
                        pcbX={0.5}
                        pcbY={-13.5}
                        schY={-1}
                        layer="bottom"
                      />
                    )}
                    {colToMicroPin?.[key.col] !== undefined && (
                      <trace from={`.${key.name} .pin2`} to={colToMicroPin[key.col]} />
                    )}
                  </group>
                )
              })}
            </group>
          )
        }
      })}
    </group>
  )
}