CodeBlock Test Page

This page tests CodeBlocks with large amounts of content to verify the shrinking issue is fixed.

Small Code Block

import { Button } from '@vuer-ai/vuer-uikit';

function App() {
  return <Button>Click me</Button>;
}

Large Code Block

import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import {
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
  Input,
  Label,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Textarea,
  Checkbox,
  RadioGroup,
  RadioGroupItem,
  Switch,
  Slider,
  Progress,
  Avatar,
  AvatarFallback,
  AvatarImage,
  Badge,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
  Sheet,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
  Toast,
  ToastAction,
  ToastDescription,
  ToastProvider,
  ToastTitle,
  ToastViewport,
  useToast,
  Toaster,
} from '@vuer-ai/vuer-uikit/src';

interface UserProfile {
  id: string;
  name: string;
  email: string;
  avatar?: string;
  bio?: string;
  preferences: {
    theme: 'light' | 'dark' | 'auto';
    notifications: boolean;
    marketing: boolean;
    analytics: boolean;
  };
  settings: {
    language: string;
    timezone: string;
    dateFormat: string;
    currency: string;
  };
  metadata: {
    createdAt: Date;
    updatedAt: Date;
    lastLoginAt?: Date;
    loginCount: number;
  };
}

interface FormData {
  personalInfo: {
    firstName: string;
    lastName: string;
    email: string;
    phone?: string;
    dateOfBirth?: Date;
  };
  address: {
    street: string;
    city: string;
    state: string;
    zipCode: string;
    country: string;
  };
  preferences: UserProfile['preferences'];
  settings: UserProfile['settings'];
}

interface ComponentProps {
  user: UserProfile;
  onSave: (data: FormData) => Promise<void>;
  onCancel: () => void;
  isLoading?: boolean;
  error?: string | null;
  className?: string;
}

