@beastmode-develeap/beastmode 0.1.121 → 0.1.122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@
15
15
  }
16
16
  </script>
17
17
  <!--BOARD_DATA-->
18
- <script>window.__BUILD_STAMP__ = "20260418-190841-6b44897";</script>
18
+ <script>window.__BUILD_STAMP__ = "20260418-202811-98d25b2";</script>
19
19
  <link rel="preconnect" href="https://fonts.googleapis.com">
20
20
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
21
21
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
@@ -1027,6 +1027,13 @@ input[type="range"]::-webkit-slider-thumb {
1027
1027
  box-shadow: var(--shadow-glow);
1028
1028
  }
1029
1029
 
1030
+ .kanban-column.drag-over-invalid {
1031
+ border: 2px dashed var(--danger);
1032
+ background: rgba(248, 113, 113, 0.05);
1033
+ opacity: 0.5;
1034
+ cursor: not-allowed;
1035
+ }
1036
+
1030
1037
  .kanban-column-header {
1031
1038
  padding: 14px 16px;
1032
1039
  border-bottom: 1px solid var(--border);
@@ -1407,6 +1414,13 @@ input[type="range"]::-webkit-slider-thumb {
1407
1414
  box-shadow: var(--shadow-glow);
1408
1415
  }
1409
1416
 
1417
+ .pipeline-column.drag-over-invalid {
1418
+ border: 2px dashed var(--danger);
1419
+ background: rgba(248, 113, 113, 0.05);
1420
+ opacity: 0.5;
1421
+ cursor: not-allowed;
1422
+ }
1423
+
1410
1424
  .pipeline-column-header {
1411
1425
  padding: 10px 12px;
1412
1426
  border-top: 3px solid var(--col-color, var(--text-muted));
@@ -2620,6 +2634,140 @@ input[type="range"]::-webkit-slider-thumb {
2620
2634
  transition: all 0.15s ease;
2621
2635
  }
2622
2636
  .btn-secondary:hover { background: var(--surface-elevated); border-color: var(--text-muted); }
2637
+
2638
+ /* ================================================================
2639
+ COSTS PAGE
2640
+ ================================================================ */
2641
+
2642
+ .costs-table-wrapper {
2643
+ overflow-x: auto;
2644
+ overflow-y: visible;
2645
+ -webkit-overflow-scrolling: touch;
2646
+ max-width: 100%;
2647
+ }
2648
+
2649
+ .costs-table {
2650
+ width: 100%;
2651
+ border-collapse: collapse;
2652
+ table-layout: fixed;
2653
+ font-family: var(--font-sans);
2654
+ font-size: 13px;
2655
+ }
2656
+
2657
+ .costs-th-id { width: 60px; }
2658
+ .costs-th-name { width: auto; }
2659
+ .costs-th-status { width: 120px; }
2660
+ .costs-th-tokens { width: 100px; }
2661
+ .costs-th-cost { width: 110px; }
2662
+ .costs-th-records { width: 80px; }
2663
+
2664
+ .costs-th {
2665
+ text-align: left;
2666
+ padding: 10px 12px;
2667
+ font-size: 11px;
2668
+ font-weight: 600;
2669
+ text-transform: uppercase;
2670
+ letter-spacing: 0.5px;
2671
+ color: var(--text-muted);
2672
+ border-bottom: 1px solid var(--border);
2673
+ cursor: pointer;
2674
+ user-select: none;
2675
+ white-space: nowrap;
2676
+ }
2677
+
2678
+ .costs-th:hover {
2679
+ color: var(--accent);
2680
+ }
2681
+
2682
+ .costs-tr {
2683
+ cursor: pointer;
2684
+ transition: background 0.15s ease;
2685
+ }
2686
+
2687
+ .costs-tr:hover {
2688
+ background: var(--bg-card-hover);
2689
+ }
2690
+
2691
+ .costs-td {
2692
+ padding: 10px 12px;
2693
+ border-bottom: 1px solid var(--border-subtle);
2694
+ color: var(--text);
2695
+ vertical-align: middle;
2696
+ overflow: hidden;
2697
+ text-overflow: ellipsis;
2698
+ white-space: nowrap;
2699
+ }
2700
+
2701
+ .costs-td-mono {
2702
+ font-family: var(--font-mono);
2703
+ font-size: 13px;
2704
+ }
2705
+
2706
+ .costs-td-name {
2707
+ font-weight: 500;
2708
+ max-width: 300px;
2709
+ overflow: hidden;
2710
+ text-overflow: ellipsis;
2711
+ white-space: nowrap;
2712
+ }
2713
+
2714
+ .costs-phase-chart {
2715
+ padding: 16px 0;
2716
+ }
2717
+
2718
+ .costs-phase-row {
2719
+ display: flex;
2720
+ align-items: center;
2721
+ gap: 12px;
2722
+ padding: 6px 16px;
2723
+ }
2724
+
2725
+ .costs-phase-label {
2726
+ width: 100px;
2727
+ font-size: 13px;
2728
+ font-weight: 500;
2729
+ color: var(--text-secondary);
2730
+ text-transform: capitalize;
2731
+ flex-shrink: 0;
2732
+ }
2733
+
2734
+ .costs-phase-bar-bg {
2735
+ flex: 1;
2736
+ height: 24px;
2737
+ background: var(--accent-subtle);
2738
+ border-radius: var(--radius-xs);
2739
+ overflow: hidden;
2740
+ position: relative;
2741
+ }
2742
+
2743
+ .costs-phase-bar-fill {
2744
+ height: 100%;
2745
+ background: var(--accent);
2746
+ border-radius: 0;
2747
+ transition: width 0.4s ease;
2748
+ min-width: 2px;
2749
+ }
2750
+
2751
+ .costs-phase-amount {
2752
+ width: 80px;
2753
+ text-align: right;
2754
+ font-family: var(--font-mono);
2755
+ font-size: 13px;
2756
+ font-weight: 500;
2757
+ color: var(--text);
2758
+ flex-shrink: 0;
2759
+ }
2760
+
2761
+ @media (max-width: 900px) {
2762
+ .costs-phase-label { width: 70px; font-size: 12px; }
2763
+ .costs-phase-amount { width: 60px; font-size: 12px; }
2764
+ .costs-td-name { max-width: 150px; }
2765
+ }
2766
+
2767
+ @media (max-width: 600px) {
2768
+ .costs-table { font-size: 12px; }
2769
+ .costs-th, .costs-td { padding: 8px 6px; }
2770
+ }
2623
2771
  </style>
2624
2772
  </head>
2625
2773
  <body>
@@ -4381,7 +4529,7 @@ function PipelineView({
4381
4529
  data-testid=${'pipeline-col-' + colId}
4382
4530
  data-column=${colId}
4383
4531
  key=${'pc-' + lane.key + '-' + colId}
4384
- onDragOver=${onDragOver}
4532
+ onDragOver=${e => onDragOver(e, colId)}
4385
4533
  onDragLeave=${onDragLeave}
4386
4534
  onDrop=${e => onDrop(e, colId)}>
4387
4535
  <div class="pipeline-column-header"
@@ -4534,7 +4682,7 @@ function BoardPage({ selectedProject }) {
4534
4682
  const [items, setItems] = useState([]);
4535
4683
  const [loading, setLoading] = useState(true);
4536
4684
  const [error, setError] = useState(null);
4537
- const [dragId, setDragId] = useState(null);
4685
+ const [dragInfo, setDragInfo] = useState(null);
4538
4686
  const [selectedItem, setSelectedItem] = useState(null);
4539
4687
  const [showCreateDialog, setShowCreateDialog] = useState(false);
4540
4688
  const [searchTerm, setSearchTerm] = useState('');
@@ -4723,32 +4871,56 @@ function BoardPage({ selectedProject }) {
4723
4871
  };
4724
4872
 
4725
4873
  const onDragStart = (e, id) => {
4726
- setDragId(id);
4874
+ const item = items.find(i => String(i.id) === String(id));
4875
+ const taskType = (item && item.task_type) ? item.task_type : 'code';
4876
+ setDragInfo({ id, taskType });
4727
4877
  e.dataTransfer.effectAllowed = 'move';
4878
+ try { e.dataTransfer.setData('text/plain', String(id)); } catch {}
4728
4879
  e.target.classList.add('dragging');
4729
4880
  };
4730
4881
 
4731
4882
  const onDragEnd = (e) => {
4732
4883
  e.target.classList.remove('dragging');
4733
- setDragId(null);
4884
+ setDragInfo(null);
4885
+ document.querySelectorAll('.drag-over, .drag-over-invalid').forEach(el => {
4886
+ el.classList.remove('drag-over', 'drag-over-invalid');
4887
+ });
4734
4888
  };
4735
4889
 
4736
- const onDragOver = (e) => {
4890
+ const onDragOver = (e, targetColumnId) => {
4737
4891
  e.preventDefault();
4738
- e.dataTransfer.dropEffect = 'move';
4739
- e.currentTarget.classList.add('drag-over');
4892
+ if (!dragInfo) return;
4893
+ const validStages = (typeof getStagesForType === 'function')
4894
+ ? getStagesForType(dragInfo.taskType)
4895
+ : [];
4896
+ const isValid = validStages.indexOf(targetColumnId) !== -1;
4897
+ if (isValid) {
4898
+ e.dataTransfer.dropEffect = 'move';
4899
+ e.currentTarget.classList.remove('drag-over-invalid');
4900
+ e.currentTarget.classList.add('drag-over');
4901
+ } else {
4902
+ e.dataTransfer.dropEffect = 'none';
4903
+ e.currentTarget.classList.remove('drag-over');
4904
+ e.currentTarget.classList.add('drag-over-invalid');
4905
+ }
4740
4906
  };
4741
4907
 
4742
4908
  const onDragLeave = (e) => {
4743
- e.currentTarget.classList.remove('drag-over');
4909
+ e.currentTarget.classList.remove('drag-over', 'drag-over-invalid');
4744
4910
  };
4745
4911
 
4746
4912
  const onDrop = async (e, status) => {
4747
4913
  e.preventDefault();
4748
- e.currentTarget.classList.remove('drag-over');
4749
- if (!dragId) return;
4914
+ e.currentTarget.classList.remove('drag-over', 'drag-over-invalid');
4915
+ if (!dragInfo) return;
4916
+ const validStages = (typeof getStagesForType === 'function')
4917
+ ? getStagesForType(dragInfo.taskType)
4918
+ : [];
4919
+ if (validStages.indexOf(status) === -1) return;
4920
+ const current = items.find(i => String(i.id) === String(dragInfo.id));
4921
+ if (current && current.status === status) return;
4750
4922
  try {
4751
- await api('PATCH', '/api/board/items/' + dragId, { status });
4923
+ await api('PATCH', '/api/board/items/' + dragInfo.id, { status });
4752
4924
  fetchItems();
4753
4925
  } catch (err) { setError(err.message); }
4754
4926
  };
@@ -5000,7 +5172,7 @@ function BoardPage({ selectedProject }) {
5000
5172
  const sortMode = columnSorts[col.id] || '';
5001
5173
  return html`
5002
5174
  <div class="kanban-column" key=${col.id}
5003
- onDragOver=${onDragOver}
5175
+ onDragOver=${e => onDragOver(e, col.id)}
5004
5176
  onDragLeave=${onDragLeave}
5005
5177
  onDrop=${e => onDrop(e, col.id)}>
5006
5178
  <div class="kanban-column-header" style=${'--col-color: ' + col.color} title=${col.tooltip} onClick=${() => cycleSort(col.id)}>
@@ -7727,19 +7899,19 @@ function CostsPage({ selectedProject }) {
7727
7899
  <table class="costs-table">
7728
7900
  <thead>
7729
7901
  <tr>
7730
- <th class="costs-th" onClick=${() => handleSort('id')}>ID${sortIndicator('id')}</th>
7731
- <th class="costs-th" onClick=${() => handleSort('name')}>Task${sortIndicator('name')}</th>
7732
- <th class="costs-th" onClick=${() => handleSort('status')}>Status${sortIndicator('status')}</th>
7733
- <th class="costs-th" onClick=${() => handleSort('tokens')}>Tokens${sortIndicator('tokens')}</th>
7734
- <th class="costs-th" onClick=${() => handleSort('cost')}>Cost (USD)${sortIndicator('cost')}</th>
7735
- <th class="costs-th" onClick=${() => handleSort('records')}>Records${sortIndicator('records')}</th>
7902
+ <th class="costs-th costs-th-id" onClick=${() => handleSort('id')}>ID${sortIndicator('id')}</th>
7903
+ <th class="costs-th costs-th-name" onClick=${() => handleSort('name')}>Task${sortIndicator('name')}</th>
7904
+ <th class="costs-th costs-th-status" onClick=${() => handleSort('status')}>Status${sortIndicator('status')}</th>
7905
+ <th class="costs-th costs-th-tokens" onClick=${() => handleSort('tokens')}>Tokens${sortIndicator('tokens')}</th>
7906
+ <th class="costs-th costs-th-cost" onClick=${() => handleSort('cost')}>Cost (USD)${sortIndicator('cost')}</th>
7907
+ <th class="costs-th costs-th-records" onClick=${() => handleSort('records')}>Records${sortIndicator('records')}</th>
7736
7908
  </tr>
7737
7909
  </thead>
7738
7910
  <tbody>
7739
7911
  ${sortedRows.map(row => html`
7740
7912
  <tr key=${row.id} class="costs-tr" onClick=${() => navigate('#/board?item=' + row.id)}>
7741
7913
  <td class="costs-td costs-td-mono">#${row.id}</td>
7742
- <td class="costs-td costs-td-name">${row.name}</td>
7914
+ <td class="costs-td costs-td-name" title=${row.name}>${row.name}</td>
7743
7915
  <td class="costs-td"><span class=${'badge ' + statusBadgeClass(row.status)}>${row.status}</span></td>
7744
7916
  <td class="costs-td costs-td-mono">${formatTokens(row.totalTokens)}</td>
7745
7917
  <td class="costs-td costs-td-mono">$${row.costUsd.toFixed(2)}</td>
@@ -1 +1 @@
1
- 20260418-190841-6b44897
1
+ 20260418-202811-98d25b2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.121",
3
+ "version": "0.1.122",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {