A web app to help you design things, local, offline, on device. In your browser.

TypeScript 53.1% JSON 45.6% CSS 0.9% Markdown 0.3% JavaScript 0.1%
index.ts 325 lines (7 KB)
// Core Types for VIT Design App

export type LayerType = 'device' | 'screenshot' | 'text' | 'shape' | 'image' | 'effect';

export interface Position {
  x: number;
  y: number;
}

export interface Size {
  width: number;
  height: number;
}

export interface Layer {
  id: string;
  type: LayerType;
  name: string;
  visible: boolean;
  locked: boolean;
  opacity: number;
  position: Position;
  size: Size;
  rotation: number;
  data: LayerData;
}

export type LayerData =
  | DeviceLayerData
  | ScreenshotLayerData
  | TextLayerData
  | ShapeLayerData
  | ImageLayerData
  | EffectLayerData;

export interface DeviceLayerData {
  type: 'device';
  deviceId: DeviceType;
  color: DeviceColor;
  showFrame: boolean;
  screenshotId?: string;
}

export interface ScreenshotLayerData {
  type: 'screenshot';
  src: string;
  fit: 'cover' | 'contain' | 'fill';
}

export interface TextLayerData {
  type: 'text';
  text: string;
  fontFamily: string;
  fontSize: number;
  fontWeight: number;
  color: string;
  align: 'left' | 'center' | 'right';
  lineHeight: number;
  letterSpacing: number;
  shadow?: TextShadow;
  gradient?: GradientConfig;
}

export interface TextShadow {
  color: string;
  blur: number;
  offsetX: number;
  offsetY: number;
}

export interface ShapeLayerData {
  type: 'shape';
  shapeType: 'rectangle' | 'circle' | 'ellipse' | 'polygon' | 'star' | 'arrow';
  fill: string | GradientConfig;
  stroke: string;
  strokeWidth: number;
  cornerRadius?: number;
  points?: number;
}

export interface CornerRadius {
  topLeft: number;
  topRight: number;
  bottomLeft: number;
  bottomRight: number;
}

export interface ImageLayerData {
  type: 'image';
  src: string;
  filters?: ImageFilters;
  cornerRadius?: number | CornerRadius;
  fit?: 'cover' | 'contain' | 'fill';
}

export interface EffectLayerData {
  type: 'effect';
  effectType: 'glass' | 'blur' | 'glow' | 'shadow';
  config: GlassEffectConfig | BlurEffectConfig | GlowEffectConfig | ShadowEffectConfig;
}

export interface GlassEffectConfig {
  blur: number;
  opacity: number;
  saturation: number;
  borderRadius: number;
  borderColor: string;
  borderWidth: number;
}

export interface BlurEffectConfig {
  blur: number;
  shape: 'rectangle' | 'circle';
}

export interface GlowEffectConfig {
  color: string;
  blur: number;
  spread: number;
}

export interface ShadowEffectConfig {
  color: string;
  blur: number;
  offsetX: number;
  offsetY: number;
}

export interface ImageFilters {
  brightness: number;
  contrast: number;
  saturation: number;
  blur: number;
}

export interface GradientConfig {
  type: 'linear' | 'radial';
  angle?: number;
  stops: GradientStop[];
}

export interface GradientStop {
  offset: number;
  color: string;
}

// Device Types
export type DeviceType =
  | 'iphone-17-pro-max'
  | 'iphone-16-pro-max'
  | 'iphone-16-pro'
  | 'iphone-16'
  | 'iphone-15-pro'
  | 'iphone-15'
  | 'iphone-se'
  | 'ipad-pro-13'
  | 'ipad-air-11'
  | 'ipad-mini'
  | 'macbook-pro-16'
  | 'macbook-air-15'
  | 'pixel-9-pro'
  | 'galaxy-s24-ultra'
  | 'apple-watch-ultra'
  | 'apple-watch-series-10';

export type DeviceColor = 'black' | 'white' | 'silver' | 'gold' | 'blue' | 'purple' | 'pink' | 'green';

export interface DeviceSpec {
  id: DeviceType;
  name: string;
  category: 'iphone' | 'ipad' | 'mac' | 'android' | 'watch';
  screenSize: Size;
  frameSize: Size;
  screenOffset: Position;
  cornerRadius: number;
  colors: DeviceColor[];
}

// Canvas & Project
export interface CanvasConfig {
  width: number;
  height: number;
  zoom: number;
  pan: Position;
  backgroundColor: string | GradientConfig;
  backgroundImage?: string;
}

