UNPKG

@nestjsvn/swagger-sse

Version:

OpenAPI documentation and interactive Swagger UI for NestJS Server-Sent Events endpoints

424 lines (357 loc) 10.3 kB
/* Enhanced SSE Plugin Styles with Theme Support and Performance Optimizations */ /* CSS Custom Properties for Theming */ :root { /* Default theme variables (will be overridden by ThemeManager) */ --sse-primary-color: #007bff; --sse-secondary-color: #6c757d; --sse-success-color: #28a745; --sse-warning-color: #ffc107; --sse-error-color: #dc3545; --sse-info-color: #17a2b8; --sse-background-color: #ffffff; --sse-surface-color: #f8f9fa; --sse-card-color: #ffffff; --sse-border-color: #dee2e6; --sse-divider-color: #e9ecef; --sse-text-primary: #212529; --sse-text-secondary: #6c757d; --sse-text-muted: #868e96; --sse-text-inverse: #ffffff; --sse-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); --sse-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --sse-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); --sse-border-radius: 0.375rem; --sse-border-radius-sm: 0.25rem; --sse-border-radius-lg: 0.5rem; --sse-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --sse-font-size-base: 0.875rem; --sse-font-size-sm: 0.75rem; --sse-font-size-lg: 1rem; --sse-spacing-xs: 0.25rem; --sse-spacing-sm: 0.5rem; --sse-spacing-md: 1rem; --sse-spacing-lg: 1.5rem; --sse-spacing-xl: 2rem; --sse-transition-fast: 0.15s ease-in-out; --sse-transition-normal: 0.3s ease-in-out; --sse-transition-slow: 0.5s ease-in-out; } /* Performance Optimizations */ .sse-interface, .sse-event-list, .sse-connection-status { /* Enable hardware acceleration */ transform: translateZ(0); will-change: transform; /* Optimize repaints */ contain: layout style paint; } /* Reduced motion support */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } /* High contrast support */ @media (prefers-contrast: high) { .sse-interface { border-width: 2px; } .sse-btn { border-width: 2px; } .sse-event-item { border-width: 2px; } } /* Main Interface Styles */ .sse-interface { border: 1px solid var(--sse-border-color); border-radius: var(--sse-border-radius); margin: var(--sse-spacing-md) 0; padding: var(--sse-spacing-lg); background: var(--sse-surface-color); font-family: var(--sse-font-family); font-size: var(--sse-font-size-base); color: var(--sse-text-primary); box-shadow: var(--sse-shadow-sm); transition: box-shadow var(--sse-transition-normal); } .sse-interface:hover { box-shadow: var(--sse-shadow); } /* Controls */ .sse-controls { display: flex; gap: var(--sse-spacing-md); align-items: center; margin-bottom: var(--sse-spacing-lg); flex-wrap: wrap; } /* Button Styles */ .sse-btn { padding: var(--sse-spacing-sm) var(--sse-spacing-md); border: 1px solid transparent; border-radius: var(--sse-border-radius-sm); cursor: pointer; font-size: var(--sse-font-size-base); font-family: inherit; font-weight: 500; line-height: 1.5; text-align: center; text-decoration: none; vertical-align: middle; user-select: none; transition: all var(--sse-transition-fast); display: inline-flex; align-items: center; gap: var(--sse-spacing-xs); } .sse-btn:focus { outline: 2px solid var(--sse-primary-color); outline-offset: 2px; } .sse-btn:disabled { opacity: 0.65; cursor: not-allowed; pointer-events: none; } .sse-btn-primary { background-color: var(--sse-primary-color); border-color: var(--sse-primary-color); color: var(--sse-text-inverse); } .sse-btn-primary:hover:not(:disabled) { background-color: color-mix(in srgb, var(--sse-primary-color) 85%, black); border-color: color-mix(in srgb, var(--sse-primary-color) 85%, black); } .sse-btn-secondary { background-color: var(--sse-secondary-color); border-color: var(--sse-secondary-color); color: var(--sse-text-inverse); } .sse-btn-secondary:hover:not(:disabled) { background-color: color-mix(in srgb, var(--sse-secondary-color) 85%, black); border-color: color-mix(in srgb, var(--sse-secondary-color) 85%, black); } .sse-btn-success { background-color: var(--sse-success-color); border-color: var(--sse-success-color); color: var(--sse-text-inverse); } .sse-btn-danger { background-color: var(--sse-error-color); border-color: var(--sse-error-color); color: var(--sse-text-inverse); } .sse-btn-sm { padding: calc(var(--sse-spacing-xs) * 0.75) var(--sse-spacing-sm); font-size: var(--sse-font-size-sm); } .sse-btn-xs { padding: calc(var(--sse-spacing-xs) * 0.5) calc(var(--sse-spacing-xs) * 0.75); font-size: calc(var(--sse-font-size-sm) * 0.875); } /* Legacy button classes for backward compatibility */ .sse-connect-btn { @extend .sse-btn, .sse-btn-success; } .sse-disconnect-btn { @extend .sse-btn, .sse-btn-danger; } .sse-clear-btn, .sse-export-btn { @extend .sse-btn, .sse-btn-secondary, .sse-btn-sm; } /* Status Indicators */ .sse-status { padding: var(--sse-spacing-xs) var(--sse-spacing-sm); border-radius: var(--sse-border-radius-sm); font-size: var(--sse-font-size-sm); font-weight: 600; text-transform: uppercase; letter-spacing: 0.025em; border: 1px solid transparent; transition: all var(--sse-transition-fast); } .sse-status.connected { background-color: color-mix(in srgb, var(--sse-success-color) 15%, transparent); color: var(--sse-success-color); border-color: color-mix(in srgb, var(--sse-success-color) 30%, transparent); } .sse-status.connecting { background-color: color-mix(in srgb, var(--sse-warning-color) 15%, transparent); color: color-mix(in srgb, var(--sse-warning-color) 80%, black); border-color: color-mix(in srgb, var(--sse-warning-color) 30%, transparent); } .sse-status.disconnected { background-color: color-mix(in srgb, var(--sse-secondary-color) 15%, transparent); color: var(--sse-secondary-color); border-color: color-mix(in srgb, var(--sse-secondary-color) 30%, transparent); } .sse-status.error { background-color: color-mix(in srgb, var(--sse-error-color) 15%, transparent); color: var(--sse-error-color); border-color: color-mix(in srgb, var(--sse-error-color) 30%, transparent); } /* Event Log */ .sse-event-log { margin-top: var(--sse-spacing-lg); } .sse-event-log h4 { margin: 0 0 var(--sse-spacing-md) 0; color: var(--sse-text-primary); font-size: var(--sse-font-size-lg); font-weight: 600; } .sse-events { max-height: 400px; overflow-y: auto; border: 1px solid var(--sse-border-color); border-radius: var(--sse-border-radius); background: var(--sse-card-color); padding: var(--sse-spacing-md); /* Smooth scrolling */ scroll-behavior: smooth; /* Custom scrollbar */ scrollbar-width: thin; scrollbar-color: var(--sse-secondary-color) transparent; } .sse-events::-webkit-scrollbar { width: 8px; } .sse-events::-webkit-scrollbar-track { background: transparent; } .sse-events::-webkit-scrollbar-thumb { background-color: var(--sse-secondary-color); border-radius: var(--sse-border-radius-sm); } .sse-events::-webkit-scrollbar-thumb:hover { background-color: color-mix(in srgb, var(--sse-secondary-color) 80%, black); } /* Event Items */ .sse-event-item { border-bottom: 1px solid var(--sse-divider-color); padding: var(--sse-spacing-sm) 0; font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace; font-size: var(--sse-font-size-sm); transition: background-color var(--sse-transition-fast); /* Performance optimization for large lists */ contain: layout style; } .sse-event-item:last-child { border-bottom: none; } .sse-event-item:hover { background-color: color-mix(in srgb, var(--sse-primary-color) 5%, transparent); } .sse-event-item.selected { background-color: color-mix(in srgb, var(--sse-primary-color) 10%, transparent); border-left: 3px solid var(--sse-primary-color); padding-left: calc(var(--sse-spacing-sm) - 3px); } .sse-event-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--sse-spacing-xs); flex-wrap: wrap; gap: var(--sse-spacing-xs); } .sse-event-type { font-weight: 600; color: var(--sse-primary-color); text-transform: uppercase; font-size: calc(var(--sse-font-size-sm) * 0.875); letter-spacing: 0.025em; } .sse-event-timestamp { color: var(--sse-text-muted); font-size: calc(var(--sse-font-size-sm) * 0.875); font-variant-numeric: tabular-nums; } .sse-event-data { background-color: var(--sse-surface-color); padding: var(--sse-spacing-sm); border-radius: var(--sse-border-radius-sm); white-space: pre-wrap; word-break: break-word; overflow-wrap: break-word; border: 1px solid var(--sse-border-color); font-size: calc(var(--sse-font-size-sm) * 0.9); line-height: 1.4; } /* Log Controls */ .sse-log-controls { margin-top: var(--sse-spacing-md); display: flex; gap: var(--sse-spacing-sm); flex-wrap: wrap; } /* Icons */ .sse-icon { width: 1em; height: 1em; fill: currentColor; display: inline-block; vertical-align: middle; } /* Loading States */ .sse-loading { display: inline-block; width: 1em; height: 1em; border: 2px solid var(--sse-border-color); border-radius: 50%; border-top-color: var(--sse-primary-color); animation: sse-spin 1s linear infinite; } @keyframes sse-spin { to { transform: rotate(360deg); } } /* Responsive Design */ @media (max-width: 768px) { .sse-interface { padding: var(--sse-spacing-md); margin: var(--sse-spacing-sm) 0; } .sse-controls { flex-direction: column; align-items: stretch; } .sse-btn { justify-content: center; } .sse-events { max-height: 250px; } .sse-event-header { flex-direction: column; align-items: flex-start; } } /* Focus Management for Keyboard Navigation */ .sse-keyboard-navigation .sse-btn:focus, .sse-keyboard-navigation .sse-event-item:focus { outline: 2px solid var(--sse-primary-color); outline-offset: 2px; } /* Print Styles */ @media print { .sse-interface { box-shadow: none; border: 1px solid #000; } .sse-controls { display: none; } .sse-events { max-height: none; overflow: visible; } }