export const ComplexUserProfileForm: React.FC<ComponentProps> = ({
  user,
  onSave,
  onCancel,
  isLoading = false,
  error = null,
  className = '',
}) => {
  // State management for form data
  const [formData, setFormData] = useState<FormData>({
    personalInfo: {
      firstName: user.name.split(' ')[0] || '',
      lastName: user.name.split(' ').slice(1).join(' ') || '',
      email: user.email,
      phone: '',
      dateOfBirth: undefined,
    },
    address: {
      street: '',
      city: '',
      state: '',
      zipCode: '',
      country: 'US',
    },
    preferences: user.preferences,
    settings: user.settings,
  });

  // Form validation state
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [touched, setTouched] = useState<Record<string, boolean>>({});
  const [isSubmitting, setIsSubmitting] = useState(false);

  // Refs for form elements
  const formRef = useRef<HTMLFormElement>(null);
  const firstInputRef = useRef<HTMLInputElement>(null);

  // Toast hook for notifications
  const { toast } = useToast();

  // Memoized validation rules
  const validationRules = useMemo(() => ({
    'personalInfo.firstName': (value: string) =>
      !value ? 'First name is required' :
      value.length < 2 ? 'First name must be at least 2 characters' : null,
    'personalInfo.lastName': (value: string) =>
      !value ? 'Last name is required' :
      value.length < 2 ? 'Last name must be at least 2 characters' : null,
    'personalInfo.email': (value: string) => {
      if (!value) return 'Email is required';
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      return !emailRegex.test(value) ? 'Invalid email format' : null;
    },
    'address.street': (value: string) =>
      !value ? 'Street address is required' : null,
    'address.city': (value: string) =>
      !value ? 'City is required' : null,
    'address.state': (value: string) =>
      !value ? 'State is required' : null,
    'address.zipCode': (value: string) => {
      if (!value) return 'ZIP code is required';
      const zipRegex = /^\d{5}(-\d{4})?$/;
      return !zipRegex.test(value) ? 'Invalid ZIP code format' : null;
    },
  }), []);

  // Validation function
  const validateField = useCallback((fieldPath: string, value: any) => {
    const validator = validationRules[fieldPath as keyof typeof validationRules];
    return validator ? validator(value) : null;
  }, [validationRules]);

  // Handle field changes
  const handleFieldChange = useCallback((fieldPath: string, value: any) => {
    setFormData(prev => {
      const keys = fieldPath.split('.');
      const newData = { ...prev };
      let current: any = newData;

      for (let i = 0; i < keys.length - 1; i++) {
        current[keys[i]] = { ...current[keys[i]] };
        current = current[keys[i]];
      }

      current[keys[keys.length - 1]] = value;
      return newData;
    });

    // Validate field if it's been touched
    if (touched[fieldPath]) {
      const error = validateField(fieldPath, value);
      setErrors(prev => ({
        ...prev,
        [fieldPath]: error,
      }));
    }
  }, [touched, validateField]);

  // Handle field blur (mark as touched and validate)
  const handleFieldBlur = useCallback((fieldPath: string, value: any) => {
    setTouched(prev => ({ ...prev, [fieldPath]: true }));
    const error = validateField(fieldPath, value);
    setErrors(prev => ({
      ...prev,
      [fieldPath]: error,
    }));
  }, [validateField]);

  // Validate entire form
  const validateForm = useCallback(() => {
    const newErrors: Record<string, string> = {};

    Object.keys(validationRules).forEach(fieldPath => {
      const keys = fieldPath.split('.');
      let value = formData as any;
      for (const key of keys) {
        value = value?.[key];
      }

      const error = validateField(fieldPath, value);
      if (error) {
        newErrors[fieldPath] = error;
      }
    });

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  }, [formData, validationRules, validateField]);

  // Handle form submission
  const handleSubmit = useCallback(async (e: React.FormEvent) => {
    e.preventDefault();

    if (!validateForm()) {
      toast({
        title: 'Validation Error',
        description: 'Please fix the errors in the form before submitting.',
        variant: 'destructive',
      });
      return;
    }

    setIsSubmitting(true);

    try {
      await onSave(formData);
      toast({
        title: 'Success',
        description: 'Profile updated successfully!',
        variant: 'default',
      });
    } catch (err) {
      toast({
        title: 'Error',
        description: 'Failed to update profile. Please try again.',
        variant: 'destructive',
      });
    } finally {
      setIsSubmitting(false);
    }
  }, [formData, validateForm, onSave, toast]);

  // Focus first input on mount
  useEffect(() => {
    if (firstInputRef.current) {
      firstInputRef.current.focus();
    }
  }, []);

  // Keyboard shortcuts
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.metaKey || e.ctrlKey) {
        switch (e.key) {
          case 's':
            e.preventDefault();
            if (!isSubmitting && !isLoading) {
              handleSubmit(e as any);
            }
            break;
          case 'Escape':
            e.preventDefault();
            onCancel();
            break;
        }
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [handleSubmit, isSubmitting, isLoading, onCancel]);

  return (
    <ToastProvider>
      <div className={`max-w-4xl mx-auto p-6 space-y-6 ${className}`}>
        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <Avatar className="h-8 w-8">
                <AvatarImage src={user.avatar} alt={user.name} />
                <AvatarFallback>
                  {user.name.split(' ').map(n => n[0]).join('')}
                </AvatarFallback>
              </Avatar>
              Edit Profile
            </CardTitle>
            <CardDescription>
              Update your personal information and preferences
            </CardDescription>
          </CardHeader>

          <form ref={formRef} onSubmit={handleSubmit}>
            <CardContent className="space-y-8">
              {error && (
                <div className="p-4 bg-destructive/10 border border-destructive/20 rounded-md">
                  <p className="text-destructive text-sm">{error}</p>
                </div>
              )}

              {/* Personal Information Section */}
              <div className="space-y-4">
                <h3 className="text-lg font-semibold">Personal Information</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <div className="space-y-2">
                    <Label htmlFor="firstName">First Name *</Label>
                    <Input
                      ref={firstInputRef}
                      id="firstName"
                      value={formData.personalInfo.firstName}
                      onChange={(e) => handleFieldChange('personalInfo.firstName', e.target.value)}
                      onBlur={(e) => handleFieldBlur('personalInfo.firstName', e.target.value)}
                      className={errors['personalInfo.firstName'] ? 'border-destructive' : ''}
                      placeholder="Enter your first name"
                    />
                    {errors['personalInfo.firstName'] && (
                      <p className="text-destructive text-sm">{errors['personalInfo.firstName']}</p>
                    )}
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="lastName">Last Name *</Label>
                    <Input
                      id="lastName"
                      value={formData.personalInfo.lastName}
                      onChange={(e) => handleFieldChange('personalInfo.lastName', e.target.value)}
                      onBlur={(e) => handleFieldBlur('personalInfo.lastName', e.target.value)}
                      className={errors['personalInfo.lastName'] ? 'border-destructive' : ''}
                      placeholder="Enter your last name"
                    />
                    {errors['personalInfo.lastName'] && (
                      <p className="text-destructive text-sm">{errors['personalInfo.lastName']}</p>
                    )}
                  </div>
                </div>
              </div>

              {/* This is a very long code block that should test the shrinking behavior */}
              {/* The component continues with more sections... */}

            </CardContent>

            <CardFooter className="flex justify-between">
              <Button type="button" variant="outline" onClick={onCancel}>
                Cancel
              </Button>
              <Button
                type="submit"
                disabled={isSubmitting || isLoading}
                className="min-w-[120px]"
              >
                {isSubmitting ? 'Saving...' : 'Save Changes'}
              </Button>
            </CardFooter>
          </form>
        </Card>
      </div>
      <Toaster />
    </ToastProvider>
  );
};

