HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/big-agi/src/modules/blocks/code/ButtonStackBlitz.tsx
import * as React from 'react';

import { Tooltip } from '@mui/joy';

import { Brand } from '~/common/app.config';
import { StackBlitzIcon } from '~/common/components/icons/3rdparty/StackBlitzIcon';
import { prettyTimestampForFilenames } from '~/common/util/timeUtils';

import { OverlayButton } from './RenderCode';


const _languages = [
  'typescript',
  'javascript', 'json',
  'html', 'css',
  // 'python',
];

// Mapping of languages to StackBlitz templates
const languageToTemplateMapping: { [language: string]: string } = {
  typescript: 'typescript',
  javascript: 'javascript', json: 'javascript',
  html: 'html', css: 'html',
  // python: 'secret-python', // webcontainers? secret-python? python?
};

// Mapping of languages to their primary file names in StackBlitz
const languageToFileExtensionMapping: { [language: string]: string } = {
  typescript: 'index.ts',
  javascript: 'index.js', json: 'data.json',
  html: 'index.html', css: 'style.css',
  // python: 'main.py',
};


export function isStackBlitzSupported(language: string | null) {
  return !!language && _languages.includes(language);
}

const handleOpenInStackBlitz = (code: string, language: string, title?: string) => {

  const template = languageToTemplateMapping[language] || 'javascript'; // Fallback to 'javascript'
  const fileName = languageToFileExtensionMapping[language] || 'index.js'; // Fallback to 'index.js'

  const projectDetails = {
    files: { [fileName]: code },
    template: template,
    description: `${Brand.Title.Common} file created on ${prettyTimestampForFilenames()}`,
    title: language == 'python' ? 'Python Starter' : title,
  } as const;

  const form = document.createElement('form');
  form.action = 'https://stackblitz.com/run';
  form.method = 'POST';
  form.target = '_blank';

  const addField = (name: string, value: string) => {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = name;
    input.value = value;
    form.appendChild(input);
  };

  Object.keys(projectDetails.files).forEach((filePath) => {
    addField(`project[files][${filePath}]`, projectDetails.files[filePath]);
  });

  addField('project[description]', projectDetails.description);
  addField('project[template]', projectDetails.template);
  !!projectDetails.title && addField('project[title]', projectDetails.title);

  document.body.appendChild(form);
  form.submit();
  document.body.removeChild(form);
};


export function ButtonStackBlitz(props: { code: string, language: string, title?: string }): React.JSX.Element {
  return (
    <Tooltip title='Open in StackBlitz' variant='solid'>
      <OverlayButton variant='outlined' onClick={() => handleOpenInStackBlitz(props.code, props.language, props.title)}>
        <StackBlitzIcon />
      </OverlayButton>
    </Tooltip>
  );
}