File size: 5,583 Bytes
68f7925
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import { z } from 'zod';

/**
 * テーマ抽出リクエストスキーマ
 */
export const themeExtractionRequestSchema = z.object({
  url: z.string().url('有効なURLを入力してください'),
  provider: z.enum(['openai', 'claude']).default('claude'),
  options: z
    .object({
      width: z.number().default(512),
      height: z.number().default(768),
      dummyMode: z.boolean().default(false),
    })
    .optional(),
});

export type ThemeExtractionRequest = z.infer<typeof themeExtractionRequestSchema>;

/**
 * カラーテーマスキーマ(15色対応)
 */
export const colorThemeSchema = z.object({
  // メインカラー
  primary_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  secondary_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  accent_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),

  // セマンティックカラー
  success_semantic_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  warning_semantic_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  error_semantic_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  info_semantic_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),

  // 背景色
  primary_background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  secondary_background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  tertiary_background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  overlay_background_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),

  // テキスト色
  primary_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  secondary_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  disabled_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
  inverse_text_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'カラーコードは#RRGGBBの形式で入力してください'),
});

export type ColorTheme = z.infer<typeof colorThemeSchema>;

/**
 * デザイン特性スキーマ(フォントファミリー詳細化対応)
 */
export const designCharacteristicsSchema = z.object({
  // フォントファミリー詳細化
  heading_font_family: z.string(),
  main_font_family: z.string(),
  special_font_family: z.string(),

  // デザイン特性
  design_style: z.string(),
  layout_type: z.string(),
});

export type DesignCharacteristics = z.infer<typeof designCharacteristicsSchema>;

/**
 * ブランド印象スキーマ
 */
export const brandImpressionSchema = z.object({
  brand_impression: z.array(z.string()),
  industry_characteristics: z.string(),
});

export type BrandImpression = z.infer<typeof brandImpressionSchema>;

/**
 * テーマ抽出結果スキーマ
 */
export const themeExtractionResultSchema = z.object({
  colors: colorThemeSchema,
  design: designCharacteristicsSchema,
  brand: brandImpressionSchema,
  analysis_notes: z.string(),
});

export type ThemeExtractionResult = z.infer<typeof themeExtractionResultSchema>;

/**
 * テーマ抽出レスポンススキーマ
 */
export const themeExtractionResponseSchema = z.object({
  success: z.boolean(),
  data: themeExtractionResultSchema.optional(),
  error: z.string().optional(),
  metadata: z
    .object({
      url: z.string(),
      provider: z.string(),
      processingTime: z.number(),
      screenshotTaken: z.boolean(),
      timestamp: z.string(),
    })
    .optional(),
});

export type ThemeExtractionResponse = z.infer<typeof themeExtractionResponseSchema>;

/**
 * AI応答パース用の中間スキーマ(15色+詳細フォント対応)
 */
export const rawThemeDataSchema = z.object({
  colors: z.object({
    // メインカラー
    primary_color: z.string(),
    secondary_color: z.string(),
    accent_color: z.string(),

    // セマンティックカラー
    success_semantic_color: z.string(),
    warning_semantic_color: z.string(),
    error_semantic_color: z.string(),
    info_semantic_color: z.string(),

    // 背景色
    primary_background_color: z.string(),
    secondary_background_color: z.string(),
    tertiary_background_color: z.string(),
    overlay_background_color: z.string(),

    // テキスト色
    primary_text_color: z.string(),
    secondary_text_color: z.string(),
    disabled_text_color: z.string(),
    inverse_text_color: z.string(),
  }),
  design: z.object({
    // フォントファミリー詳細化
    heading_font_family: z.string(),
    main_font_family: z.string(),
    special_font_family: z.string(),

    // デザイン特性
    design_style: z.string(),
    layout_type: z.string(),
  }),
  brand: z.object({
    brand_impression: z.array(z.string()),
    industry_characteristics: z.string(),
  }),
  analysis_notes: z.string(),
});

export type RawThemeData = z.infer<typeof rawThemeDataSchema>;