@illuma-ai/code-sandbox 1.2.1 → 1.2.2

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
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:Menlo,Monaco,Consolas,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.right-4{right:1rem}.top-0{top:0}.top-4{top:1rem}.z-0{z-index:0}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.-mb-\[1px\]{margin-bottom:-1px}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-0\.5{margin-left:.125rem}.ml-1{margin-left:.25rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0\.5{height:.125rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-48{height:12rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0px}.min-h-\[36px\]{min-height:36px}.min-h-\[calc\(100vh-56px\)\]{min-height:calc(100vh - 56px)}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-\[120px\]{max-width:120px}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-bounce{animation:bounce 1s infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overscroll-contain{overscroll-behavior:contain}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-2{border-top-width:2px}.border-none{border-style:none}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.border-sb-accent{border-color:var(--sb-accent, #007acc)}.border-sb-border{border-color:var(--sb-border, #3c3c3c)}.border-t-sb-accent{border-top-color:var(--sb-accent, #007acc)}.border-t-transparent{border-top-color:transparent}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-700{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-sb-accent{background-color:var(--sb-accent, #007acc)}.bg-sb-bg{background-color:var(--sb-bg, #1e1e1e)}.bg-sb-bg-active{background-color:var(--sb-bg-active, #37373d)}.bg-sb-bg-alt{background-color:var(--sb-bg-alt, #252526)}.bg-sb-editor{background-color:var(--sb-editor, #1e1e1e)}.bg-sb-sidebar{background-color:var(--sb-sidebar, #252526)}.bg-sb-success{background-color:var(--sb-success, #4ec9b0)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-blue-500{--tw-gradient-from: #3b82f6 var(--tw-gradient-from-position);--tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-purple-500{--tw-gradient-to: #a855f7 var(--tw-gradient-to-position)}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-\[3px\]{padding-top:3px;padding-bottom:3px}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:Menlo,Monaco,Consolas,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-sb-text{color:var(--sb-text, #cccccc)}.text-sb-text-active{color:var(--sb-text-active, #ffffff)}.text-sb-text-muted{color:var(--sb-text-muted, #858585)}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--sb-bg: #1e1e1e;--sb-bg-alt: #252526;--sb-bg-hover: #2a2d2e;--sb-bg-active: #37373d;--sb-sidebar: #252526;--sb-editor: #1e1e1e;--sb-terminal: #0d1117;--sb-terminal-header: #161b22;--sb-preview: #ffffff;--sb-border: #3c3c3c;--sb-text: #cccccc;--sb-text-muted: #858585;--sb-text-active: #ffffff;--sb-accent: #007acc;--sb-accent-hover: #1a8ad4;--sb-success: #3fb950;--sb-warning: #d29922;--sb-error: #f85149;--sb-info: #58a6ff;--sb-cyan: #56d4dd;--sb-magenta: #bc8cff;--sb-yellow: #e3b341;--sb-scrollbar-thumb: rgba(255, 255, 255, .12);--sb-scrollbar-thumb-hover: rgba(255, 255, 255, .25);--sb-scrollbar-track: transparent;--sb-scrollbar-width: 6px}.sb-root ::-webkit-scrollbar{width:var(--sb-scrollbar-width);height:var(--sb-scrollbar-width)}.sb-root ::-webkit-scrollbar-track{background:var(--sb-scrollbar-track)}.sb-root ::-webkit-scrollbar-thumb{background:var(--sb-scrollbar-thumb);border-radius:999px}.sb-root ::-webkit-scrollbar-thumb:hover{background:var(--sb-scrollbar-thumb-hover)}.sb-root ::-webkit-scrollbar-corner{background:transparent}.sb-root *{scrollbar-width:thin;scrollbar-color:var(--sb-scrollbar-thumb) var(--sb-scrollbar-track)}.sb-terminal-output{font-family:Cascadia Code,JetBrains Mono,Fira Code,Consolas,Monaco,Courier New,monospace;font-size:12.5px;line-height:1.6;letter-spacing:.01em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sb-term-line{color:#c9d1d9}.sb-term-prompt{color:var(--sb-success);font-weight:600}.sb-term-cmd{color:#f0f6fc;font-weight:500}.sb-term-stderr{color:var(--sb-error)}.sb-term-success{color:var(--sb-success)}.sb-term-warning{color:var(--sb-warning)}.sb-term-info{color:var(--sb-info)}.sb-term-dim{color:#484f58}.sb-term-path{color:var(--sb-cyan)}.sb-term-pkg{color:var(--sb-magenta)}.sb-term-exit-ok{color:var(--sb-success)}.sb-term-exit-fail{color:var(--sb-error);font-weight:600}:root{--text-primary: #1a1a1a;--text-secondary: #565869;--text-tertiary: #8e8ea0;--surface-primary: #ffffff;--surface-secondary: #f9fafb;--surface-tertiary: #f3f4f6;--border-light: #e5e7eb;--border-medium: #d1d5db;--border-heavy: #9ca3af;--background: 0 0% 100%;--foreground: 0 0% 3.9%;--card: 0 0% 100%;--card-foreground: 0 0% 3.9%;--primary: 0 0% 9%;--primary-foreground: 0 0% 98%;--secondary: 0 0% 96.1%;--secondary-foreground: 0 0% 9%;--muted: 0 0% 96.1%;--muted-foreground: 0 0% 45.1%;--accent: 0 0% 96.1%;--accent-foreground: 0 0% 9%;--destructive: 0 84.2% 60.2%;--destructive-foreground: 0 0% 98%;--border: 0 0% 89.8%;--input: 0 0% 89.8%;--ring: 0 0% 3.9%;--radius: .5rem;--chart-1: 12 76% 61%;--chart-2: 173 58% 39%;--chart-3: 197 37% 24%;--chart-4: 43 74% 66%;--chart-5: 27 87% 67%}.dark{--text-primary: #f3f4f6;--text-secondary: #d1d5db;--text-tertiary: #6b7280;--surface-primary: #111827;--surface-secondary: #1f2937;--surface-tertiary: #374151;--border-light: #3a3a3b;--border-medium: #4b5563;--border-heavy: #6b7280;--background: 0 0% 7%;--foreground: 0 0% 98%;--card: 0 0% 3.9%;--card-foreground: 0 0% 98%;--primary: 0 0% 98%;--primary-foreground: 0 0% 9%;--secondary: 0 0% 14.9%;--secondary-foreground: 0 0% 98%;--muted: 0 0% 14.9%;--muted-foreground: 0 0% 63.9%;--accent: 0 0% 14.9%;--accent-foreground: 0 0% 98%;--destructive: 0 62.8% 40.6%;--destructive-foreground: 0 0% 98%;--border: 0 0% 14.9%;--input: 0 0% 14.9%;--ring: 0 0% 83.1%;--chart-1: 220 70% 50%;--chart-2: 160 60% 45%;--chart-3: 30 80% 55%;--chart-4: 280 65% 60%;--chart-5: 340 75% 55%}.hover\:bg-amber-600:hover{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-600:hover{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.hover\:bg-sb-bg-hover:hover{background-color:var(--sb-bg-hover, #2a2d2e)}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-sb-text:hover{color:var(--sb-text, #cccccc)}.hover\:text-sb-text-active:hover{color:var(--sb-text-active, #ffffff)}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}@media(min-width:640px){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-5xl{font-size:3rem;line-height:1}}@media(min-width:1024px){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}:root{--separator-border: rgba(128, 128, 128, .35);--sash-hover-transition-duration: .1s}.allotment-module_splitView__L-yRc{height:100%;overflow:hidden;position:relative;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF{height:100%;pointer-events:none;position:absolute;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF>.allotment-module_sash__QA-2t{pointer-events:auto}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa{height:100%;position:relative;white-space:nowrap;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{overflow:hidden;position:absolute;white-space:initial}.allotment-module_splitView__L-yRc.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{width:100%}.allotment-module_splitView__L-yRc.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{height:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{background-color:var(--separator-border);content:" ";left:0;pointer-events:none;position:absolute;top:0;z-index:5}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:1px;width:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:100%;width:1px}:root{--focus-border: #007fd4;--sash-size: 8px;--sash-hover-size: 4px}.sash-module_sash__K-9lB{position:absolute;z-index:35;touch-action:none;pointer-events:auto;text-align:initial}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{pointer-events:none}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_vertical__pB-rs{cursor:col-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_minimum__-UKxp{cursor:e-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_maximum__TCWxD{cursor:w-resize}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_horizontal__kFbiw{cursor:row-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_minimum__-UKxp{cursor:s-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_maximum__TCWxD{cursor:n-resize}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{cursor:default!important;pointer-events:none!important}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs{cursor:ew-resize;top:0;width:var(--sash-size);height:100%}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw{cursor:ns-resize;left:0;width:100%;height:var(--sash-size)}.sash-module_sash__K-9lB:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-{content:" ";height:calc(var(--sash-size) * 2);width:calc(var(--sash-size) * 2);z-index:100;display:block;cursor:all-scroll;position:absolute}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{cursor:nwse-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{cursor:nesw-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{left:calc(var(--sash-size) * -.5);top:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{left:calc(var(--sash-size) * -.5);bottom:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{top:calc(var(--sash-size) * -.5);left:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{top:calc(var(--sash-size) * -.5);right:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB:before{content:"";pointer-events:none;position:absolute;width:100%;height:100%;transition:background-color var(--sash-hover-transition-duration) ease-out;background:transparent}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs:before{width:var(--sash-hover-size);left:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw:before{height:var(--sash-hover-size);top:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_hover__80W6I:before,.sash-module_sash__K-9lB.sash-module_active__bJspD:before{background:var(--focus-border)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illuma-ai/code-sandbox",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Illuma AI (https://github.com/illuma-ai)",
@@ -231,7 +231,7 @@ export function FileTree({
231
231
  fileChanges,
232
232
  }: FileTreeProps) {
233
233
  return (
234
- <div className="h-full overflow-auto bg-sb-sidebar text-sm select-none">
234
+ <div className="h-full overflow-auto bg-sb-sidebar text-sm select-none overscroll-contain">
235
235
  <div className="px-3 py-2 text-[11px] font-semibold text-sb-text-muted uppercase tracking-wider border-b border-sb-border">
236
236
  Explorer
237
237
  </div>
@@ -1,19 +1,189 @@
1
1
  /**
2
- * Terminal — Display terminal output from Nodepod processes.
2
+ * Terminal — Git-bash inspired terminal output panel.
3
3
  *
4
- * Simple scrolling output panel styled like a terminal.
5
- * Auto-scrolls to the bottom as new output arrives.
4
+ * Renders process stdout/stderr with color-coded output:
5
+ * - Commands ($ ...) get a green prompt + white command
6
+ * - stderr lines get red text
7
+ * - Success markers (checkmarks) get green
8
+ * - Warnings get yellow
9
+ * - Package names get purple
10
+ * - URLs and paths get cyan
11
+ * - Exit codes get colored by status
12
+ *
13
+ * Uses a simple div-based approach (not xterm.js) to keep the bundle lean.
14
+ * Auto-scrolls to bottom as new output arrives.
6
15
  */
7
16
 
8
17
  import React, { useEffect, useRef } from "react";
9
18
  import type { TerminalProps } from "../types";
10
19
 
20
+ /** Classify a terminal output line for color coding */
21
+ type LineType =
22
+ | "prompt" // $ command
23
+ | "stderr" // [stderr] ...
24
+ | "success" // ✓ ...
25
+ | "error" // ✗ ... or error messages
26
+ | "warning" // warn / Warning
27
+ | "info" // Installing, Dependencies, info lines
28
+ | "exit-ok" // Process exited with code 0
29
+ | "exit-fail" // Process exited with non-zero code
30
+ | "dim" // Empty or separator lines
31
+ | "normal"; // Default output
32
+
11
33
  /**
12
- * Terminal component renders process stdout/stderr in a terminal-style panel.
34
+ * Classify a line of terminal output for styling.
13
35
  *
14
- * Uses a simple div-based approach (not xterm.js) for the initial version.
15
- * This keeps the bundle small and avoids the xterm peer dependency
16
- * for consumers who don't need full terminal emulation.
36
+ * Pattern matching order matters more specific patterns first.
37
+ */
38
+ function classifyLine(line: string): LineType {
39
+ const trimmed = line.trim();
40
+
41
+ // Empty or whitespace-only
42
+ if (!trimmed) return "dim";
43
+
44
+ // Explicit stderr prefix from runtime
45
+ if (trimmed.startsWith("[stderr]")) return "stderr";
46
+
47
+ // Command prompt ($ node server.js)
48
+ if (/^\$\s/.test(trimmed)) return "prompt";
49
+
50
+ // Success indicators
51
+ if (/^\s*✓/.test(line) || /^\s*✔/.test(line) || /^done$/i.test(trimmed))
52
+ return "success";
53
+
54
+ // Error indicators
55
+ if (
56
+ /^\s*✗/.test(line) ||
57
+ /^\s*✘/.test(line) ||
58
+ /^error\b/i.test(trimmed) ||
59
+ /^Error:/i.test(trimmed) ||
60
+ /^TypeError:/i.test(trimmed) ||
61
+ /^ReferenceError:/i.test(trimmed) ||
62
+ /^SyntaxError:/i.test(trimmed) ||
63
+ /ENOENT|EACCES|ECONNREFUSED/i.test(trimmed)
64
+ )
65
+ return "error";
66
+
67
+ // Process exit
68
+ if (/^Process exited with code\s+(\d+)/.test(trimmed)) {
69
+ const code = trimmed.match(/code\s+(\d+)/)?.[1];
70
+ return code === "0" ? "exit-ok" : "exit-fail";
71
+ }
72
+
73
+ // Warning
74
+ if (
75
+ /^warn\b/i.test(trimmed) ||
76
+ /^warning\b/i.test(trimmed) ||
77
+ /^Warning:/i.test(trimmed) ||
78
+ /deprecated/i.test(trimmed)
79
+ )
80
+ return "warning";
81
+
82
+ // Info / install progress
83
+ if (
84
+ /^Installing\b/i.test(trimmed) ||
85
+ /^Dependencies\s+installed/i.test(trimmed) ||
86
+ /^Listening\b/i.test(trimmed) ||
87
+ /^Server\s+(running|started|listening)/i.test(trimmed) ||
88
+ /^Starting\b/i.test(trimmed)
89
+ )
90
+ return "info";
91
+
92
+ return "normal";
93
+ }
94
+
95
+ /** CSS class name for each line type */
96
+ const LINE_CLASS: Record<LineType, string> = {
97
+ prompt: "", // handled specially (split into prompt + command)
98
+ stderr: "sb-term-stderr",
99
+ success: "sb-term-success",
100
+ error: "sb-term-stderr",
101
+ warning: "sb-term-warning",
102
+ info: "sb-term-info",
103
+ "exit-ok": "sb-term-exit-ok",
104
+ "exit-fail": "sb-term-exit-fail",
105
+ dim: "sb-term-dim",
106
+ normal: "sb-term-line",
107
+ };
108
+
109
+ /**
110
+ * Render a single terminal line with appropriate styling.
111
+ *
112
+ * Prompt lines are split into a green "$ " prefix and white command text.
113
+ * Stderr lines strip the "[stderr]" prefix and show in red.
114
+ * Package install lines highlight the package name in purple.
115
+ */
116
+ function TerminalLine({ line }: { line: string }) {
117
+ const type = classifyLine(line);
118
+
119
+ // Prompt line: split into green prompt + white command
120
+ if (type === "prompt") {
121
+ const commandText = line.replace(/^\$\s*/, "");
122
+ return (
123
+ <div className="whitespace-pre-wrap">
124
+ <span className="sb-term-prompt">{"$ "}</span>
125
+ <span className="sb-term-cmd">{commandText}</span>
126
+ </div>
127
+ );
128
+ }
129
+
130
+ // Stderr: strip prefix, show in red
131
+ if (type === "stderr") {
132
+ const message = line.replace(/^\[stderr\]\s*/, "");
133
+ return (
134
+ <div className="whitespace-pre-wrap sb-term-stderr">
135
+ <span className="sb-term-dim select-none">{"stderr "}</span>
136
+ {message}
137
+ </div>
138
+ );
139
+ }
140
+
141
+ // Package install success: " ✓ express@4.18.0" → green check + purple pkg
142
+ if (type === "success" && /✓\s+\S+@/.test(line)) {
143
+ const match = line.match(/(.*✓\s*)(\S+@\S+)(.*)/);
144
+ if (match) {
145
+ return (
146
+ <div className="whitespace-pre-wrap sb-term-success">
147
+ {match[1]}
148
+ <span className="sb-term-pkg">{match[2]}</span>
149
+ {match[3]}
150
+ </div>
151
+ );
152
+ }
153
+ }
154
+
155
+ // Info lines with port numbers: highlight the port
156
+ if (type === "info" && /:\d{4}/.test(line)) {
157
+ const parts = line.split(/(:\d{4,5})/);
158
+ return (
159
+ <div className="whitespace-pre-wrap sb-term-info">
160
+ {parts.map((part, i) =>
161
+ /^:\d{4,5}$/.test(part) ? (
162
+ <span key={i} className="sb-term-path">
163
+ {part}
164
+ </span>
165
+ ) : (
166
+ <span key={i}>{part}</span>
167
+ ),
168
+ )}
169
+ </div>
170
+ );
171
+ }
172
+
173
+ return (
174
+ <div className={`whitespace-pre-wrap ${LINE_CLASS[type]}`}>{line}</div>
175
+ );
176
+ }
177
+
178
+ /**
179
+ * Terminal component — renders process output in a git-bash inspired panel.
180
+ *
181
+ * Features:
182
+ * - Color-coded output (commands, errors, warnings, info, packages)
183
+ * - Monospace font stack (Cascadia Code → JetBrains Mono → Fira Code → fallback)
184
+ * - Auto-scroll to bottom on new output
185
+ * - Modern thin scrollbar matching the sandbox theme
186
+ * - Dark background separate from editor for visual distinction
17
187
  */
18
188
  export function Terminal({ output, className = "" }: TerminalProps) {
19
189
  const containerRef = useRef<HTMLDivElement>(null);
@@ -27,40 +197,54 @@ export function Terminal({ output, className = "" }: TerminalProps) {
27
197
  }, [output.length]);
28
198
 
29
199
  return (
30
- <div className={`flex flex-col h-full bg-sb-terminal ${className}`}>
31
- {/* Header */}
32
- <div className="flex items-center px-3 py-1 bg-sb-bg-alt border-b border-sb-border">
33
- <span className="text-xs font-medium text-sb-text-muted uppercase tracking-wider">
34
- Terminal
200
+ <div
201
+ className={`flex flex-col h-full ${className}`}
202
+ style={{ background: "var(--sb-terminal)" }}
203
+ >
204
+ {/* Header — styled like a real terminal tab bar */}
205
+ <div
206
+ className="flex items-center gap-2 px-3 py-1.5 border-b border-sb-border shrink-0"
207
+ style={{ background: "var(--sb-terminal-header)" }}
208
+ >
209
+ {/* Traffic light dots (decorative) */}
210
+ <div className="flex items-center gap-1.5 mr-1">
211
+ <span
212
+ className="w-2.5 h-2.5 rounded-full"
213
+ style={{ background: "#f85149" }}
214
+ />
215
+ <span
216
+ className="w-2.5 h-2.5 rounded-full"
217
+ style={{ background: "#d29922" }}
218
+ />
219
+ <span
220
+ className="w-2.5 h-2.5 rounded-full"
221
+ style={{ background: "#3fb950" }}
222
+ />
223
+ </div>
224
+ <span
225
+ className="text-[11px] font-medium tracking-wider"
226
+ style={{ color: "var(--sb-text-muted)" }}
227
+ >
228
+ TERMINAL
229
+ </span>
230
+ {/* Shell indicator */}
231
+ <span className="text-[10px] ml-auto" style={{ color: "#484f58" }}>
232
+ bash
35
233
  </span>
36
234
  </div>
37
235
 
38
- {/* Output */}
236
+ {/* Output area */}
39
237
  <div
40
238
  ref={containerRef}
41
- className="flex-1 overflow-auto p-3 font-mono text-xs leading-relaxed"
239
+ className="flex-1 overflow-auto px-3.5 py-2.5 sb-terminal-output overscroll-contain"
42
240
  >
43
241
  {output.length === 0 ? (
44
- <span className="text-sb-text-muted">Waiting for output...</span>
242
+ <div className="flex items-center gap-2 sb-term-dim">
243
+ <span className="sb-term-prompt">$</span>
244
+ <span className="animate-pulse">_</span>
245
+ </div>
45
246
  ) : (
46
- output.map((line, i) => (
47
- <div
48
- key={i}
49
- className={`whitespace-pre-wrap ${
50
- line.startsWith("[stderr]")
51
- ? "text-sb-error"
52
- : line.startsWith("$")
53
- ? "text-sb-success"
54
- : line.startsWith(" ✓")
55
- ? "text-sb-success"
56
- : line.startsWith(" ✗")
57
- ? "text-sb-error"
58
- : "text-sb-text"
59
- }`}
60
- >
61
- {line}
62
- </div>
63
- ))
247
+ output.map((line, i) => <TerminalLine key={i} line={line} />)
64
248
  )}
65
249
  </div>
66
250
  </div>
package/src/index.ts CHANGED
@@ -5,6 +5,10 @@
5
5
  * Consumers import from here.
6
6
  */
7
7
 
8
+ // Styles — imported here so Vite extracts them into the library CSS bundle.
9
+ // Consumers must import: import "@illuma-ai/code-sandbox/styles.css";
10
+ import "./styles.css";
11
+
8
12
  // Main component
9
13
  export { CodeSandbox } from "./components/Workbench";
10
14
 
package/src/styles.css CHANGED
@@ -10,7 +10,8 @@
10
10
  --sb-bg-active: #37373d;
11
11
  --sb-sidebar: #252526;
12
12
  --sb-editor: #1e1e1e;
13
- --sb-terminal: #1e1e1e;
13
+ --sb-terminal: #0d1117;
14
+ --sb-terminal-header: #161b22;
14
15
  --sb-preview: #ffffff;
15
16
  --sb-border: #3c3c3c;
16
17
  --sb-text: #cccccc;
@@ -18,9 +19,107 @@
18
19
  --sb-text-active: #ffffff;
19
20
  --sb-accent: #007acc;
20
21
  --sb-accent-hover: #1a8ad4;
21
- --sb-success: #4ec9b0;
22
- --sb-warning: #cca700;
23
- --sb-error: #f44747;
22
+ --sb-success: #3fb950;
23
+ --sb-warning: #d29922;
24
+ --sb-error: #f85149;
25
+ --sb-info: #58a6ff;
26
+ --sb-cyan: #56d4dd;
27
+ --sb-magenta: #bc8cff;
28
+ --sb-yellow: #e3b341;
29
+ --sb-scrollbar-thumb: rgba(255, 255, 255, 0.12);
30
+ --sb-scrollbar-thumb-hover: rgba(255, 255, 255, 0.25);
31
+ --sb-scrollbar-track: transparent;
32
+ --sb-scrollbar-width: 6px;
33
+ }
34
+
35
+ /* ---------------------------------------------------------------------------
36
+ * Modern thin scrollbars — applies to ALL scrollable elements in sandbox
37
+ * Auto-hides via opacity transition. Themed with CSS vars.
38
+ * --------------------------------------------------------------------------- */
39
+
40
+ /* Webkit (Chrome, Safari, Edge) */
41
+ .sb-root ::-webkit-scrollbar {
42
+ width: var(--sb-scrollbar-width);
43
+ height: var(--sb-scrollbar-width);
44
+ }
45
+
46
+ .sb-root ::-webkit-scrollbar-track {
47
+ background: var(--sb-scrollbar-track);
48
+ }
49
+
50
+ .sb-root ::-webkit-scrollbar-thumb {
51
+ background: var(--sb-scrollbar-thumb);
52
+ border-radius: 999px;
53
+ }
54
+
55
+ .sb-root ::-webkit-scrollbar-thumb:hover {
56
+ background: var(--sb-scrollbar-thumb-hover);
57
+ }
58
+
59
+ .sb-root ::-webkit-scrollbar-corner {
60
+ background: transparent;
61
+ }
62
+
63
+ /* Firefox */
64
+ .sb-root * {
65
+ scrollbar-width: thin;
66
+ scrollbar-color: var(--sb-scrollbar-thumb) var(--sb-scrollbar-track);
67
+ }
68
+
69
+ /* ---------------------------------------------------------------------------
70
+ * Terminal theme — git-bash inspired colors and styling
71
+ * --------------------------------------------------------------------------- */
72
+
73
+ .sb-terminal-output {
74
+ font-family:
75
+ "Cascadia Code", "JetBrains Mono", "Fira Code", "Consolas", "Monaco",
76
+ "Courier New", monospace;
77
+ font-size: 12.5px;
78
+ line-height: 1.6;
79
+ letter-spacing: 0.01em;
80
+ -webkit-font-smoothing: antialiased;
81
+ -moz-osx-font-smoothing: grayscale;
82
+ }
83
+
84
+ /* Terminal line colors via data attribute */
85
+ .sb-term-line {
86
+ color: #c9d1d9;
87
+ }
88
+ .sb-term-prompt {
89
+ color: var(--sb-success);
90
+ font-weight: 600;
91
+ }
92
+ .sb-term-cmd {
93
+ color: #f0f6fc;
94
+ font-weight: 500;
95
+ }
96
+ .sb-term-stderr {
97
+ color: var(--sb-error);
98
+ }
99
+ .sb-term-success {
100
+ color: var(--sb-success);
101
+ }
102
+ .sb-term-warning {
103
+ color: var(--sb-warning);
104
+ }
105
+ .sb-term-info {
106
+ color: var(--sb-info);
107
+ }
108
+ .sb-term-dim {
109
+ color: #484f58;
110
+ }
111
+ .sb-term-path {
112
+ color: var(--sb-cyan);
113
+ }
114
+ .sb-term-pkg {
115
+ color: var(--sb-magenta);
116
+ }
117
+ .sb-term-exit-ok {
118
+ color: var(--sb-success);
119
+ }
120
+ .sb-term-exit-fail {
121
+ color: var(--sb-error);
122
+ font-weight: 600;
24
123
  }
25
124
 
26
125
  /*
@@ -1 +0,0 @@
1
- :root{--separator-border: rgba(128, 128, 128, .35);--sash-hover-transition-duration: .1s}.allotment-module_splitView__L-yRc{height:100%;overflow:hidden;position:relative;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF{height:100%;pointer-events:none;position:absolute;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF>.allotment-module_sash__QA-2t{pointer-events:auto}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa{height:100%;position:relative;white-space:nowrap;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{overflow:hidden;position:absolute;white-space:initial}.allotment-module_splitView__L-yRc.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{width:100%}.allotment-module_splitView__L-yRc.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{height:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{background-color:var(--separator-border);content:" ";left:0;pointer-events:none;position:absolute;top:0;z-index:5}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:1px;width:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:100%;width:1px}:root{--focus-border: #007fd4;--sash-size: 8px;--sash-hover-size: 4px}.sash-module_sash__K-9lB{position:absolute;z-index:35;touch-action:none;pointer-events:auto;text-align:initial}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{pointer-events:none}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_vertical__pB-rs{cursor:col-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_minimum__-UKxp{cursor:e-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_maximum__TCWxD{cursor:w-resize}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_horizontal__kFbiw{cursor:row-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_minimum__-UKxp{cursor:s-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_maximum__TCWxD{cursor:n-resize}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{cursor:default!important;pointer-events:none!important}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs{cursor:ew-resize;top:0;width:var(--sash-size);height:100%}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw{cursor:ns-resize;left:0;width:100%;height:var(--sash-size)}.sash-module_sash__K-9lB:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-{content:" ";height:calc(var(--sash-size) * 2);width:calc(var(--sash-size) * 2);z-index:100;display:block;cursor:all-scroll;position:absolute}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{cursor:nwse-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{cursor:nesw-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{left:calc(var(--sash-size) * -.5);top:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{left:calc(var(--sash-size) * -.5);bottom:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{top:calc(var(--sash-size) * -.5);left:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{top:calc(var(--sash-size) * -.5);right:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB:before{content:"";pointer-events:none;position:absolute;width:100%;height:100%;transition:background-color var(--sash-hover-transition-duration) ease-out;background:transparent}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs:before{width:var(--sash-hover-size);left:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw:before{height:var(--sash-hover-size);top:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_hover__80W6I:before,.sash-module_sash__K-9lB.sash-module_active__bJspD:before{background:var(--focus-border)}