Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ceb687c
Initial plan
Copilot May 21, 2026
63a4780
feat: add configurable weighted path finder
Copilot May 21, 2026
fda58e7
perf: optimize path queue and polish step summary formatting
Copilot May 21, 2026
810d076
feat: address pathfinder review feedback
Copilot May 21, 2026
9adf69a
chore: polish path summary tempo label casing
Copilot May 21, 2026
9899f9f
feat: improve scope diagnostics and pathfinder UX polish
Copilot May 21, 2026
3eea3eb
feat: add scope diagnostics and improve pathfinder labels
Copilot May 21, 2026
c3c000c
fix: prefer analyzed BPM with robust Engine DJ column matching
Copilot May 21, 2026
8f16b4c
chore: polish engine parser naming
Copilot May 21, 2026
0ec52e3
feat: add path cost metrics sorting and per-step limits
Copilot May 21, 2026
3647c2e
chore: clarify path metric abbreviations
Copilot May 21, 2026
0ec8742
fix: enforce average cost on completed paths only
Copilot May 21, 2026
752060c
Fine tune path graph cost
samsta May 21, 2026
4a30abe
feat: increase path finder results cap to 10
Copilot May 21, 2026
13378ae
test: make path finder fixtures independent of app defaults
Copilot May 21, 2026
a6f2fc7
Potential fix for pull request finding
samsta May 21, 2026
ec2bfe3
Potential fix for pull request finding
samsta May 21, 2026
f169efd
fix: make navigation path ids unique per step details
Copilot May 21, 2026
2ce146d
fix: align path weight labels and inputs consistently
Copilot May 21, 2026
8649956
refactor: switch path weight help text to compact tooltips
Copilot May 21, 2026
57272a8
Fix TypeScript error: replace invalid textAnchor value "beginning" wi…
Copilot May 21, 2026
0627e26
Sync package-lock.json version to 0.7.0
Copilot May 21, 2026
51ae953
fix: revert version to 0.5.0 per PR convention (one bump per PR)
Copilot May 21, 2026
7f650de
feat: add Transition costs heading above weight inputs
Copilot May 21, 2026
cef98d9
chore: replace 'cost'→'weight' and 'step'→'transition' in UI text
Copilot May 21, 2026
2a890bd
docs: add build workflow badge to README.md
Copilot May 21, 2026
0c61856
ui: use 'cost' instead of 'weight' throughout Path Finder UI
Copilot May 21, 2026
bd653dc
Update track table headers and button labels
samsta May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# KeyBpmMap

