projax 3.3.28 → 3.3.29

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.
@@ -0,0 +1 @@
1
+ .project-list{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0;padding:.75rem}.project-list::-webkit-scrollbar{width:6px}.project-list::-webkit-scrollbar-track{background:var(--bg-primary)}.project-list::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.project-list::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.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}.btn-small{padding:.35rem .75rem;font-size:11px}.btn-tiny{padding:.25rem .5rem;font-size:10px;display:inline-flex;align-items:center;gap:4px}.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-item.running{border-left:3px solid var(--accent-cyan)}.script-info{display:flex;flex-direction:column;gap:.5rem;flex:1}.script-header{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.script-process-info{display:flex;flex-direction:column;gap:.375rem;margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--border-color)}.process-badge{display:flex;align-items:center;gap:.5rem;font-size:11px;font-family:SF Mono,Monaco,monospace;color:var(--text-secondary)}.process-badge .btn:first-of-type{margin-left:auto}.process-indicator{color:var(--accent-cyan);font-size:8px}.process-pid{color:var(--text-secondary)}.process-uptime{color:var(--text-tertiary)}.process-port{color:var(--accent-cyan);font-weight:600}.btn-tiny{padding:2px 8px;font-size:10px;font-weight:600;border-radius:4px;margin-left:4px}.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)}.test-results-section{margin-bottom:2rem;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:6px;padding:1.25rem;transition:all .15s ease}.test-results-section .section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.test-timestamp{font-size:10px;color:var(--text-tertiary);font-family:SF Mono,Monaco,monospace;letter-spacing:.3px}.test-results-content{display:flex;flex-direction:column;gap:1rem}.test-stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:.75rem}.test-stat{display:flex;align-items:center;gap:.625rem;padding:.75rem;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;transition:all .15s ease}.test-stat:hover{background:var(--bg-hover);border-color:var(--border-hover)}.test-stat.passed{border-left:3px solid var(--accent-green)}.test-stat.failed{border-left:3px solid #f85149}.test-stat.skipped{border-left:3px solid var(--text-tertiary)}.test-stat.total{border-left:3px solid var(--accent-cyan)}.test-stat-icon{font-size:20px;line-height:1}.test-stat.passed .test-stat-icon{color:var(--accent-green)}.test-stat.failed .test-stat-icon{color:#f85149}.test-stat.skipped .test-stat-icon{color:var(--text-tertiary);opacity:.6}.test-stat.total .test-stat-icon{color:var(--accent-cyan)}.test-stat-info{display:flex;flex-direction:column;gap:.125rem}.test-stat-value{font-size:24px;font-weight:700;color:var(--text-primary);line-height:1;font-family:SF Mono,Monaco,monospace}.test-stat-label{font-size:10px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.5px;font-weight:600}.test-meta{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;padding-top:.75rem;border-top:1px solid var(--border-color)}.test-framework-badge{display:inline-flex;align-items:center;padding:.25rem .625rem;background:#7d76fc1a;border:1px solid var(--accent-purple);border-radius:3px;font-size:10px;font-weight:600;color:var(--accent-purple);text-transform:uppercase;letter-spacing:.5px}.test-duration,.test-coverage,.test-script-name{font-size:11px;color:var(--text-secondary);font-family:SF Mono,Monaco,monospace;letter-spacing:.3px}.test-coverage{color:var(--accent-cyan);font-weight:500}.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);flex-shrink: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-version{color:var(--text-tertiary);font-size:11px;font-family:SF Mono,Monaco,monospace;font-weight:500;letter-spacing:.3px}.status-right{display:flex;align-items:center;gap:1rem}.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}.terminal-sidebar{display:flex;flex-direction:column;width:100%;height:100%;background:var(--bg-secondary);border-left:1px solid var(--border-color);color:var(--text-primary);font-family:SF Mono,Monaco,Courier New,monospace;font-size:12px}.terminal-header{display:flex;flex-direction:column;gap:.75rem;padding:1rem;background:var(--bg-tertiary);border-bottom:1px solid var(--border-color);position:relative}.terminal-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}.terminal-title-row{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}.terminal-title-content{display:flex;align-items:flex-start;gap:.625rem;flex:1}.terminal-status-indicator{font-size:10px;margin-top:2px;flex-shrink:0}.terminal-status-indicator.running{color:var(--accent-cyan);animation:pulse 2s infinite}.terminal-status-indicator.stopped{color:var(--text-tertiary);opacity:.5}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}.terminal-info{display:flex;flex-direction:column;gap:.25rem;flex:1;min-width:0}.terminal-script{font-weight:600;color:var(--text-primary);font-size:13px;letter-spacing:.3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.terminal-project{font-size:10px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.terminal-meta{display:flex;flex-direction:column;align-items:flex-end;gap:.25rem;flex-shrink:0}.terminal-status-badge{font-size:10px;padding:.25rem .5rem;border-radius:3px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;border:1px solid}.terminal-status-badge.running{color:var(--accent-cyan);background:#39c5cf1a;border-color:var(--accent-cyan)}.terminal-status-badge.stopped{color:var(--text-tertiary);background:var(--bg-secondary);border-color:var(--border-color)}.terminal-pid{font-size:10px;color:var(--text-tertiary);letter-spacing:.3px}.terminal-toolbar{display:flex;gap:.5rem;align-items:center}.terminal-output{flex:1;overflow-y:auto;padding:1rem;line-height:1.6;white-space:pre-wrap;word-wrap:break-word;background:var(--bg-primary);font-size:11px}.terminal-output::-webkit-scrollbar{width:6px}.terminal-output::-webkit-scrollbar-track{background:var(--bg-primary)}.terminal-output::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.terminal-output::-webkit-scrollbar-thumb:hover{background:var(--border-hover)}.terminal-line{margin-bottom:.125rem;padding:.125rem 0;color:var(--text-secondary);transition:background .15s ease}.terminal-line:hover{background:var(--bg-secondary);margin-left:-.5rem;margin-right:-.5rem;padding-left:.5rem;padding-right:.5rem;border-radius:2px}.terminal-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text-tertiary);padding:3rem 2rem;text-align:center;gap:.75rem}.terminal-empty-icon{font-size:48px;opacity:.3;margin-bottom:.5rem}.terminal-empty-text{font-size:13px;color:var(--text-secondary);font-weight:500}.terminal-empty-hint{font-size:11px;color:var(--text-tertiary);font-family:SF Mono,Monaco,monospace;letter-spacing:.3px}.terminal-line{color:var(--text-secondary)}.terminal-line:contains("error"),.terminal-line:contains("Error"),.terminal-line:contains("ERROR"),.terminal-line:contains("✗"),.terminal-line:contains("failed"),.terminal-line:contains("Failed"){color:#f85149}.terminal-line:contains("warning"),.terminal-line:contains("Warning"),.terminal-line:contains("WARN"),.terminal-line:contains("⚠"){color:#d29922}.terminal-line:contains("success"),.terminal-line:contains("Success"),.terminal-line:contains("✓"),.terminal-line:contains("✔"),.terminal-line:contains("passed"),.terminal-line:contains("Passed"){color:var(--accent-cyan)}.terminal-line:contains("info"),.terminal-line:contains("Info"),.terminal-line:contains("INFO"){color:var(--accent-blue)}.terminal-line:contains("debug"),.terminal-line:contains("Debug"),.terminal-line:contains("DEBUG"){color:var(--text-tertiary);opacity:.7}.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}.btn-tiny{padding:.25rem .5rem;font-size:10px}.terminal-icon{font-size:14px;display:inline-block}.app-content{display:flex;flex:1;overflow:hidden;position:relative}.app-content-with-terminal{display:grid;grid-template-columns:auto 1fr auto;flex:1;overflow:hidden}.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: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}
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' http://localhost:* ws://localhost:*;" />
7
7
  <title>projax</title>
8
- <script type="module" crossorigin src="./assets/index-BGodNljq.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-CS-85xbL.css">
8
+ <script type="module" crossorigin src="./assets/index-CYph0WPA.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-CQTleudf.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/dist/index.js CHANGED
@@ -517,6 +517,7 @@ program
517
517
  .option('--tags <tags>', 'Comma-separated list of tags')
518
518
  .action(async (projectPath, options) => {
519
519
  try {
520
+ await ensureAPIServerRunning(true);
520
521
  let finalPath = projectPath;
521
522
  if (!finalPath) {
522
523
  const inquirer = (await Promise.resolve().then(() => __importStar(require('inquirer')))).default;
@@ -654,6 +655,7 @@ program
654
655
  .option('--ports', 'Show detailed port information per script')
655
656
  .action(async (options) => {
656
657
  try {
658
+ await ensureAPIServerRunning(true);
657
659
  const db = (0, core_bridge_1.getDatabaseManager)();
658
660
  const projects = (0, core_bridge_1.getAllProjects)();
659
661
  if (projects.length === 0) {
@@ -762,6 +764,7 @@ program
762
764
  .argument('[project]', 'Project ID or name to scan (leave empty to scan all)')
763
765
  .action(async (projectIdentifier) => {
764
766
  try {
767
+ await ensureAPIServerRunning(true);
765
768
  const db = (0, core_bridge_1.getDatabaseManager)();
766
769
  if (projectIdentifier) {
767
770
  // Find project by ID or name
@@ -860,8 +863,9 @@ program
860
863
  .description('Set or get project description')
861
864
  .argument('<project>', 'Project ID or name')
862
865
  .argument('[description]', 'New description (leave empty to view current)')
863
- .action((projectIdentifier, description) => {
866
+ .action(async (projectIdentifier, description) => {
864
867
  try {
868
+ await ensureAPIServerRunning(true);
865
869
  const db = (0, core_bridge_1.getDatabaseManager)();
866
870
  const projects = (0, core_bridge_1.getAllProjects)();
867
871
  const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
@@ -902,8 +906,9 @@ program
902
906
  .argument('<project>', 'Project ID or name')
903
907
  .argument('[action]', 'Action: add, remove, or list (default: list)', 'list')
904
908
  .argument('[tag]', 'Tag name (required for add/remove)')
905
- .action((projectIdentifier, action = 'list', tag) => {
909
+ .action(async (projectIdentifier, action = 'list', tag) => {
906
910
  try {
911
+ await ensureAPIServerRunning(true);
907
912
  const db = (0, core_bridge_1.getDatabaseManager)();
908
913
  const projects = (0, core_bridge_1.getAllProjects)();
909
914
  const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
@@ -967,6 +972,7 @@ program
967
972
  .argument('<project>', 'Project ID or name')
968
973
  .action(async (projectIdentifier) => {
969
974
  try {
975
+ await ensureAPIServerRunning(true);
970
976
  const projects = (0, core_bridge_1.getAllProjects)();
971
977
  const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
972
978
  if (!project) {
@@ -1068,6 +1074,7 @@ program
1068
1074
  .argument('<project>', 'Project ID or name')
1069
1075
  .action(async (projectIdentifier) => {
1070
1076
  try {
1077
+ await ensureAPIServerRunning(true);
1071
1078
  const projects = (0, core_bridge_1.getAllProjects)();
1072
1079
  const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
1073
1080
  if (!project) {
@@ -1117,6 +1124,7 @@ program
1117
1124
  .option('-f, --force', 'Skip confirmation')
1118
1125
  .action(async (projectIdentifier, options) => {
1119
1126
  try {
1127
+ await ensureAPIServerRunning(true);
1120
1128
  const db = (0, core_bridge_1.getDatabaseManager)();
1121
1129
  const projects = (0, core_bridge_1.getAllProjects)();
1122
1130
  const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
@@ -1154,6 +1162,7 @@ program
1154
1162
  .argument('[project]', 'Project ID or name (leave empty for interactive selection)')
1155
1163
  .action(async (projectIdentifier) => {
1156
1164
  try {
1165
+ await ensureAPIServerRunning(true);
1157
1166
  const projects = (0, core_bridge_1.getAllProjects)();
1158
1167
  if (projects.length === 0) {
1159
1168
  console.error('Error: No projects tracked yet. Use "prx add" to add a project.');
@@ -1218,6 +1227,7 @@ program
1218
1227
  .argument('[project]', 'Project ID or name (leave empty for interactive selection)')
1219
1228
  .action(async (projectIdentifier) => {
1220
1229
  try {
1230
+ await ensureAPIServerRunning(true);
1221
1231
  const projects = (0, core_bridge_1.getAllProjects)();
1222
1232
  if (projects.length === 0) {
1223
1233
  console.error('Error: No projects tracked yet. Use "prx add" to add a project.');
@@ -1807,6 +1817,7 @@ program
1807
1817
  .argument('[project]', 'Project ID or name to scan (leave empty to scan all)')
1808
1818
  .action(async (projectIdentifier) => {
1809
1819
  try {
1820
+ await ensureAPIServerRunning(true);
1810
1821
  const { scanProjectPorts, scanAllProjectPorts } = await Promise.resolve().then(() => __importStar(require('./port-scanner')));
1811
1822
  const db = (0, core_bridge_1.getDatabaseManager)();
1812
1823
  if (projectIdentifier) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projax",
3
- "version": "3.3.28",
3
+ "version": "3.3.29",
4
4
  "description": "Cross-platform project management dashboard for tracking local development projects. Features CLI, Terminal UI, Desktop app, REST API, and built-in tools for test detection, port management, and script execution.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {