projax 1.3.11 → 1.3.12

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.
Files changed (40) hide show
  1. package/dist/api/package.json +10 -7
  2. package/dist/index.js +100 -1
  3. package/package.json +1 -1
  4. package/dist/core.d.ts +0 -2
  5. package/dist/core.js +0 -76
  6. package/dist/electron/renderer/assets/index-7KIJIiIM.js +0 -42
  7. package/dist/electron/renderer/assets/index-BGV4pGGx.js +0 -46
  8. package/dist/electron/renderer/assets/index-BTFVUZ9M.js +0 -46
  9. package/dist/electron/renderer/assets/index-BT_e6Msc.js +0 -46
  10. package/dist/electron/renderer/assets/index-Bu1Gyxs5.js +0 -46
  11. package/dist/electron/renderer/assets/index-BwyNdCvJ.js +0 -46
  12. package/dist/electron/renderer/assets/index-C9bA-P-3.css +0 -1
  13. package/dist/electron/renderer/assets/index-CJlaCHj5.css +0 -1
  14. package/dist/electron/renderer/assets/index-CTxba8Fs.js +0 -61
  15. package/dist/electron/renderer/assets/index-C_6HLZ3g.js +0 -46
  16. package/dist/electron/renderer/assets/index-Cejn7BcN.js +0 -46
  17. package/dist/electron/renderer/assets/index-CfEtNYYJ.js +0 -46
  18. package/dist/electron/renderer/assets/index-CgMqjX1w.css +0 -1
  19. package/dist/electron/renderer/assets/index-CknIIag9.js +0 -61
  20. package/dist/electron/renderer/assets/index-Cs0biDoD.css +0 -1
  21. package/dist/electron/renderer/assets/index-Csg1hzAW.js +0 -61
  22. package/dist/electron/renderer/assets/index-CtD66H57.js +0 -46
  23. package/dist/electron/renderer/assets/index-Cz5tpCH_.css +0 -1
  24. package/dist/electron/renderer/assets/index-CzSAm4rV.js +0 -46
  25. package/dist/electron/renderer/assets/index-D5r8Ki4V.js +0 -46
  26. package/dist/electron/renderer/assets/index-D7t8lZFK.js +0 -46
  27. package/dist/electron/renderer/assets/index-D8AivBJO.js +0 -42
  28. package/dist/electron/renderer/assets/index-DPZN2_De.css +0 -1
  29. package/dist/electron/renderer/assets/index-DZfKv3qb.js +0 -61
  30. package/dist/electron/renderer/assets/index-DmLmfvuw.css +0 -1
  31. package/dist/electron/renderer/assets/index-DtjxFwRT.css +0 -1
  32. package/dist/electron/renderer/assets/index-DyhB_yB5.js +0 -61
  33. package/dist/electron/renderer/assets/index-FdqNz85q.css +0 -1
  34. package/dist/electron/renderer/assets/index-IV4RpG6x.css +0 -1
  35. package/dist/electron/renderer/assets/index-O6z5EG_7.js +0 -46
  36. package/dist/electron/renderer/assets/index-_QUmEi7R.css +0 -1
  37. package/dist/electron/renderer/assets/index-ezVMxZrM.css +0 -1
  38. package/dist/prxi.d.ts +0 -2
  39. package/dist/prxi.js +0 -297
  40. package/dist/prxi.mjs +0 -34059