export interface Project {
  id: string;
  name: string;
  preset: ExportPreset;
  canvas: CanvasConfig;
  layers: Layer[];
  brandKit?: BrandKit;
  createdAt: Date;
  updatedAt: Date;
}

// Export Presets
export type ExportPreset =
  | 'iphone-6.9'
  | 'iphone-6.5'
  | 'iphone-6.1'
  | 'ipad-13'
  | 'ipad-11'
  | 'mac'
  | 'instagram-post'
  | 'instagram-story'
  | 'twitter-post'
  | 'linkedin-post'
  | 'facebook-post'
  | 'product-hunt'
  | 'youtube-thumbnail'
  | 'custom';

export interface ExportConfig {
  preset: ExportPreset;
  name: string;
  width: number;
  height: number;
  format: 'png' | 'jpg' | 'webp';
  quality: number;
  scale: number;
}

export const EXPORT_PRESETS: Record<ExportPreset, Omit<ExportConfig, 'format' | 'quality' | 'scale'>> = {
  'iphone-6.9': { preset: 'iphone-6.9', name: 'iPhone 6.9" (Pro Max)', width: 1260, height: 2736 },
  'iphone-6.5': { preset: 'iphone-6.5', name: 'iPhone 6.5"', width: 1284, height: 2778 },
  'iphone-6.1': { preset: 'iphone-6.1', name: 'iPhone 6.1"', width: 1179, height: 2556 },
  'ipad-13': { preset: 'ipad-13', name: 'iPad 13"', width: 2064, height: 2752 },
  'ipad-11': { preset: 'ipad-11', name: 'iPad 11"', width: 1668, height: 2420 },
  'mac': { preset: 'mac', name: 'Mac App Store', width: 2880, height: 1800 },
  'instagram-post': { preset: 'instagram-post', name: 'Instagram Post', width: 1080, height: 1350 },
  'instagram-story': { preset: 'instagram-story', name: 'Instagram Story', width: 1080, height: 1920 },
  'twitter-post': { preset: 'twitter-post', name: 'Twitter/X Post', width: 1200, height: 675 },
  'linkedin-post': { preset: 'linkedin-post', name: 'LinkedIn Post', width: 1200, height: 627 },
  'facebook-post': { preset: 'facebook-post', name: 'Facebook Post', width: 1200, height: 630 },
  'product-hunt': { preset: 'product-hunt', name: 'Product Hunt', width: 1270, height: 760 },
  'youtube-thumbnail': { preset: 'youtube-thumbnail', name: 'YouTube Thumbnail', width: 1280, height: 720 },
  'custom': { preset: 'custom', name: 'Custom Size', width: 1080, height: 1920 },
};

// Brand Kit
export interface BrandKit {
  id: string;
  name: string;
  colors: BrandColor[];
  fonts: BrandFont[];
  logos: BrandLogo[];
}

export interface BrandColor {
  id: string;
  name: string;
  hex: string;
  usage: 'primary' | 'secondary' | 'accent' | 'background' | 'text' | 'custom';
}

export interface BrandFont {
  id: string;
  name: string;
  family: string;
  weights: number[];
  usage: 'heading' | 'body' | 'accent' | 'custom';
}

export interface BrandLogo {
  id: string;
  name: string;
  src: string;
  variant: 'full' | 'icon' | 'wordmark' | 'custom';
}

// Template Types
export interface Template {
  id: string;
  name: string;
  category: TemplateCategory;
  style: TemplateStyle;
  preset: ExportPreset;
  thumbnail: string;
  layers: Layer[];
  canvas: Partial<CanvasConfig>;
}

export type TemplateCategory =
  | 'app-store'
  | 'social-media'
  | 'marketing'
  | 'presentation';

export type TemplateStyle =
  | 'minimal'
  | 'bold'
  | 'gradient'
  | 'dark'
  | 'light'
  | 'glass'
  | 'lifestyle';

// History for undo/redo
export interface HistoryEntry {
  id: string;
  timestamp: number;
  action: string;
  state: {
    layers: Layer[];
    canvas: CanvasConfig;
  };
}

// Tool Types
export type Tool =
  | 'select'
  | 'move'
  | 'text'
  | 'shape'
  | 'device'
  | 'image'
  | 'effect'
  | 'crop'
  | 'highlight'
  | 'annotate';

About

A web app to help you design things, local, offline, on device. In your browser.

0 stars
0 forks