export default ComplexUserProfileForm;

Very Long Code Block with Horizontal Scrolling

// This is an extremely long line that should trigger horizontal scrolling: const veryLongVariableName = "This is a very long string that contains a lot of text and should demonstrate horizontal scrolling behavior in code blocks when the content exceeds the available width of the container element";

function processLargeDataset(data, options = {}) {
  const {
    chunkSize = 1000,
    parallel = true,
    timeout = 30000,
    retryAttempts = 3,
    onProgress = () => {},
    onError = () => {},
    transformFunction = (item) => item,
    filterFunction = (item) => true,
    sortFunction = (a, b) => a.id.localeCompare(b.id),
    aggregateFunction = (acc, item) => ({ ...acc, [item.id]: item }),
  } = options;

  return new Promise(async (resolve, reject) => {
    try {
      // Initialize processing state
      const processingState = {
        totalItems: data.length,
        processedItems: 0,
        errors: [],
        results: {},
        startTime: Date.now(),
        chunks: [],
        currentChunkIndex: 0,
      };

      // Split data into chunks for processing
      for (let i = 0; i < data.length; i += chunkSize) {
        processingState.chunks.push(data.slice(i, i + chunkSize));
      }

      // Process chunks sequentially or in parallel based on options
      if (parallel) {
        const chunkPromises = processingState.chunks.map(async (chunk, index) => {
          return await processChunk(chunk, index, processingState, {
            transformFunction,
            filterFunction,
            sortFunction,
            aggregateFunction,
            retryAttempts,
            timeout,
            onProgress,
            onError,
          });
        });

        const chunkResults = await Promise.allSettled(chunkPromises);

        // Aggregate results from all chunks
        chunkResults.forEach((result, index) => {
          if (result.status === 'fulfilled') {
            Object.assign(processingState.results, result.value);
          } else {
            processingState.errors.push({
              chunkIndex: index,
              error: result.reason,
              timestamp: Date.now(),
            });
          }
        });
      } else {
        // Sequential processing
        for (let i = 0; i < processingState.chunks.length; i++) {
          try {
            const chunkResult = await processChunk(
              processingState.chunks[i],
              i,
              processingState,
              {
                transformFunction,
                filterFunction,
                sortFunction,
                aggregateFunction,
                retryAttempts,
                timeout,
                onProgress,
                onError,
              }
            );
            Object.assign(processingState.results, chunkResult);
          } catch (error) {
            processingState.errors.push({
              chunkIndex: i,
              error,
              timestamp: Date.now(),
            });
          }
        }
      }

      // Final processing and cleanup
      const endTime = Date.now();
      const processingTime = endTime - processingState.startTime;

      resolve({
        results: processingState.results,
        errors: processingState.errors,
        statistics: {
          totalItems: processingState.totalItems,
          processedItems: Object.keys(processingState.results).length,
          errorCount: processingState.errors.length,
          processingTime,
          averageTimePerItem: processingTime / processingState.totalItems,
          throughput: processingState.totalItems / (processingTime / 1000),
        },
      });
    } catch (error) {
      reject(error);
    }
  });
}

async function processChunk(chunk, chunkIndex, state, options) {
  const { transformFunction, filterFunction, sortFunction, aggregateFunction, retryAttempts, timeout, onProgress, onError } = options;

  // Another extremely long line for testing horizontal scroll: const anotherVeryLongVariableNameThatShouldTriggerHorizontalScrollingInTheCodeBlockComponentWhenTheContentExceedsTheAvailableWidthOfTheContainer = "This is another very long string for testing purposes";

  let attempts = 0;
  while (attempts < retryAttempts) {
    try {
      const processedChunk = await Promise.race([
        new Promise(async (resolve) => {
          const results = {};

          for (const item of chunk) {
            if (filterFunction(item)) {
              const transformedItem = await transformFunction(item);
              results[item.id] = transformedItem;
              state.processedItems++;

              // Report progress
              const progress = (state.processedItems / state.totalItems) * 100;
              onProgress({
                progress,
                processedItems: state.processedItems,
                totalItems: state.totalItems,
                currentChunk: chunkIndex,
                currentItem: item,
              });
            }
          }

          resolve(results);
        }),
        new Promise((_, reject) => {
          setTimeout(() => reject(new Error('Processing timeout')), timeout);
        }),
      ]);

      return processedChunk;
    } catch (error) {
      attempts++;
      onError({
        error,
        chunkIndex,
        attempt: attempts,
        maxAttempts: retryAttempts,
      });

      if (attempts >= retryAttempts) {
        throw error;
      }

      // Exponential backoff
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempts) * 1000));
    }
  }
}

Test Complete

The CodeBlocks should now display properly without shrinking, even with large amounts of content.