@@ -1 +0,0 @@
1
- .project-list{padding:.75rem}.project-list-loading,.project-list-empty{padding:2rem;text-align:center;color:var(--text-secondary)}.project-list-empty .hint{font-size:12px;color:var(--text-tertiary);margin-top:.5rem}.project-item{padding:.875rem;margin-bottom:.5rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all .15s ease;position:relative}.project-item:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:transparent;transition:background .15s ease}.project-item:hover{background:var(--bg-hover);border-color:var(--border-hover);transform:translate(2px)}.project-item:hover:before{background:var(--accent-cyan)}.project-item.selected{background:var(--bg-hover);border-color:var(--accent-cyan);box-shadow:var(--shadow-sm)}.project-item.keyboard-focused{outline:2px solid var(--accent-cyan);outline-offset:-2px;background:var(--bg-hover)}.project-item.selected:before{background:var(--accent-cyan)}.project-item-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.5rem;gap:.5rem}.project-name{font-size:13px;font-weight:600;color:var(--text-primary);margin:0;flex:1;font-family:inherit;letter-spacing:.2px}.project-remove-btn{background:transparent;border:1px solid transparent;font-size:18px;color:var(--text-tertiary);cursor:pointer;padding:0;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:3px;transition:all .15s ease;flex-shrink:0;line-height:1}.project-remove-btn:hover{background:#ff52521a;color:#ff5252;border-color:#ff52524d}.project-path{font-size:11px;color:var(--text-tertiary);margin:.25rem 0;word-break:break-all;font-family:SF Mono,Monaco,monospace;opacity:.8}.project-meta{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem;font-size:11px;color:var(--text-tertiary);gap:.5rem}.project-tags{display:flex;flex-wrap:wrap;gap:.375rem;margin-top:.5rem}.project-tag{background:var(--bg-hover);border:1px solid var(--border-color);padding:.125rem .5rem;border-radius:3px;font-size:10px;font-weight:500;color:var(--accent-cyan);font-family:SF Mono,Monaco,monospace;text-transform:uppercase;letter-spacing:.3px}.project-scanned{flex:1;font-family:SF Mono,Monaco,monospace}.project-scan-btn{background:transparent;border:1px solid var(--border-color);font-size:12px;cursor:pointer;padding:.25rem .5rem;border-radius:3px;transition:all .15s ease;color:var(--text-secondary);font-family:inherit}.project-scan-btn:hover:not(:disabled){background:var(--bg-hover);border-color:var(--accent-green);color:var(--accent-green)}.project-scan-btn:disabled{opacity:.3;cursor:not-allowed}.running-indicator-dot{color:var(--accent-green);margin-right:.5rem;font-size:10px;animation:pulse 2s infinite}.project-item.running:before{background:var(--accent-green)}.running-count{background:var(--accent-green);color:var(--bg-primary);padding:.125rem .5rem;border-radius:10px;font-size:10px;font-weight:600;font-family:SF Mono,Monaco,monospace}.running-ports{display:flex;gap:.25rem;flex-wrap:wrap}.port-badge{background:var(--accent-blue);color:var(--bg-primary);padding:.125rem .5rem;border-radius:3px;font-size:10px;font-weight:600;font-family:SF Mono,Monaco,monospace}.project-urls-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.urls-list{display:flex;flex-direction:column;gap:.5rem}.url-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.url-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.url-text{font-family:SF Mono,Monaco,monospace;font-size:12px;color:var(--accent-cyan);flex:1;word-break:break-all;cursor:pointer;text-decoration:underline}.url-text:hover{color:var(--accent-blue)}.project-details{max-width:1000px}.project-details-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1.5rem;padding-bottom:1rem;border-bottom:1px solid var(--border-color);gap:1rem}.project-details-header h2{font-size:18px;color:var(--text-primary);margin-bottom:.5rem;font-weight:600;font-family:inherit;letter-spacing:.3px}.project-name-editable{cursor:pointer;transition:color .15s ease}.project-name-editable:hover{color:var(--accent-cyan)}.project-name-edit{margin-bottom:.5rem}.project-name-input{background:var(--bg-tertiary);border:1px solid var(--accent-cyan);border-radius:4px;padding:.5rem;font-size:18px;font-weight:600;color:var(--text-primary);font-family:inherit;width:100%;max-width:400px}.project-name-input:focus{outline:none;box-shadow:0 0 0 2px #39c5cf33}.project-description-edit{margin-bottom:.5rem}.project-description-input{background:var(--bg-tertiary);border:1px solid var(--accent-cyan);border-radius:4px;padding:.5rem;font-size:13px;color:var(--text-primary);font-family:inherit;width:100%;max-width:600px;resize:vertical;min-height:60px}.project-description-input:focus{outline:none;box-shadow:0 0 0 2px #39c5cf33}.project-description{cursor:pointer;color:var(--text-secondary);font-size:13px;transition:color .15s ease;margin-bottom:.5rem}.project-description:hover{color:var(--text-primary)}.header-actions-group{display:flex;gap:.5rem;align-items:center}.project-path{color:var(--text-tertiary);font-size:11px;word-break:break-all;font-family:SF Mono,Monaco,monospace;opacity:.8}.project-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.75rem;margin-bottom:1.5rem}.stat-card{background:var(--bg-secondary);padding:1rem;border-radius:4px;border:1px solid var(--border-color);text-align:left;transition:all .15s ease}.stat-card:hover{border-color:var(--border-hover);background:var(--bg-tertiary)}.stat-value{font-size:24px;font-weight:600;color:var(--accent-cyan);margin-bottom:.25rem;font-family:SF Mono,Monaco,monospace;line-height:1.2}.stat-label{font-size:11px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.5px;font-weight:500}.framework-breakdown{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.framework-breakdown h3{font-size:13px;color:var(--text-primary);margin-bottom:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.framework-list{display:flex;flex-wrap:wrap;gap:.5rem}.framework-item{display:flex;align-items:center;gap:.5rem;padding:.375rem .75rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;transition:all .15s ease}.framework-item:hover{border-color:var(--accent-purple);background:var(--bg-hover)}.framework-name{font-weight:500;color:var(--text-primary);font-size:12px;font-family:SF Mono,Monaco,monospace}.framework-count{background:var(--accent-purple);color:var(--bg-primary);padding:.125rem .5rem;border-radius:2px;font-size:11px;font-weight:600;font-family:SF Mono,Monaco,monospace}.tests-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.tests-section h3{font-size:13px;color:var(--text-primary);margin-bottom:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.no-tests{padding:2rem;text-align:center;color:var(--text-tertiary);font-size:12px}.tests-list{display:flex;flex-direction:column;gap:.5rem}.test-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease}.test-item:hover{background:var(--bg-hover);border-color:var(--border-hover);transform:translate(2px)}.test-file{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem;gap:.75rem}.test-path{font-family:SF Mono,Monaco,monospace;font-size:12px;color:var(--text-primary);flex:1;word-break:break-all}.test-framework{background:var(--accent-blue);color:var(--bg-primary);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;font-family:SF Mono,Monaco,monospace;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0}.test-status{font-size:11px;color:var(--text-tertiary);font-family:SF Mono,Monaco,monospace}.jenkins-placeholder{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px dashed var(--border-color);opacity:.6}.jenkins-placeholder h3{font-size:13px;color:var(--text-secondary);margin-bottom:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.placeholder-text{color:var(--text-tertiary);font-style:italic;font-size:12px;line-height:1.6}.danger-zone{background:#f851490d;padding:1.25rem;border-radius:4px;border:1px solid rgba(248,81,73,.3);margin-top:1.5rem}.danger-zone h3{font-size:13px;color:#f85149;margin-bottom:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.danger-zone-text{color:var(--text-secondary);font-size:12px;line-height:1.6;margin-bottom:1rem}.danger-zone .btn-danger{background:transparent;border:1px solid #f85149;color:#f85149}.danger-zone .btn-danger:hover:not(:disabled){background:#f85149;color:var(--bg-primary)}.btn-small{padding:.375rem .75rem;font-size:11px}.tags-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.tags-content{margin-top:.75rem}.tags-list{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}.tag-item{background:var(--bg-tertiary);border:1px solid var(--border-color);padding:.375rem .375rem .375rem .625rem;border-radius:4px;font-size:11px;font-weight:500;color:var(--accent-cyan);font-family:SF Mono,Monaco,monospace;text-transform:uppercase;letter-spacing:.3px;display:flex;align-items:center;gap:.375rem;transition:all .15s ease}.tag-item:hover{border-color:var(--accent-cyan)}.tag-remove{background:none;border:none;color:var(--text-tertiary);cursor:pointer;padding:0 4px;font-size:16px;line-height:1;transition:color .15s ease}.tag-remove:hover{color:#f85149}.tag-add-btn{background:transparent;border:1px dashed var(--border-color);padding:.375rem .75rem;border-radius:4px;font-size:11px;font-weight:500;color:var(--text-secondary);cursor:pointer;transition:all .15s ease;text-transform:uppercase;letter-spacing:.3px}.tag-add-btn:hover{border-color:var(--accent-cyan);color:var(--accent-cyan);background:var(--bg-tertiary)}.tag-input-wrapper{position:relative;display:inline-block}.tag-input{background:var(--bg-tertiary);border:1px solid var(--accent-cyan);border-radius:4px;padding:.375rem .625rem;font-size:11px;font-family:SF Mono,Monaco,monospace;color:var(--text-primary);min-width:120px;outline:none}.tag-input:focus{box-shadow:0 0 0 2px #39c5cf33}.tag-suggestions{position:absolute;top:calc(100% + 4px);left:0;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;box-shadow:var(--shadow-md);z-index:100;min-width:100%;max-width:200px}.tag-suggestion{padding:.5rem .75rem;cursor:pointer;font-size:11px;color:var(--text-primary);font-family:SF Mono,Monaco,monospace;transition:all .15s ease}.tag-suggestion:first-child{border-radius:4px 4px 0 0}.tag-suggestion:last-child{border-radius:0 0 4px 4px}.tag-suggestion:hover{background:var(--bg-hover);color:var(--accent-cyan)}.ports-section,.scripts-section,.running-processes-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.section-header h3{font-size:13px;color:var(--text-primary);font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit;margin:0}.project-type-badge{background:var(--bg-tertiary);border:1px solid var(--border-color);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.3px;font-family:SF Mono,Monaco,monospace}.ports-list,.scripts-list,.processes-list{display:flex;flex-direction:column;gap:.5rem}.port-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease}.port-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.port-info{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.port-number{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--accent-cyan)}.port-script{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary)}.port-source{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-tertiary);flex:1}.script-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.script-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.script-info{display:flex;align-items:center;gap:.75rem;flex:1;flex-wrap:wrap}.script-name{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--text-primary);min-width:80px}.script-command{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary);flex:1;word-break:break-all}.script-runner{background:var(--bg-hover);border:1px solid var(--border-color);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.3px;font-family:SF Mono,Monaco,monospace;flex-shrink:0}.script-actions{display:flex;gap:.5rem;flex-shrink:0}.loading-state,.no-scripts{padding:2rem;text-align:center;color:var(--text-tertiary);font-size:12px}.running-indicator{color:var(--accent-green);font-size:12px;margin-right:.5rem;animation:pulse 2s infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.process-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.process-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.process-info{display:flex;align-items:center;gap:.75rem;flex:1;flex-wrap:wrap}.process-name{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--text-primary);min-width:100px}.process-pid{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary)}.process-uptime{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-tertiary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:1000}.modal-content{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;width:90%;max-width:500px;box-shadow:var(--shadow-lg);animation:modalSlideIn .2s ease}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:1.25rem;border-bottom:1px solid var(--border-color)}.modal-header h2{font-size:14px;color:var(--text-primary);margin:0;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.modal-close{background:transparent;border:1px solid transparent;font-size:20px;color:var(--text-tertiary);cursor:pointer;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:3px;transition:all .15s ease;line-height:1}.modal-close:hover{background:var(--bg-hover);color:var(--text-primary);border-color:var(--border-color)}.modal-content form{padding:1.25rem}.form-group{margin-bottom:1.25rem}.form-group label{display:block;margin-bottom:.5rem;font-weight:500;color:var(--text-primary);font-size:12px;text-transform:uppercase;letter-spacing:.3px;font-family:inherit}.path-input-group{display:flex;gap:.5rem}.path-input-group input{flex:1;padding:.625rem;border:1px solid var(--border-color);border-radius:4px;font-size:12px;font-family:SF Mono,Monaco,monospace;background:var(--bg-tertiary);color:var(--text-primary);transition:all .15s ease}.path-input-group input::placeholder{color:var(--text-tertiary);opacity:.6}.path-input-group input:focus{outline:none;border-color:var(--accent-cyan);box-shadow:0 0 0 2px #39c5cf1a;background:var(--bg-hover)}.path-input-group input:disabled{background:var(--bg-primary);cursor:not-allowed;opacity:.5}.modal-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1.25rem}.project-search{padding:12px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);position:sticky;top:0;z-index:10}.search-input-group{display:flex;gap:8px;position:relative}.search-input-wrapper{flex:1;position:relative;display:flex;align-items:center}.search-input{flex:1;padding:8px 36px 8px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;outline:none;transition:border-color .2s;background:var(--bg-tertiary);color:var(--text-primary)}.sort-icon-btn{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--text-tertiary);cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;border-radius:3px;transition:all .15s ease}.sort-icon-btn:hover{color:var(--text-primary);background:var(--bg-hover)}.sort-menu{position:absolute;top:calc(100% + 4px);right:0;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;box-shadow:var(--shadow-md);z-index:100;min-width:180px;padding:4px}.sort-menu-item{padding:8px 12px;cursor:pointer;border-radius:3px;font-size:13px;color:var(--text-primary);display:flex;justify-content:space-between;align-items:center;transition:all .15s ease}.sort-menu-item:hover{background:var(--bg-hover)}.sort-menu-item.active{background:var(--bg-hover);color:var(--accent-cyan)}.sort-menu-item .checkmark{color:var(--accent-green);font-size:12px;margin-left:8px}.search-input:focus{border-color:var(--accent-cyan)}.search-input::placeholder{color:var(--text-tertiary)}.search-filter{padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;background:var(--bg-tertiary);color:var(--text-primary);cursor:pointer;outline:none;transition:border-color .2s}.search-filter:focus{border-color:var(--accent-cyan)}.search-filter:hover{border-color:var(--border-hover);background:var(--bg-hover)}.settings-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.settings-modal{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;width:90%;max-width:600px;max-height:90vh;display:flex;flex-direction:column;box-shadow:var(--shadow-lg)}.settings-header{display:flex;justify-content:space-between;align-items:center;padding:1.5rem;border-bottom:1px solid var(--border-color)}.settings-header h2{font-size:18px;font-weight:600;color:var(--text-primary);margin:0}.settings-close-btn{background:none;border:none;color:var(--text-secondary);font-size:24px;cursor:pointer;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .15s ease}.settings-close-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.settings-content{padding:1.5rem;overflow-y:auto;flex:1}.settings-section{margin-bottom:2rem}.settings-section:last-child{margin-bottom:0}.settings-section h3{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:1rem;text-transform:uppercase;letter-spacing:.5px}.settings-field{margin-bottom:1rem}.settings-field:last-child{margin-bottom:0}.settings-field label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.3px}.settings-select,.settings-input{width:100%;padding:.75rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-primary);font-size:13px;font-family:inherit;outline:none;transition:border-color .15s ease}.settings-select:focus,.settings-input:focus{border-color:var(--accent-cyan)}.settings-input{font-family:SF Mono,Monaco,monospace}.settings-footer{display:flex;justify-content:flex-end;gap:.75rem;padding:1.5rem;border-top:1px solid var(--border-color)}.loading-state{padding:3rem;text-align:center;color:var(--text-tertiary);font-size:13px}.app-header{-webkit-app-region:drag;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:1rem}.app-header button,.app-header .btn,.app-header .btn-link,.app-header .header-actions{-webkit-app-region:no-drag}.status-bar{background:var(--bg-secondary);border-top:1px solid var(--border-color);padding:.5rem 1.5rem;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;font-size:11px;font-family:SF Mono,Monaco,monospace}.status-bar-content{display:flex;align-items:center;gap:1rem;width:100%;justify-content:space-between}.status-indicator{display:flex;align-items:center;gap:.5rem}.status-dot{width:6px;height:6px;border-radius:50%;display:inline-block}.status-dot.connected{background:var(--accent-green);box-shadow:0 0 4px var(--accent-green)}.status-dot.disconnected{background:#f85149;box-shadow:0 0 4px #f85149}.status-text{color:var(--text-secondary);font-size:11px;text-transform:uppercase;letter-spacing:.5px}.api-port{color:var(--text-tertiary);font-size:11px;font-family:SF Mono,Monaco,monospace}.app{display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg-primary)}.app-header{background:var(--bg-secondary);border-bottom:1px solid var(--border-color);padding:.5rem 1.5rem;display:flex;align-items:center;justify-content:center;gap:1rem;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);position:relative;z-index:10;flex-shrink:0}.app-header:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent 0%,var(--accent-cyan) 50%,transparent 100%);opacity:.3}.app-logo{margin:0;font-size:12px;font-weight:600;letter-spacing:1.5px;color:var(--accent-cyan);position:absolute;left:50%;transform:translate(-50%)}.header-actions{display:flex;gap:1.5rem;margin-left:auto}.btn-link{padding:0;border:none;background:none;font-size:11px;font-weight:500;cursor:pointer;transition:color .15s ease;font-family:inherit;letter-spacing:.3px;text-transform:uppercase;color:var(--text-secondary);-webkit-app-region:no-drag}.btn-link:hover:not(:disabled){color:var(--text-primary)}.btn-link:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.btn-link-primary{color:var(--accent-cyan)}.btn-link-primary:hover:not(:disabled){color:var(--accent-blue)}.btn{padding:.5rem 1rem;border:1px solid var(--border-color);border-radius:4px;font-size:12px;font-weight:500;cursor:pointer;transition:all .15s ease;font-family:inherit;letter-spacing:.3px;text-transform:uppercase;background:var(--bg-tertiary);color:var(--text-primary)}.btn:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.btn-primary{background:var(--accent-cyan);color:var(--bg-primary);border-color:var(--accent-cyan);font-weight:600}.btn-primary:hover:not(:disabled){background:var(--accent-blue);border-color:var(--accent-blue);transform:translateY(-1px);box-shadow:var(--shadow-sm)}.btn-secondary{background:transparent;color:var(--text-secondary);border-color:var(--border-color)}.btn-secondary:hover:not(:disabled){background:var(--bg-hover);border-color:var(--border-hover);color:var(--text-primary)}.btn-danger{background:transparent;color:#f85149;border-color:#f85149}.btn-danger:hover:not(:disabled){background:#f851491a;border-color:#f85149;color:#f85149}.app-content{display:flex;flex:1;overflow:hidden;position:relative}.react-resizable-handle{position:absolute;width:4px;right:-2px;top:0;bottom:0;cursor:col-resize;background:transparent;z-index:10}.react-resizable-handle:hover{background:var(--accent-cyan);opacity:.3}.react-resizable-handle:active{background:var(--accent-cyan);opacity:.6}.sidebar{width:100%;height:100%;background:var(--bg-secondary);border-right:1px solid var(--border-color);overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column}.sidebar::-webkit-scrollbar{width:6px}.sidebar::-webkit-scrollbar-track{background:var(--bg-primary)}.sidebar::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.sidebar::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.main-content{flex:1;overflow-y:auto;padding:1.5rem;background:var(--bg-primary)}.main-content::-webkit-scrollbar{width:6px}.main-content::-webkit-scrollbar-track{background:var(--bg-primary)}.main-content::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.main-content::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text-secondary);text-align:center;padding:2rem}.empty-state h2{margin-bottom:.5rem;color:var(--text-primary);font-size:16px;font-weight:500}.empty-state p{color:var(--text-tertiary);font-size:13px}.app-footer{background:var(--bg-secondary);border-top:1px solid var(--border-color);padding:.5rem 1.5rem;flex-shrink:0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: #0d1117;--bg-secondary: #161b22;--bg-tertiary: #1c2128;--bg-hover: #21262d;--border-color: #30363d;--border-hover: #484f58;--text-primary: #c9d1d9;--text-secondary: #8b949e;--text-tertiary: #6e7681;--accent-cyan: #39c5cf;--accent-blue: #58a6ff;--accent-green: #3fb950;--accent-purple: #bc8cff;--accent-orange: #ffa657;--shadow-sm: 0 1px 3px rgba(0, 0, 0, .3);--shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--shadow-lg: 0 8px 24px rgba(0, 0, 0, .5)}body{font-family:SF Mono,Monaco,Inconsolata,Fira Code,Fira Mono,Droid Sans Mono,Source Code Pro,Menlo,Consolas,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:var(--bg-primary);color:var(--text-primary);font-size:13px;line-height:1.5;-webkit-user-select:none;user-select:none}input,textarea,[contenteditable=true],[contenteditable=""]{-webkit-user-select:text;user-select:text}code{font-family:SF Mono,Monaco,Inconsolata,Fira Code,Fira Mono,Droid Sans Mono,Source Code Pro,Menlo,Consolas,Courier New,monospace}#root{width:100%;height:100vh}
@@ -1 +0,0 @@
1
- .project-list{padding:.75rem}.project-list-loading,.project-list-empty{padding:2rem;text-align:center;color:var(--text-secondary)}.project-list-empty .hint{font-size:12px;color:var(--text-tertiary);margin-top:.5rem}.project-item{padding:.875rem;margin-bottom:.5rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all .15s ease;position:relative}.project-item:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:transparent;transition:background .15s ease}.project-item:hover{background:var(--bg-hover);border-color:var(--border-hover);transform:translate(2px)}.project-item:hover:before{background:var(--accent-cyan)}.project-item.selected{background:var(--bg-hover);border-color:var(--accent-cyan);box-shadow:var(--shadow-sm)}.project-item.selected:before{background:var(--accent-cyan)}.project-item-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.5rem;gap:.5rem}.project-name{font-size:13px;font-weight:600;color:var(--text-primary);margin:0;flex:1;font-family:inherit;letter-spacing:.2px}.project-remove-btn{background:transparent;border:1px solid transparent;font-size:18px;color:var(--text-tertiary);cursor:pointer;padding:0;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:3px;transition:all .15s ease;flex-shrink:0;line-height:1}.project-remove-btn:hover{background:#ff52521a;color:#ff5252;border-color:#ff52524d}.project-path{font-size:11px;color:var(--text-tertiary);margin:.25rem 0;word-break:break-all;font-family:SF Mono,Monaco,monospace;opacity:.8}.project-meta{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem;font-size:11px;color:var(--text-tertiary);gap:.5rem}.project-scanned{flex:1;font-family:SF Mono,Monaco,monospace}.project-scan-btn{background:transparent;border:1px solid var(--border-color);font-size:12px;cursor:pointer;padding:.25rem .5rem;border-radius:3px;transition:all .15s ease;color:var(--text-secondary);font-family:inherit}.project-scan-btn:hover:not(:disabled){background:var(--bg-hover);border-color:var(--accent-green);color:var(--accent-green)}.project-scan-btn:disabled{opacity:.3;cursor:not-allowed}.project-urls-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.urls-list{display:flex;flex-direction:column;gap:.5rem}.url-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.url-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.url-text{font-family:SF Mono,Monaco,monospace;font-size:12px;color:var(--accent-cyan);flex:1;word-break:break-all;cursor:pointer;text-decoration:underline}.url-text:hover{color:var(--accent-blue)}.project-details{max-width:1000px}.project-details-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1.5rem;padding-bottom:1rem;border-bottom:1px solid var(--border-color);gap:1rem}.project-details-header h2{font-size:18px;color:var(--text-primary);margin-bottom:.5rem;font-weight:600;font-family:inherit;letter-spacing:.3px}.project-name-editable{cursor:pointer;transition:color .15s ease}.project-name-editable:hover{color:var(--accent-cyan)}.project-name-edit{margin-bottom:.5rem}.project-name-input{background:var(--bg-tertiary);border:1px solid var(--accent-cyan);border-radius:4px;padding:.5rem;font-size:18px;font-weight:600;color:var(--text-primary);font-family:inherit;width:100%;max-width:400px}.project-name-input:focus{outline:none;box-shadow:0 0 0 2px #39c5cf33}.header-actions-group{display:flex;gap:.5rem;align-items:center}.project-path{color:var(--text-tertiary);font-size:11px;word-break:break-all;font-family:SF Mono,Monaco,monospace;opacity:.8}.project-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.75rem;margin-bottom:1.5rem}.stat-card{background:var(--bg-secondary);padding:1rem;border-radius:4px;border:1px solid var(--border-color);text-align:left;transition:all .15s ease}.stat-card:hover{border-color:var(--border-hover);background:var(--bg-tertiary)}.stat-value{font-size:24px;font-weight:600;color:var(--accent-cyan);margin-bottom:.25rem;font-family:SF Mono,Monaco,monospace;line-height:1.2}.stat-label{font-size:11px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.5px;font-weight:500}.framework-breakdown{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.framework-breakdown h3{font-size:13px;color:var(--text-primary);margin-bottom:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.framework-list{display:flex;flex-wrap:wrap;gap:.5rem}.framework-item{display:flex;align-items:center;gap:.5rem;padding:.375rem .75rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;transition:all .15s ease}.framework-item:hover{border-color:var(--accent-purple);background:var(--bg-hover)}.framework-name{font-weight:500;color:var(--text-primary);font-size:12px;font-family:SF Mono,Monaco,monospace}.framework-count{background:var(--accent-purple);color:var(--bg-primary);padding:.125rem .5rem;border-radius:2px;font-size:11px;font-weight:600;font-family:SF Mono,Monaco,monospace}.tests-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.tests-section h3{font-size:13px;color:var(--text-primary);margin-bottom:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.no-tests{padding:2rem;text-align:center;color:var(--text-tertiary);font-size:12px}.tests-list{display:flex;flex-direction:column;gap:.5rem}.test-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease}.test-item:hover{background:var(--bg-hover);border-color:var(--border-hover);transform:translate(2px)}.test-file{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem;gap:.75rem}.test-path{font-family:SF Mono,Monaco,monospace;font-size:12px;color:var(--text-primary);flex:1;word-break:break-all}.test-framework{background:var(--accent-blue);color:var(--bg-primary);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;font-family:SF Mono,Monaco,monospace;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0}.test-status{font-size:11px;color:var(--text-tertiary);font-family:SF Mono,Monaco,monospace}.jenkins-placeholder{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px dashed var(--border-color);opacity:.6}.jenkins-placeholder h3{font-size:13px;color:var(--text-secondary);margin-bottom:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.placeholder-text{color:var(--text-tertiary);font-style:italic;font-size:12px;line-height:1.6}.btn-small{padding:.375rem .75rem;font-size:11px}.ports-section,.scripts-section,.running-processes-section{background:var(--bg-secondary);padding:1.25rem;border-radius:4px;border:1px solid var(--border-color);margin-bottom:1.5rem}.section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.section-header h3{font-size:13px;color:var(--text-primary);font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit;margin:0}.project-type-badge{background:var(--bg-tertiary);border:1px solid var(--border-color);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.3px;font-family:SF Mono,Monaco,monospace}.ports-list,.scripts-list,.processes-list{display:flex;flex-direction:column;gap:.5rem}.port-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease}.port-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.port-info{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.port-number{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--accent-cyan)}.port-script{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary)}.port-source{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-tertiary);flex:1}.script-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.script-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.script-info{display:flex;align-items:center;gap:.75rem;flex:1;flex-wrap:wrap}.script-name{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--text-primary);min-width:80px}.script-command{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary);flex:1;word-break:break-all}.script-runner{background:var(--bg-hover);border:1px solid var(--border-color);padding:.25rem .5rem;border-radius:3px;font-size:10px;font-weight:600;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.3px;font-family:SF Mono,Monaco,monospace;flex-shrink:0}.script-actions{display:flex;gap:.5rem;flex-shrink:0}.loading-state,.no-scripts{padding:2rem;text-align:center;color:var(--text-tertiary);font-size:12px}.running-indicator{color:var(--accent-green);font-size:12px;margin-right:.5rem;animation:pulse 2s infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.process-item{padding:.875rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease;display:flex;justify-content:space-between;align-items:center;gap:1rem}.process-item:hover{background:var(--bg-hover);border-color:var(--border-hover)}.process-info{display:flex;align-items:center;gap:.75rem;flex:1;flex-wrap:wrap}.process-name{font-family:SF Mono,Monaco,monospace;font-size:13px;font-weight:600;color:var(--text-primary);min-width:100px}.process-pid{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-secondary)}.process-uptime{font-family:SF Mono,Monaco,monospace;font-size:11px;color:var(--text-tertiary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:1000}.modal-content{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;width:90%;max-width:500px;box-shadow:var(--shadow-lg);animation:modalSlideIn .2s ease}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:1.25rem;border-bottom:1px solid var(--border-color)}.modal-header h2{font-size:14px;color:var(--text-primary);margin:0;font-weight:600;text-transform:uppercase;letter-spacing:.5px;font-family:inherit}.modal-close{background:transparent;border:1px solid transparent;font-size:20px;color:var(--text-tertiary);cursor:pointer;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:3px;transition:all .15s ease;line-height:1}.modal-close:hover{background:var(--bg-hover);color:var(--text-primary);border-color:var(--border-color)}.modal-content form{padding:1.25rem}.form-group{margin-bottom:1.25rem}.form-group label{display:block;margin-bottom:.5rem;font-weight:500;color:var(--text-primary);font-size:12px;text-transform:uppercase;letter-spacing:.3px;font-family:inherit}.path-input-group{display:flex;gap:.5rem}.path-input-group input{flex:1;padding:.625rem;border:1px solid var(--border-color);border-radius:4px;font-size:12px;font-family:SF Mono,Monaco,monospace;background:var(--bg-tertiary);color:var(--text-primary);transition:all .15s ease}.path-input-group input::placeholder{color:var(--text-tertiary);opacity:.6}.path-input-group input:focus{outline:none;border-color:var(--accent-cyan);box-shadow:0 0 0 2px #39c5cf1a;background:var(--bg-hover)}.path-input-group input:disabled{background:var(--bg-primary);cursor:not-allowed;opacity:.5}.modal-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1.25rem}.project-search{padding:12px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary)}.search-input-group{display:flex;gap:8px}.search-input{flex:1;padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;outline:none;transition:border-color .2s;background:var(--bg-tertiary);color:var(--text-primary)}.search-input:focus{border-color:var(--accent-cyan)}.search-input::placeholder{color:var(--text-tertiary)}.search-filter{padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;background:var(--bg-tertiary);color:var(--text-primary);cursor:pointer;outline:none;transition:border-color .2s}.search-filter:focus{border-color:var(--accent-cyan)}.search-filter:hover{border-color:var(--border-hover);background:var(--bg-hover)}.settings-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.settings-modal{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;width:90%;max-width:600px;max-height:90vh;display:flex;flex-direction:column;box-shadow:var(--shadow-lg)}.settings-header{display:flex;justify-content:space-between;align-items:center;padding:1.5rem;border-bottom:1px solid var(--border-color)}.settings-header h2{font-size:18px;font-weight:600;color:var(--text-primary);margin:0}.settings-close-btn{background:none;border:none;color:var(--text-secondary);font-size:24px;cursor:pointer;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .15s ease}.settings-close-btn:hover{background:var(--bg-tertiary);color:var(--text-primary)}.settings-content{padding:1.5rem;overflow-y:auto;flex:1}.settings-section{margin-bottom:2rem}.settings-section:last-child{margin-bottom:0}.settings-section h3{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:1rem;text-transform:uppercase;letter-spacing:.5px}.settings-field{margin-bottom:1rem}.settings-field:last-child{margin-bottom:0}.settings-field label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:.5rem;text-transform:uppercase;letter-spacing:.3px}.settings-select,.settings-input{width:100%;padding:.75rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-primary);font-size:13px;font-family:inherit;outline:none;transition:border-color .15s ease}.settings-select:focus,.settings-input:focus{border-color:var(--accent-cyan)}.settings-input{font-family:SF Mono,Monaco,monospace}.settings-footer{display:flex;justify-content:flex-end;gap:.75rem;padding:1.5rem;border-top:1px solid var(--border-color)}.loading-state{padding:3rem;text-align:center;color:var(--text-tertiary);font-size:13px}.app-header{-webkit-app-region:drag;-webkit-user-select:none;user-select:none}.status-bar{background:var(--bg-secondary);border-top:1px solid var(--border-color);padding:.5rem 1.5rem;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;font-size:11px;font-family:SF Mono,Monaco,monospace}.status-bar-content{display:flex;align-items:center;gap:1rem;width:100%;justify-content:space-between}.status-indicator{display:flex;align-items:center;gap:.5rem}.status-dot{width:6px;height:6px;border-radius:50%;display:inline-block}.status-dot.connected{background:var(--accent-green);box-shadow:0 0 4px var(--accent-green)}.status-dot.disconnected{background:#f85149;box-shadow:0 0 4px #f85149}.status-text{color:var(--text-secondary);font-size:11px;text-transform:uppercase;letter-spacing:.5px}.api-port{color:var(--text-tertiary);font-size:11px;font-family:SF Mono,Monaco,monospace}.app{display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg-primary)}.app-header{background:var(--bg-secondary);border-bottom:1px solid var(--border-color);padding:.875rem 1.5rem;display:flex;align-items:center;gap:1rem;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);position:relative;z-index:10;flex-shrink:0}.app-header:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent 0%,var(--accent-cyan) 50%,transparent 100%);opacity:.3}.app-header h1{font-size:14px;font-weight:600;color:var(--text-primary);letter-spacing:.5px;text-transform:uppercase;font-family:SF Mono,Monaco,monospace}.header-actions{display:flex;gap:.5rem}.btn{padding:.5rem 1rem;border:1px solid var(--border-color);border-radius:4px;font-size:12px;font-weight:500;cursor:pointer;transition:all .15s ease;font-family:inherit;letter-spacing:.3px;text-transform:uppercase;background:var(--bg-tertiary);color:var(--text-primary)}.btn:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.btn-primary{background:var(--accent-cyan);color:var(--bg-primary);border-color:var(--accent-cyan);font-weight:600}.btn-primary:hover:not(:disabled){background:var(--accent-blue);border-color:var(--accent-blue);transform:translateY(-1px);box-shadow:var(--shadow-sm)}.btn-secondary{background:transparent;color:var(--text-secondary);border-color:var(--border-color)}.btn-secondary:hover:not(:disabled){background:var(--bg-hover);border-color:var(--border-hover);color:var(--text-primary)}.btn-danger{background:transparent;color:#f85149;border-color:#f85149}.btn-danger:hover:not(:disabled){background:#f851491a;border-color:#f85149;color:#f85149}.app-content{display:flex;flex:1;overflow:hidden}.sidebar{width:280px;background:var(--bg-secondary);border-right:1px solid var(--border-color);overflow-y:auto;overflow-x:hidden}.sidebar::-webkit-scrollbar{width:6px}.sidebar::-webkit-scrollbar-track{background:var(--bg-primary)}.sidebar::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.sidebar::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.main-content{flex:1;overflow-y:auto;padding:1.5rem;background:var(--bg-primary)}.main-content::-webkit-scrollbar{width:6px}.main-content::-webkit-scrollbar-track{background:var(--bg-primary)}.main-content::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.main-content::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text-secondary);text-align:center;padding:2rem}.empty-state h2{margin-bottom:.5rem;color:var(--text-primary);font-size:16px;font-weight:500}.empty-state p{color:var(--text-tertiary);font-size:13px}.app-footer{background:var(--bg-secondary);border-top:1px solid var(--border-color);padding:.5rem 1.5rem;flex-shrink:0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: #0d1117;--bg-secondary: #161b22;--bg-tertiary: #1c2128;--bg-hover: #21262d;--border-color: #30363d;--border-hover: #484f58;--text-primary: #c9d1d9;--text-secondary: #8b949e;--text-tertiary: #6e7681;--accent-cyan: #39c5cf;--accent-blue: #58a6ff;--accent-green: #3fb950;--accent-purple: #bc8cff;--accent-orange: #ffa657;--shadow-sm: 0 1px 3px rgba(0, 0, 0, .3);--shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--shadow-lg: 0 8px 24px rgba(0, 0, 0, .5)}body{font-family:SF Mono,Monaco,Inconsolata,Fira Code,Fira Mono,Droid Sans Mono,Source Code Pro,Menlo,Consolas,Courier New,monospace;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:var(--bg-primary);color:var(--text-primary);font-size:13px;line-height:1.5}code{font-family:SF Mono,Monaco,Inconsolata,Fira Code,Fira Mono,Droid Sans Mono,Source Code Pro,Menlo,Consolas,Courier New,monospace}#root{width:100%;height:100vh}
package/dist/prxi.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/prxi.js DELETED
@@ -1,297 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || (function () {
20
- var ownKeys = function(o) {
21
- ownKeys = Object.getOwnPropertyNames || function (o) {
22
- var ar = [];
23
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
- return ar;
25
- };
26
- return ownKeys(o);
27
- };
28
- return function (mod) {
29
- if (mod && mod.__esModule) return mod;
30
- var result = {};
31
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
- __setModuleDefault(result, mod);
33
- return result;
34
- };
35
- })();
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- const react_1 = __importStar(require("react"));
38
- const ink_1 = require("ink");
39
- const core_bridge_1 = require("./core-bridge");
40
- const script_runner_1 = require("./script-runner");
41
- // Color scheme matching desktop app
42
- const colors = {
43
- bgPrimary: '#0d1117',
44
- bgSecondary: '#161b22',
45
- bgTertiary: '#1c2128',
46
- bgHover: '#21262d',
47
- borderColor: '#30363d',
48
- textPrimary: '#c9d1d9',
49
- textSecondary: '#8b949e',
50
- textTertiary: '#6e7681',
51
- accentCyan: '#39c5cf',
52
- accentBlue: '#58a6ff',
53
- accentGreen: '#3fb950',
54
- accentPurple: '#bc8cff',
55
- accentOrange: '#ffa657',
56
- };
57
- const HelpModal = ({ onClose }) => {
58
- (0, ink_1.useInput)((input, key) => {
59
- if (input === 'q' || key.escape || key.return) {
60
- onClose();
61
- }
62
- });
63
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", borderStyle: "round", borderColor: colors.accentCyan, padding: 1, width: 60 },
64
- react_1.default.createElement(ink_1.Text, { bold: true, color: colors.accentCyan }, "PROJAX Terminal UI - Help"),
65
- react_1.default.createElement(ink_1.Text, null, " "),
66
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, "Navigation:"),
67
- react_1.default.createElement(ink_1.Text, null, " \u2191/k Move up in project list"),
68
- react_1.default.createElement(ink_1.Text, null, " \u2193/j Move down in project list"),
69
- react_1.default.createElement(ink_1.Text, null, " Enter Select project"),
70
- react_1.default.createElement(ink_1.Text, null, " "),
71
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, "Actions:"),
72
- react_1.default.createElement(ink_1.Text, null, " s Scan selected project"),
73
- react_1.default.createElement(ink_1.Text, null, " p Scan ports"),
74
- react_1.default.createElement(ink_1.Text, null, " "),
75
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, "General:"),
76
- react_1.default.createElement(ink_1.Text, null, " q/Esc Quit"),
77
- react_1.default.createElement(ink_1.Text, null, " ? Show this help"),
78
- react_1.default.createElement(ink_1.Text, null, " "),
79
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "Press any key to close...")));
80
- };
81
- const LoadingModal = ({ message }) => {
82
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", borderStyle: "round", borderColor: colors.accentCyan, padding: 1, width: 40 },
83
- react_1.default.createElement(ink_1.Text, null, message),
84
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "Please wait...")));
85
- };
86
- const ErrorModal = ({ message, onClose }) => {
87
- (0, ink_1.useInput)((input, key) => {
88
- if (key.escape || key.return) {
89
- onClose();
90
- }
91
- });
92
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f85149", padding: 1, width: 50 },
93
- react_1.default.createElement(ink_1.Text, { color: "#f85149", bold: true }, "Error"),
94
- react_1.default.createElement(ink_1.Text, null, " "),
95
- react_1.default.createElement(ink_1.Text, null, message),
96
- react_1.default.createElement(ink_1.Text, null, " "),
97
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "Press any key to close...")));
98
- };
99
- const ProjectListComponent = ({ projects, selectedIndex }) => {
100
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", width: "30%", borderStyle: "round", borderColor: colors.borderColor, padding: 1 },
101
- react_1.default.createElement(ink_1.Text, { bold: true, color: colors.textPrimary }, "Projects"),
102
- react_1.default.createElement(ink_1.Text, null, " "),
103
- projects.length === 0 ? (react_1.default.createElement(ink_1.Text, { color: colors.textTertiary }, "No projects found")) : (projects.map((project, index) => {
104
- const isSelected = index === selectedIndex;
105
- const desc = project.description || project.path;
106
- const shortDesc = desc.length > 30 ? desc.substring(0, 27) + '...' : desc;
107
- return (react_1.default.createElement(ink_1.Text, { key: project.id, color: isSelected ? colors.accentCyan : colors.textPrimary, bold: isSelected },
108
- isSelected ? '▶ ' : ' ',
109
- project.name,
110
- " - ",
111
- shortDesc));
112
- }))));
113
- };
114
- const ProjectDetailsComponent = ({ project }) => {
115
- const [scripts, setScripts] = (0, react_1.useState)(null);
116
- const [ports, setPorts] = (0, react_1.useState)([]);
117
- (0, react_1.useEffect)(() => {
118
- if (!project) {
119
- setScripts(null);
120
- setPorts([]);
121
- return;
122
- }
123
- // Load scripts
124
- try {
125
- const projectScripts = (0, script_runner_1.getProjectScripts)(project.path);
126
- setScripts(projectScripts);
127
- }
128
- catch (error) {
129
- setScripts(null);
130
- }
131
- // Load ports
132
- try {
133
- const db = (0, core_bridge_1.getDatabaseManager)();
134
- const projectPorts = db.getProjectPorts(project.id);
135
- setPorts(projectPorts);
136
- }
137
- catch (error) {
138
- setPorts([]);
139
- }
140
- }, [project]);
141
- if (!project) {
142
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: colors.borderColor, padding: 1 },
143
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "Select a project to view details")));
144
- }
145
- const lastScanned = project.last_scanned
146
- ? new Date(project.last_scanned * 1000).toLocaleString()
147
- : 'Never';
148
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: colors.borderColor, padding: 1 },
149
- react_1.default.createElement(ink_1.Text, { bold: true, color: colors.textPrimary }, project.name),
150
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, project.description || project.path),
151
- react_1.default.createElement(ink_1.Text, { color: colors.textTertiary }, project.path),
152
- react_1.default.createElement(ink_1.Text, null, " "),
153
- project.framework && (react_1.default.createElement(react_1.default.Fragment, null,
154
- react_1.default.createElement(ink_1.Text, null,
155
- "Framework: ",
156
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, project.framework)))),
157
- react_1.default.createElement(ink_1.Text, null,
158
- "Last Scanned: ",
159
- lastScanned),
160
- react_1.default.createElement(ink_1.Text, null, " "),
161
- scripts && scripts.scripts && scripts.scripts.size > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
162
- react_1.default.createElement(ink_1.Text, { bold: true },
163
- "Available Scripts (",
164
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, scripts.scripts.size),
165
- "):"),
166
- Array.from(scripts.scripts.entries()).map(([name, script]) => (react_1.default.createElement(ink_1.Text, { key: name },
167
- ' ',
168
- react_1.default.createElement(ink_1.Text, { color: colors.accentGreen }, name),
169
- ' - ',
170
- script.command))),
171
- react_1.default.createElement(ink_1.Text, null, " "))),
172
- ports.length > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
173
- react_1.default.createElement(ink_1.Text, { bold: true },
174
- "Detected Ports (",
175
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, ports.length),
176
- "):"),
177
- ports.map((port) => (react_1.default.createElement(ink_1.Text, { key: port.id },
178
- ' ',
179
- "Port ",
180
- react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, port.port),
181
- " - ",
182
- port.config_source))),
183
- react_1.default.createElement(ink_1.Text, null, " ")))));
184
- };
185
- const StatusBar = () => {
186
- return (react_1.default.createElement(ink_1.Box, null,
187
- react_1.default.createElement(ink_1.Text, { color: colors.accentGreen }, "\u25CF API CONNECTED"),
188
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, " | Press "),
189
- react_1.default.createElement(ink_1.Text, { bold: true }, "q"),
190
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, " to quit, "),
191
- react_1.default.createElement(ink_1.Text, { bold: true }, "?"),
192
- react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, " for help")));
193
- };
194
- const App = () => {
195
- const { exit } = (0, ink_1.useApp)();
196
- const [projects, setProjects] = (0, react_1.useState)([]);
197
- const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(0);
198
- const [showHelp, setShowHelp] = (0, react_1.useState)(false);
199
- const [isLoading, setIsLoading] = (0, react_1.useState)(false);
200
- const [loadingMessage, setLoadingMessage] = (0, react_1.useState)('');
201
- const [error, setError] = (0, react_1.useState)(null);
202
- (0, react_1.useEffect)(() => {
203
- loadProjects();
204
- }, []);
205
- const loadProjects = () => {
206
- const allProjects = (0, core_bridge_1.getAllProjects)();
207
- setProjects(allProjects);
208
- if (selectedIndex >= allProjects.length) {
209
- setSelectedIndex(Math.max(0, allProjects.length - 1));
210
- }
211
- };
212
- const selectedProject = projects.length > 0 ? projects[selectedIndex] : null;
213
- (0, ink_1.useInput)((input, key) => {
214
- // Don't process input if modal is showing
215
- if (showHelp || isLoading || error) {
216
- return;
217
- }
218
- // Quit
219
- if (input === 'q' || key.escape) {
220
- exit();
221
- return;
222
- }
223
- // Help
224
- if (input === '?') {
225
- setShowHelp(true);
226
- return;
227
- }
228
- // Navigation
229
- if (key.upArrow || input === 'k') {
230
- setSelectedIndex((prev) => Math.max(0, prev - 1));
231
- return;
232
- }
233
- if (key.downArrow || input === 'j') {
234
- setSelectedIndex((prev) => Math.min(projects.length - 1, prev + 1));
235
- return;
236
- }
237
- // Scan project
238
- if (input === 's' && selectedProject) {
239
- setIsLoading(true);
240
- setLoadingMessage(`Scanning ${selectedProject.name}...`);
241
- setTimeout(async () => {
242
- try {
243
- await (0, core_bridge_1.scanProject)(selectedProject.id);
244
- loadProjects();
245
- setIsLoading(false);
246
- }
247
- catch (err) {
248
- setIsLoading(false);
249
- setError(err instanceof Error ? err.message : String(err));
250
- }
251
- }, 100);
252
- return;
253
- }
254
- // Scan ports
255
- if (input === 'p' && selectedProject) {
256
- setIsLoading(true);
257
- setLoadingMessage(`Scanning ports for ${selectedProject.name}...`);
258
- setTimeout(async () => {
259
- try {
260
- // Import port scanner dynamically
261
- const { scanProjectPorts } = await Promise.resolve().then(() => __importStar(require('./port-scanner')));
262
- await scanProjectPorts(selectedProject.id);
263
- loadProjects();
264
- setIsLoading(false);
265
- }
266
- catch (err) {
267
- setIsLoading(false);
268
- setError(err instanceof Error ? err.message : String(err));
269
- }
270
- }, 100);
271
- return;
272
- }
273
- });
274
- if (showHelp) {
275
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 1 },
276
- react_1.default.createElement(HelpModal, { onClose: () => setShowHelp(false) })));
277
- }
278
- if (isLoading) {
279
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 1 },
280
- react_1.default.createElement(LoadingModal, { message: loadingMessage })));
281
- }
282
- if (error) {
283
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 1 },
284
- react_1.default.createElement(ErrorModal, { message: error, onClose: () => setError(null) })));
285
- }
286
- return (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 1 },
287
- react_1.default.createElement(ink_1.Box, { borderStyle: "round", borderColor: colors.borderColor, padding: 1 },
288
- react_1.default.createElement(ink_1.Text, { bold: true, color: colors.accentCyan }, "PROJAX")),
289
- react_1.default.createElement(ink_1.Box, { flexDirection: "row", marginTop: 1 },
290
- react_1.default.createElement(ProjectListComponent, { projects: projects, selectedIndex: selectedIndex }),
291
- react_1.default.createElement(ink_1.Box, { width: 1 }),
292
- react_1.default.createElement(ProjectDetailsComponent, { project: selectedProject })),
293
- react_1.default.createElement(ink_1.Box, { marginTop: 1 },
294
- react_1.default.createElement(StatusBar, null))));
295
- };
296
- // Render the app
297
- (0, ink_1.render)(react_1.default.createElement(App, null));