![Tests](https://github.com/samsta/KeyBpmMap/actions/workflows/test.yml/badge.svg)
![Build](https://github.com/samsta/KeyBpmMap/actions/workflows/deploy.yml/badge.svg)

KeyBpmMap is a client-only React application for exploring the harmonic and tempo shape of a DJ music library.
It reads local Engine DJ SQLite databases and Traktor `collection.nml` files directly in the browser, normalizes supported key formats into Camelot notation, and renders both a polar density map and a BPM-vs-key heatmap for fast library analysis.
Expand All @@ -11,6 +12,7 @@ It reads local Engine DJ SQLite databases and Traktor `collection.nml` files dir
- Browser-only Traktor `collection.nml` loading, including playlist metadata
- Engine numeric, Open Key, and standard musical key → Camelot conversion
- Polar harmonic density map and rectangular BPM heatmap
- Weighted path finder between start/end tracks with configurable key/tempo costs
- Playlist, rating, BPM, and text filters
- Region inspection for exact track lists inside a selected cell
- Playlist transition summaries derived from playlist ordering
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "keybpmmap",
"private": true,
"version": "0.4.0",
"version": "0.5.0",
"type": "module",
Comment thread
samsta marked this conversation as resolved.
"scripts": {
"dev": "vite",
Expand Down
201 changes: 200 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@
}

.source-panel,
.filters-panel {
.filters-panel,
.pathfinder-panel {
padding: 24px 28px;
}

Expand Down Expand Up @@ -144,6 +145,10 @@ select {
box-sizing: border-box;
}

input[type='checkbox'] {
width: auto;
}

.stats-grid,
.visual-grid,
.insights-grid {
Expand Down Expand Up @@ -253,6 +258,156 @@ select {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.pathfinder-panel {
display: grid;
gap: 16px;
order: 999;
}

.path-weight-grid {
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}

.path-section-heading {
margin: 0 0 8px 0;
font-size: 0.85rem;
font-weight: 600;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.05em;
}

.path-weight-grid label {
grid-template-rows: minmax(2.5em, auto) min-content;
}

.path-weight-label-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 8px;
}

.path-weight-label-text {
display: block;
line-height: 1.25;
}

.path-weight-tooltip {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1rem;
min-width: 1rem;
color: #94a3b8;
font-size: 0.85rem;
line-height: 1;
cursor: help;
}

.path-weight-tooltip:focus-visible {
outline: 1px solid rgba(34, 211, 238, 0.7);
outline-offset: 2px;
border-radius: 50%;
}

.pathfinder-panel input[type='number'],
.pathfinder-panel input[type='search'],
.pathfinder-panel select {
min-height: 44px;
}

.path-checkbox {
align-self: end;
display: flex;
align-items: center;
gap: 10px;
}

.path-helper-copy,
.path-status {
color: #94a3b8;
}

.path-actions {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}

.path-results-grid {
display: grid;
gap: 16px;
}

.path-graph-wrapper {
overflow-x: auto;
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 18px;
padding: 10px;
background: rgba(15, 23, 42, 0.4);
}

.path-graph {
width: 100%;
min-width: 460px;
height: auto;
}

.path-graph-row {
cursor: pointer;
}

.path-graph-row polyline {
fill: none;
stroke: rgba(148, 163, 184, 0.55);
stroke-width: 2;
}

.path-graph-row circle {
fill: rgba(30, 41, 59, 1);
stroke: rgba(148, 163, 184, 0.55);
stroke-width: 2;
}

.path-graph-row.is-selected polyline,
.path-graph-row.is-selected circle {
stroke: rgba(34, 211, 238, 0.9);
}

.path-graph-label,
.path-graph-node-label {
fill: #cbd5e1;
font-size: 0.78rem;
}

.path-graph-cost {
fill: #38bdf8;
font-size: 0.6rem;
}

.path-graph-track-label {
fill: #94a3b8;
font-size: 0.63rem;
}

.path-graph-track-artist {
font-weight: 700;
fill: #cbd5e1;
}

.path-summary-list {
max-height: 220px;
overflow: auto;
padding-right: 6px;
}

.path-details {
display: grid;
gap: 10px;
}

.insight-subtitle,
.placeholder-text,
.error-banner {
Expand Down Expand Up @@ -323,6 +478,49 @@ select {
font-style: normal;
}

.track-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
}

.track-action-button {
padding: 0.45rem 0.8rem;
font-size: 0.82rem;
}

.scope-track-table-wrapper {
overflow: auto;
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 14px;
}

.scope-track-table {
width: 100%;
min-width: 680px;
border-collapse: collapse;
font-size: 0.86rem;
}

.scope-track-table th,
.scope-track-table td {
padding: 10px 12px;
border-bottom: 1px solid rgba(148, 163, 184, 0.16);
text-align: left;
vertical-align: middle;
}

.scope-track-table thead th {
font-size: 0.78rem;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.04em;
}

.scope-track-table tbody td {
color: #cbd5e1;
}

.simple-list button {
width: 100%;
padding: 0;
Expand Down Expand Up @@ -390,6 +588,7 @@ select {
.hero-panel,
.source-panel,
.filters-panel,
.pathfinder-panel,
.chart-panel,
.insight-panel {
padding: 20px;
Expand Down
Loading
Loading