@growgroup/visual-editor 0.1.0

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.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +52 -0
  3. package/README.md +143 -0
  4. package/dist/editor.css +2 -0
  5. package/package.json +94 -0
  6. package/src/components/DeckSlideRender.tsx +21 -0
  7. package/src/components/SaveNote.tsx +21 -0
  8. package/src/components/auth/AuthProvider.tsx +44 -0
  9. package/src/components/ui/accordion.tsx +57 -0
  10. package/src/components/ui/alert-dialog.tsx +141 -0
  11. package/src/components/ui/badge.tsx +36 -0
  12. package/src/components/ui/button.tsx +56 -0
  13. package/src/components/ui/card.tsx +76 -0
  14. package/src/components/ui/checkbox.tsx +30 -0
  15. package/src/components/ui/collapsible.tsx +11 -0
  16. package/src/components/ui/context-menu.tsx +200 -0
  17. package/src/components/ui/dialog.tsx +122 -0
  18. package/src/components/ui/dropdown-menu.tsx +201 -0
  19. package/src/components/ui/input.tsx +22 -0
  20. package/src/components/ui/label.tsx +26 -0
  21. package/src/components/ui/popover.tsx +33 -0
  22. package/src/components/ui/scroll-area.tsx +48 -0
  23. package/src/components/ui/scrubbable-label.tsx +95 -0
  24. package/src/components/ui/select.tsx +159 -0
  25. package/src/components/ui/separator.tsx +31 -0
  26. package/src/components/ui/slider.tsx +28 -0
  27. package/src/components/ui/switch.tsx +29 -0
  28. package/src/components/ui/tabs.tsx +55 -0
  29. package/src/components/ui/textarea.tsx +22 -0
  30. package/src/components/ui/tooltip.tsx +32 -0
  31. package/src/components/viewer/useDeck.ts +58 -0
  32. package/src/editor/EditorContext.tsx +632 -0
  33. package/src/editor/EditorToolbar.tsx +446 -0
  34. package/src/editor/FrontendVisualEditor.tsx +2595 -0
  35. package/src/editor/autosave.ts +34 -0
  36. package/src/editor/components/AiPromptPopover.tsx +378 -0
  37. package/src/editor/components/BreakpointGuides.tsx +323 -0
  38. package/src/editor/components/BreakpointSelector.tsx +180 -0
  39. package/src/editor/components/ComponentPropertyEditor.tsx +426 -0
  40. package/src/editor/components/CssEditorDialog.tsx +168 -0
  41. package/src/editor/components/EditorCanvas.tsx +987 -0
  42. package/src/editor/components/EditorContextMenu.tsx +515 -0
  43. package/src/editor/components/EditorFooter.tsx +81 -0
  44. package/src/editor/components/EditorHeader.tsx +524 -0
  45. package/src/editor/components/EditorLayerPanel.tsx +1197 -0
  46. package/src/editor/components/EditorPropertyPanel.tsx +2996 -0
  47. package/src/editor/components/EditorSidebar.tsx +226 -0
  48. package/src/editor/components/FigmaColorPicker.tsx +1577 -0
  49. package/src/editor/components/HtmlEditorDialog.tsx +71 -0
  50. package/src/editor/components/HtmlImportDialog.tsx +346 -0
  51. package/src/editor/components/JsEditorDialog.tsx +175 -0
  52. package/src/editor/components/LayerTreeItem.tsx +494 -0
  53. package/src/editor/components/MasterComponentEditor.tsx +846 -0
  54. package/src/editor/components/MediaLibraryDialog.tsx +447 -0
  55. package/src/editor/components/PageSettingsDialog.tsx +776 -0
  56. package/src/editor/components/VariablePicker.tsx +355 -0
  57. package/src/editor/components/VariablesDialog.tsx +564 -0
  58. package/src/editor/components/VariantEditor.tsx +687 -0
  59. package/src/editor/components/VariantMatrix.tsx +507 -0
  60. package/src/editor/components/component-panel/CategoryAccordion.tsx +139 -0
  61. package/src/editor/components/component-panel/ComponentGrid.tsx +51 -0
  62. package/src/editor/components/component-panel/ComponentItem.tsx +368 -0
  63. package/src/editor/components/component-panel/ComponentPanel.tsx +275 -0
  64. package/src/editor/components/component-panel/ComponentSearch.tsx +82 -0
  65. package/src/editor/components/component-panel/VariantList.tsx +260 -0
  66. package/src/editor/components/component-panel/index.ts +12 -0
  67. package/src/editor/components/index.ts +48 -0
  68. package/src/editor/components/multi-page/CanvasZoomControls.tsx +71 -0
  69. package/src/editor/components/multi-page/InfiniteCanvas.tsx +95 -0
  70. package/src/editor/components/multi-page/MultiPageCanvasView.tsx +1404 -0
  71. package/src/editor/components/multi-page/PageFrameOverlay.tsx +76 -0
  72. package/src/editor/components/multi-page/PageLabel.tsx +34 -0
  73. package/src/editor/components/multi-page/PageLivePreview.tsx +242 -0
  74. package/src/editor/components/multi-page/PageThumbnail.tsx +59 -0
  75. package/src/editor/components/multi-page/index.ts +7 -0
  76. package/src/editor/components/ppt/PptChrome.tsx +2508 -0
  77. package/src/editor/components/ppt/PptComments.tsx +589 -0
  78. package/src/editor/components/ppt/PptDesignProposals.tsx +275 -0
  79. package/src/editor/components/ppt/PptFormatPane.tsx +320 -0
  80. package/src/editor/components/ppt/PptNotes.tsx +246 -0
  81. package/src/editor/components/property-panel/AlignmentPanel.tsx +110 -0
  82. package/src/editor/components/property-panel/AutoLayoutPanel.tsx +615 -0
  83. package/src/editor/components/property-panel/BorderSection.tsx +104 -0
  84. package/src/editor/components/property-panel/CompactNumberInput.tsx +237 -0
  85. package/src/editor/components/property-panel/CompactSizeInput.tsx +148 -0
  86. package/src/editor/components/property-panel/EffectSection.tsx +157 -0
  87. package/src/editor/components/property-panel/FillSection.tsx +69 -0
  88. package/src/editor/components/property-panel/GoogleFontPicker.tsx +192 -0
  89. package/src/editor/components/property-panel/ImageSection.tsx +206 -0
  90. package/src/editor/components/property-panel/ImgSrcSection.tsx +125 -0
  91. package/src/editor/components/property-panel/InstanceOverrideSection.tsx +413 -0
  92. package/src/editor/components/property-panel/LayoutSection.tsx +105 -0
  93. package/src/editor/components/property-panel/LinkSection.tsx +103 -0
  94. package/src/editor/components/property-panel/PropertyVariablePicker.tsx +311 -0
  95. package/src/editor/components/property-panel/ScalePanel.tsx +212 -0
  96. package/src/editor/components/property-panel/TypographySection.tsx +230 -0
  97. package/src/editor/components/property-panel/UnitAwareNumberInput.tsx +238 -0
  98. package/src/editor/components/property-panel/VariableAwareColorInput.tsx +477 -0
  99. package/src/editor/components/property-panel/VariableAwareInput.tsx +606 -0
  100. package/src/editor/components/property-panel/VariableAwareSizeInput.tsx +588 -0
  101. package/src/editor/components/property-panel/VariableAwareUnitInput.tsx +546 -0
  102. package/src/editor/components/property-panel/index.ts +24 -0
  103. package/src/editor/components/property-panel/unit-utils.ts +261 -0
  104. package/src/editor/components/shell/EditorTopBar.tsx +392 -0
  105. package/src/editor/components/shell/LeftPanel.tsx +47 -0
  106. package/src/editor/components/shell/PagesPanel.tsx +118 -0
  107. package/src/editor/components/variables-panel/ColorValueCell.tsx +165 -0
  108. package/src/editor/components/variables-panel/TextValueCell.tsx +116 -0
  109. package/src/editor/components/variables-panel/VariablesPanel.tsx +518 -0
  110. package/src/editor/components/variables-panel/index.ts +7 -0
  111. package/src/editor/constants.ts +468 -0
  112. package/src/editor/contexts/EditorArtboardContext.tsx +229 -0
  113. package/src/editor/contexts/EditorComponentsContext.tsx +1320 -0
  114. package/src/editor/contexts/EditorDocumentContext.tsx +113 -0
  115. package/src/editor/contexts/EditorHistoryContext.tsx +516 -0
  116. package/src/editor/contexts/EditorRefsContext.tsx +204 -0
  117. package/src/editor/contexts/EditorSelectionContext.tsx +54 -0
  118. package/src/editor/contexts/EditorToolContext.tsx +58 -0
  119. package/src/editor/contexts/EditorUIStateContext.tsx +122 -0
  120. package/src/editor/contexts/EditorVariablesContext.tsx +397 -0
  121. package/src/editor/contexts/EditorViewContext.tsx +101 -0
  122. package/src/editor/contexts/MultiPageCanvasContext.tsx +498 -0
  123. package/src/editor/contexts/index.ts +17 -0
  124. package/src/editor/editor-skin.css +122 -0
  125. package/src/editor/hooks/index.ts +38 -0
  126. package/src/editor/hooks/useAiReplace.ts +397 -0
  127. package/src/editor/hooks/useAltMeasure.ts +67 -0
  128. package/src/editor/hooks/useBrowserZoomPrevention.ts +121 -0
  129. package/src/editor/hooks/useCanvasControls.ts +1222 -0
  130. package/src/editor/hooks/useComponentEditMode.ts +658 -0
  131. package/src/editor/hooks/useComponentInstances.ts +515 -0
  132. package/src/editor/hooks/useContextMenuHandler.ts +157 -0
  133. package/src/editor/hooks/useCoordinateTransform.ts +207 -0
  134. package/src/editor/hooks/useDragResize.ts +1317 -0
  135. package/src/editor/hooks/useDrawingMode.ts +472 -0
  136. package/src/editor/hooks/useEditorColors.ts +144 -0
  137. package/src/editor/hooks/useEditorMessages.ts +108 -0
  138. package/src/editor/hooks/useElementActions.ts +1754 -0
  139. package/src/editor/hooks/useElementSelection.ts +1573 -0
  140. package/src/editor/hooks/useFocusManagement.ts +249 -0
  141. package/src/editor/hooks/useGoogleFonts.ts +305 -0
  142. package/src/editor/hooks/useIframeInitializer.ts +584 -0
  143. package/src/editor/hooks/useIframeSetup.ts +360 -0
  144. package/src/editor/hooks/useImageUpload.ts +270 -0
  145. package/src/editor/hooks/useInfiniteCanvas.ts +301 -0
  146. package/src/editor/hooks/useKeyboardShortcuts.ts +205 -0
  147. package/src/editor/hooks/useMarqueeSelection.ts +388 -0
  148. package/src/editor/hooks/useMediaLibrary.ts +129 -0
  149. package/src/editor/hooks/usePageSettingsManager.ts +739 -0
  150. package/src/editor/hooks/useResizablePanel.ts +163 -0
  151. package/src/editor/hooks/useRichPaste.ts +255 -0
  152. package/src/editor/hooks/useTouchGestures.ts +197 -0
  153. package/src/editor/index.ts +27 -0
  154. package/src/editor/types/page-settings.ts +513 -0
  155. package/src/editor/types.ts +382 -0
  156. package/src/editor/utils/align-elements.ts +169 -0
  157. package/src/editor/utils/api-json.ts +21 -0
  158. package/src/editor/utils/aspect-lock.ts +50 -0
  159. package/src/editor/utils/component-renderer.ts +702 -0
  160. package/src/editor/utils/component-sync.ts +845 -0
  161. package/src/editor/utils/crop-mode.ts +265 -0
  162. package/src/editor/utils/dom-utils.ts +2238 -0
  163. package/src/editor/utils/element-effects.ts +218 -0
  164. package/src/editor/utils/eyedropper.ts +35 -0
  165. package/src/editor/utils/figma-export.ts +560 -0
  166. package/src/editor/utils/figma-kiwi-decoder.ts +722 -0
  167. package/src/editor/utils/figma-kiwi-encoder.ts +583 -0
  168. package/src/editor/utils/figma-paste.ts +2262 -0
  169. package/src/editor/utils/flex-reorder.ts +231 -0
  170. package/src/editor/utils/flex-utils.ts +1230 -0
  171. package/src/editor/utils/geometry.ts +232 -0
  172. package/src/editor/utils/grid-layout.ts +210 -0
  173. package/src/editor/utils/html-utils.ts +470 -0
  174. package/src/editor/utils/index.ts +11 -0
  175. package/src/editor/utils/ink-style.ts +57 -0
  176. package/src/editor/utils/inline-format.ts +236 -0
  177. package/src/editor/utils/measure-distance.ts +120 -0
  178. package/src/editor/utils/override-apply.ts +526 -0
  179. package/src/editor/utils/override-detection.ts +613 -0
  180. package/src/editor/utils/paste-processors.ts +609 -0
  181. package/src/editor/utils/paste-sanitizer.ts +244 -0
  182. package/src/editor/utils/restore-flow.ts +188 -0
  183. package/src/editor/utils/shape-library.ts +171 -0
  184. package/src/editor/utils/slide-root.ts +29 -0
  185. package/src/editor/utils/smart-guides.ts +218 -0
  186. package/src/editor/utils/style-utils.ts +685 -0
  187. package/src/editor/utils/table-edit.ts +151 -0
  188. package/src/editor/utils/tailwind-mappings.ts +778 -0
  189. package/src/editor/utils/tailwind-utils.ts +804 -0
  190. package/src/editor/utils/text-highlight.ts +216 -0
  191. package/src/editor/utils/theme-to-variables.ts +341 -0
  192. package/src/editor/utils/variant-resolver.ts +456 -0
  193. package/src/editor/utils/viewport-utils.ts +295 -0
  194. package/src/hooks/useEditorHistory.ts +195 -0
  195. package/src/hooks/useEditorShortcuts.ts +260 -0
  196. package/src/index.ts +40 -0
  197. package/src/io.ts +134 -0
  198. package/src/lib/agent/slide-agent/types.ts +547 -0
  199. package/src/lib/agent/website-agent/types.ts +805 -0
  200. package/src/lib/api/auth-fetch.ts +58 -0
  201. package/src/lib/deck.ts +69 -0
  202. package/src/lib/export.ts +47 -0
  203. package/src/lib/firebase/config.ts +29 -0
  204. package/src/lib/firebase/css-variables.ts +378 -0
  205. package/src/lib/firebase/editor-components.ts +677 -0
  206. package/src/lib/firebase/storage.ts +469 -0
  207. package/src/lib/utils.ts +6 -0
  208. package/src/styles/editor.css +52 -0
  209. package/src/styles/skin.css +122 -0
  210. package/src/types/css-variables.ts +645 -0
  211. package/src/types/editor-components.ts +944 -0
  212. package/src/types/editor.ts +420 -0
  213. package/src/types/page-master.ts +197 -0
  214. package/src/types/page.ts +419 -0
  215. package/src/types/slide.ts +402 -0
  216. package/src/types/website-theme.ts +788 -0
  217. package/src/types/website.ts +374 -0
  218. package/src/vendor/firebase-firestore.ts +13 -0
  219. package/src/vendor/firebase-functions.ts +17 -0
@@ -0,0 +1,788 @@
1
+ /**
2
+ * Webサイトテーマの型定義
3
+ * デザインシステムの基盤となる包括的な設定
4
+ */
5
+
6
+ import { Timestamp } from '../vendor/firebase-firestore';
7
+
8
+ // ============================================
9
+ // 基本カラー設定
10
+ // ============================================
11
+
12
+ export interface WebsiteThemeColors {
13
+ background: string; // ページ背景色
14
+ text: string; // 本文テキスト色
15
+ textMuted?: string; // 薄いテキスト色(キャプション等)
16
+ primary: string; // プライマリカラー
17
+ secondary?: string; // セカンダリカラー
18
+ accent?: string; // アクセントカラー
19
+ surface?: string; // サーフェス(カード等)の色
20
+ surfaceAlt?: string; // 代替サーフェス色(ストライプ等)
21
+ border?: string; // ボーダー色
22
+ borderStrong?: string; // 強調ボーダー色
23
+ success?: string; // 成功色
24
+ warning?: string; // 警告色
25
+ error?: string; // エラー色
26
+ info?: string; // 情報色
27
+ }
28
+
29
+ // ============================================
30
+ // 基本スタイルオプション
31
+ // ============================================
32
+
33
+ export type BorderRadiusOption = 'none' | 'small' | 'medium' | 'large' | 'full';
34
+ export type ShadowOption = 'none' | 'subtle' | 'medium' | 'strong';
35
+ export type SpacingOption = 'compact' | 'normal' | 'relaxed' | 'spacious';
36
+
37
+ export interface WebsiteThemeStyles {
38
+ borderRadius?: BorderRadiusOption;
39
+ shadow?: ShadowOption;
40
+ spacing?: SpacingOption;
41
+ }
42
+
43
+ // ============================================
44
+ // タイポグラフィ設定
45
+ // ============================================
46
+
47
+ // テキストスタイルの詳細設定
48
+ export interface TextStyle {
49
+ fontSize: string; // 例: '16px', '1rem'
50
+ fontWeight: string; // 例: '400', '700'
51
+ lineHeight: string; // 例: '1.5', '1.75'
52
+ letterSpacing?: string; // 例: '-0.02em', '0.05em'
53
+ color?: string; // テーマカラーを上書きする場合
54
+ textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize';
55
+ marginBottom?: string; // 要素後の余白
56
+ }
57
+
58
+ // 見出しスタイル(h1-h6)
59
+ export interface HeadingStyles {
60
+ h1: TextStyle;
61
+ h2: TextStyle;
62
+ h3: TextStyle;
63
+ h4: TextStyle;
64
+ h5: TextStyle;
65
+ h6: TextStyle;
66
+ }
67
+
68
+ // 本文スタイル
69
+ export interface BodyStyles {
70
+ base: TextStyle; // 通常本文
71
+ large: TextStyle; // リード文・大きめ本文
72
+ small: TextStyle; // 小さめ本文・注釈
73
+ }
74
+
75
+ // 拡張タイポグラフィ設定
76
+ export interface WebsiteTypography {
77
+ // フォント設定
78
+ fontFamily: string; // 本文フォント
79
+ headingFontFamily?: string; // 見出しフォント(省略時はfontFamily)
80
+ monoFontFamily?: string; // コード用等幅フォント
81
+
82
+ // 基準フォントサイズ
83
+ baseFontSize?: string; // 例: '16px'
84
+
85
+ // 見出しスタイル
86
+ headings: HeadingStyles;
87
+
88
+ // 本文スタイル
89
+ body: BodyStyles;
90
+ }
91
+
92
+ // ============================================
93
+ // コンポーネントスタイル設定
94
+ // ============================================
95
+
96
+ // リンクスタイル
97
+ export interface LinkStyles {
98
+ color?: string;
99
+ hoverColor?: string;
100
+ textDecoration?: 'none' | 'underline';
101
+ hoverTextDecoration?: 'none' | 'underline';
102
+ }
103
+
104
+ // ボタンバリアント
105
+ export interface ButtonVariantStyle {
106
+ backgroundColor?: string;
107
+ textColor?: string;
108
+ borderColor?: string;
109
+ hoverBackgroundColor?: string;
110
+ hoverTextColor?: string;
111
+ hoverBorderColor?: string;
112
+ }
113
+
114
+ // ボタンスタイル
115
+ export interface ButtonStyles {
116
+ borderRadius?: string;
117
+ fontWeight?: string;
118
+ paddingX?: string;
119
+ paddingY?: string;
120
+ // バリアント
121
+ primary?: ButtonVariantStyle;
122
+ secondary?: ButtonVariantStyle;
123
+ outline?: ButtonVariantStyle;
124
+ ghost?: ButtonVariantStyle;
125
+ }
126
+
127
+ // テーブルスタイル
128
+ export interface TableStyles {
129
+ // ヘッダー
130
+ headerBackgroundColor?: string;
131
+ headerTextColor?: string;
132
+ headerFontWeight?: string;
133
+ headerBorderColor?: string;
134
+ // セル
135
+ cellPaddingX?: string;
136
+ cellPaddingY?: string;
137
+ cellBorderColor?: string;
138
+ // ストライプ
139
+ stripedBackgroundColor?: string;
140
+ // ホバー
141
+ hoverBackgroundColor?: string;
142
+ }
143
+
144
+ // 引用(blockquote)スタイル
145
+ export interface BlockquoteStyles {
146
+ backgroundColor?: string;
147
+ borderLeftColor?: string;
148
+ borderLeftWidth?: string;
149
+ textColor?: string;
150
+ fontStyle?: 'normal' | 'italic';
151
+ paddingX?: string;
152
+ paddingY?: string;
153
+ fontSize?: string;
154
+ }
155
+
156
+ // リストスタイル
157
+ export interface ListStyles {
158
+ // マーカーカラー
159
+ markerColor?: string;
160
+ // 項目間の余白
161
+ itemSpacing?: string;
162
+ // ネストのインデント
163
+ nestedIndent?: string;
164
+ // 順序付きリストのスタイル
165
+ orderedListStyle?: 'decimal' | 'lower-alpha' | 'lower-roman' | 'upper-alpha' | 'upper-roman';
166
+ // 順序なしリストのスタイル
167
+ unorderedListStyle?: 'disc' | 'circle' | 'square' | 'none';
168
+ }
169
+
170
+ // コードブロックスタイル
171
+ export interface CodeStyles {
172
+ // インラインコード
173
+ inlineBackgroundColor?: string;
174
+ inlineTextColor?: string;
175
+ inlinePaddingX?: string;
176
+ inlinePaddingY?: string;
177
+ inlineBorderRadius?: string;
178
+ // コードブロック
179
+ blockBackgroundColor?: string;
180
+ blockTextColor?: string;
181
+ blockPadding?: string;
182
+ blockBorderRadius?: string;
183
+ blockBorderColor?: string;
184
+ }
185
+
186
+ // カード/サーフェススタイル
187
+ export interface CardStyles {
188
+ backgroundColor?: string;
189
+ borderColor?: string;
190
+ borderWidth?: string;
191
+ borderRadius?: string;
192
+ shadow?: string;
193
+ padding?: string;
194
+ hoverShadow?: string;
195
+ hoverBorderColor?: string;
196
+ }
197
+
198
+ // フォーム要素スタイル
199
+ export interface FormStyles {
200
+ // 入力フィールド
201
+ inputBackgroundColor?: string;
202
+ inputTextColor?: string;
203
+ inputBorderColor?: string;
204
+ inputBorderRadius?: string;
205
+ inputPaddingX?: string;
206
+ inputPaddingY?: string;
207
+ inputFocusBorderColor?: string;
208
+ inputFocusRingColor?: string;
209
+ // プレースホルダー
210
+ placeholderColor?: string;
211
+ // ラベル
212
+ labelColor?: string;
213
+ labelFontWeight?: string;
214
+ labelFontSize?: string;
215
+ // エラー状態
216
+ errorBorderColor?: string;
217
+ errorTextColor?: string;
218
+ }
219
+
220
+ // 区切り線/セパレータスタイル
221
+ export interface DividerStyles {
222
+ color?: string;
223
+ thickness?: string;
224
+ style?: 'solid' | 'dashed' | 'dotted';
225
+ spacing?: string; // 上下の余白
226
+ }
227
+
228
+ // バッジ/タグスタイル
229
+ export interface BadgeStyles {
230
+ backgroundColor?: string;
231
+ textColor?: string;
232
+ borderRadius?: string;
233
+ paddingX?: string;
234
+ paddingY?: string;
235
+ fontSize?: string;
236
+ fontWeight?: string;
237
+ }
238
+
239
+ // アラート/通知スタイル
240
+ export interface AlertStyles {
241
+ borderRadius?: string;
242
+ padding?: string;
243
+ // バリアント
244
+ successBackgroundColor?: string;
245
+ successBorderColor?: string;
246
+ successTextColor?: string;
247
+ warningBackgroundColor?: string;
248
+ warningBorderColor?: string;
249
+ warningTextColor?: string;
250
+ errorBackgroundColor?: string;
251
+ errorBorderColor?: string;
252
+ errorTextColor?: string;
253
+ infoBackgroundColor?: string;
254
+ infoBorderColor?: string;
255
+ infoTextColor?: string;
256
+ }
257
+
258
+ // 全コンポーネントスタイル
259
+ export interface ComponentStyles {
260
+ link?: LinkStyles;
261
+ button?: ButtonStyles;
262
+ table?: TableStyles;
263
+ blockquote?: BlockquoteStyles;
264
+ list?: ListStyles;
265
+ code?: CodeStyles;
266
+ card?: CardStyles;
267
+ form?: FormStyles;
268
+ divider?: DividerStyles;
269
+ badge?: BadgeStyles;
270
+ alert?: AlertStyles;
271
+ }
272
+
273
+ // ============================================
274
+ // Webサイトテーマ本体
275
+ // ============================================
276
+
277
+ export interface WebsiteTheme {
278
+ id: string;
279
+ name: string;
280
+ description?: string;
281
+ category?: 'light' | 'dark' | 'corporate' | 'modern' | 'custom';
282
+
283
+ // カラー設定
284
+ colors: WebsiteThemeColors;
285
+
286
+ // 基本スタイル設定
287
+ styles?: WebsiteThemeStyles;
288
+
289
+ // タイポグラフィ設定
290
+ typography?: WebsiteTypography;
291
+
292
+ // コンポーネントスタイル設定
293
+ components?: ComponentStyles;
294
+
295
+ // 追加プロンプト(AIへの追加指示)
296
+ additionalPrompt?: string;
297
+
298
+ // メタデータ
299
+ isDefault?: boolean;
300
+ isSystem?: boolean;
301
+ userId?: string;
302
+
303
+ createdAt: Timestamp | Date;
304
+ updatedAt: Timestamp | Date;
305
+ }
306
+
307
+ // ============================================
308
+ // スタイルオプション定数
309
+ // ============================================
310
+
311
+ export const BORDER_RADIUS_OPTIONS: { value: BorderRadiusOption; label: string; css: string }[] = [
312
+ { value: 'none', label: 'なし', css: '0' },
313
+ { value: 'small', label: '小', css: '4px' },
314
+ { value: 'medium', label: '中', css: '8px' },
315
+ { value: 'large', label: '大', css: '16px' },
316
+ { value: 'full', label: '最大', css: '9999px' },
317
+ ];
318
+
319
+ export const SHADOW_OPTIONS: { value: ShadowOption; label: string; css: string }[] = [
320
+ { value: 'none', label: 'なし', css: 'none' },
321
+ { value: 'subtle', label: '控えめ', css: '0 1px 2px rgba(0,0,0,0.05)' },
322
+ { value: 'medium', label: '標準', css: '0 4px 6px rgba(0,0,0,0.1)' },
323
+ { value: 'strong', label: '強め', css: '0 10px 15px rgba(0,0,0,0.15)' },
324
+ ];
325
+
326
+ export const SPACING_OPTIONS: { value: SpacingOption; label: string; description: string }[] = [
327
+ { value: 'compact', label: '詰める', description: '要素間の余白を最小限に' },
328
+ { value: 'normal', label: '通常', description: '標準的な余白感' },
329
+ { value: 'relaxed', label: '広め', description: 'ゆったりとした余白' },
330
+ { value: 'spacious', label: '最大', description: '大きな余白でインパクト重視' },
331
+ ];
332
+
333
+ // フォントウェイトオプション
334
+ export const FONT_WEIGHT_OPTIONS = [
335
+ { value: '300', label: 'Light' },
336
+ { value: '400', label: 'Regular' },
337
+ { value: '500', label: 'Medium' },
338
+ { value: '600', label: 'Semi Bold' },
339
+ { value: '700', label: 'Bold' },
340
+ { value: '800', label: 'Extra Bold' },
341
+ ];
342
+
343
+ // フォントサイズプリセット
344
+ export const FONT_SIZE_PRESETS = {
345
+ h1: ['32px', '36px', '40px', '48px', '56px', '64px'],
346
+ h2: ['28px', '32px', '36px', '40px', '48px'],
347
+ h3: ['24px', '28px', '32px', '36px'],
348
+ h4: ['20px', '22px', '24px', '28px'],
349
+ h5: ['18px', '20px', '22px', '24px'],
350
+ h6: ['16px', '18px', '20px'],
351
+ body: ['14px', '16px', '18px', '20px'],
352
+ small: ['12px', '13px', '14px'],
353
+ };
354
+
355
+ // ============================================
356
+ // デフォルト値の定義
357
+ // ============================================
358
+
359
+ // デフォルトの見出しスタイル
360
+ export const DEFAULT_HEADING_STYLES: HeadingStyles = {
361
+ h1: {
362
+ fontSize: '48px',
363
+ fontWeight: '700',
364
+ lineHeight: '1.2',
365
+ letterSpacing: '-0.02em',
366
+ marginBottom: '24px',
367
+ },
368
+ h2: {
369
+ fontSize: '36px',
370
+ fontWeight: '600',
371
+ lineHeight: '1.25',
372
+ letterSpacing: '-0.01em',
373
+ marginBottom: '20px',
374
+ },
375
+ h3: {
376
+ fontSize: '28px',
377
+ fontWeight: '600',
378
+ lineHeight: '1.3',
379
+ marginBottom: '16px',
380
+ },
381
+ h4: {
382
+ fontSize: '24px',
383
+ fontWeight: '600',
384
+ lineHeight: '1.35',
385
+ marginBottom: '12px',
386
+ },
387
+ h5: {
388
+ fontSize: '20px',
389
+ fontWeight: '600',
390
+ lineHeight: '1.4',
391
+ marginBottom: '8px',
392
+ },
393
+ h6: {
394
+ fontSize: '18px',
395
+ fontWeight: '600',
396
+ lineHeight: '1.4',
397
+ marginBottom: '8px',
398
+ },
399
+ };
400
+
401
+ // デフォルトの本文スタイル
402
+ export const DEFAULT_BODY_STYLES: BodyStyles = {
403
+ base: {
404
+ fontSize: '16px',
405
+ fontWeight: '400',
406
+ lineHeight: '1.7',
407
+ marginBottom: '16px',
408
+ },
409
+ large: {
410
+ fontSize: '20px',
411
+ fontWeight: '400',
412
+ lineHeight: '1.6',
413
+ marginBottom: '20px',
414
+ },
415
+ small: {
416
+ fontSize: '14px',
417
+ fontWeight: '400',
418
+ lineHeight: '1.5',
419
+ marginBottom: '12px',
420
+ },
421
+ };
422
+
423
+ // デフォルトのタイポグラフィ設定
424
+ export const DEFAULT_WEBSITE_TYPOGRAPHY: WebsiteTypography = {
425
+ fontFamily: "'Noto Sans JP', 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Meiryo', sans-serif",
426
+ headingFontFamily: "'Noto Sans JP', 'Hiragino Sans', sans-serif",
427
+ monoFontFamily: "'JetBrains Mono', 'Fira Code', 'Source Code Pro', monospace",
428
+ baseFontSize: '16px',
429
+ headings: DEFAULT_HEADING_STYLES,
430
+ body: DEFAULT_BODY_STYLES,
431
+ };
432
+
433
+ // デフォルトのコンポーネントスタイル
434
+ export const DEFAULT_COMPONENT_STYLES: ComponentStyles = {
435
+ link: {
436
+ textDecoration: 'none',
437
+ hoverTextDecoration: 'underline',
438
+ },
439
+ button: {
440
+ borderRadius: '8px',
441
+ fontWeight: '500',
442
+ paddingX: '16px',
443
+ paddingY: '10px',
444
+ },
445
+ table: {
446
+ headerFontWeight: '600',
447
+ cellPaddingX: '16px',
448
+ cellPaddingY: '12px',
449
+ },
450
+ blockquote: {
451
+ borderLeftWidth: '4px',
452
+ fontStyle: 'normal',
453
+ paddingX: '20px',
454
+ paddingY: '16px',
455
+ fontSize: '18px',
456
+ },
457
+ list: {
458
+ itemSpacing: '8px',
459
+ nestedIndent: '24px',
460
+ orderedListStyle: 'decimal',
461
+ unorderedListStyle: 'disc',
462
+ },
463
+ code: {
464
+ inlinePaddingX: '6px',
465
+ inlinePaddingY: '2px',
466
+ inlineBorderRadius: '4px',
467
+ blockPadding: '16px',
468
+ blockBorderRadius: '8px',
469
+ },
470
+ card: {
471
+ borderWidth: '1px',
472
+ borderRadius: '12px',
473
+ padding: '24px',
474
+ },
475
+ form: {
476
+ inputBorderRadius: '8px',
477
+ inputPaddingX: '12px',
478
+ inputPaddingY: '10px',
479
+ labelFontWeight: '500',
480
+ labelFontSize: '14px',
481
+ },
482
+ divider: {
483
+ thickness: '1px',
484
+ style: 'solid',
485
+ spacing: '24px',
486
+ },
487
+ badge: {
488
+ borderRadius: '9999px',
489
+ paddingX: '10px',
490
+ paddingY: '4px',
491
+ fontSize: '12px',
492
+ fontWeight: '500',
493
+ },
494
+ alert: {
495
+ borderRadius: '8px',
496
+ padding: '16px',
497
+ },
498
+ };
499
+
500
+ // ============================================
501
+ // リクエスト型
502
+ // ============================================
503
+
504
+ export interface CreateWebsiteThemeRequest {
505
+ name: string;
506
+ description?: string;
507
+ category?: WebsiteTheme['category'];
508
+ colors: WebsiteThemeColors;
509
+ styles?: WebsiteThemeStyles;
510
+ typography?: WebsiteTypography;
511
+ components?: ComponentStyles;
512
+ additionalPrompt?: string;
513
+ }
514
+
515
+ export interface UpdateWebsiteThemeRequest {
516
+ name?: string;
517
+ description?: string;
518
+ category?: WebsiteTheme['category'];
519
+ colors?: Partial<WebsiteThemeColors>;
520
+ styles?: WebsiteThemeStyles;
521
+ typography?: Partial<WebsiteTypography>;
522
+ components?: Partial<ComponentStyles>;
523
+ additionalPrompt?: string;
524
+ }
525
+
526
+ export interface WebsiteThemeFilter {
527
+ category?: WebsiteTheme['category'];
528
+ userId?: string;
529
+ includeSystem?: boolean;
530
+ }
531
+
532
+ // ============================================
533
+ // デフォルトテーマ(4 system themes)
534
+ // ============================================
535
+
536
+ export const DEFAULT_WEBSITE_THEMES: Omit<WebsiteTheme, 'id' | 'createdAt' | 'updatedAt'>[] = [
537
+ {
538
+ name: 'ライト',
539
+ description: '明るく清潔感のある標準テーマ',
540
+ category: 'light',
541
+ colors: {
542
+ background: '#ffffff',
543
+ text: '#1f2937',
544
+ textMuted: '#6b7280',
545
+ primary: '#3b82f6',
546
+ secondary: '#6b7280',
547
+ accent: '#2563eb',
548
+ surface: '#f9fafb',
549
+ surfaceAlt: '#f3f4f6',
550
+ border: '#e5e7eb',
551
+ borderStrong: '#d1d5db',
552
+ success: '#10b981',
553
+ warning: '#f59e0b',
554
+ error: '#ef4444',
555
+ info: '#3b82f6',
556
+ },
557
+ styles: {
558
+ borderRadius: 'medium',
559
+ shadow: 'medium',
560
+ spacing: 'normal',
561
+ },
562
+ isDefault: true,
563
+ isSystem: true,
564
+ },
565
+ {
566
+ name: 'ダーク',
567
+ description: 'モダンで落ち着いたダークテーマ',
568
+ category: 'dark',
569
+ colors: {
570
+ background: '#111827',
571
+ text: '#f9fafb',
572
+ textMuted: '#9ca3af',
573
+ primary: '#3b82f6',
574
+ secondary: '#9ca3af',
575
+ accent: '#60a5fa',
576
+ surface: '#1f2937',
577
+ surfaceAlt: '#374151',
578
+ border: '#374151',
579
+ borderStrong: '#4b5563',
580
+ success: '#34d399',
581
+ warning: '#fbbf24',
582
+ error: '#f87171',
583
+ info: '#60a5fa',
584
+ },
585
+ styles: {
586
+ borderRadius: 'medium',
587
+ shadow: 'medium',
588
+ spacing: 'normal',
589
+ },
590
+ isSystem: true,
591
+ },
592
+ {
593
+ name: 'コーポレート',
594
+ description: 'ビジネス向けの信頼感あるテーマ',
595
+ category: 'corporate',
596
+ colors: {
597
+ background: '#ffffff',
598
+ text: '#1e3a5f',
599
+ textMuted: '#64748b',
600
+ primary: '#0a4d8c',
601
+ secondary: '#64748b',
602
+ accent: '#0d6efd',
603
+ surface: '#f8fafc',
604
+ surfaceAlt: '#f1f5f9',
605
+ border: '#cbd5e1',
606
+ borderStrong: '#94a3b8',
607
+ success: '#059669',
608
+ warning: '#d97706',
609
+ error: '#dc2626',
610
+ info: '#0284c7',
611
+ },
612
+ styles: {
613
+ borderRadius: 'small',
614
+ shadow: 'subtle',
615
+ spacing: 'normal',
616
+ },
617
+ isSystem: true,
618
+ },
619
+ {
620
+ name: 'モダン',
621
+ description: 'スタイリッシュで現代的なテーマ',
622
+ category: 'modern',
623
+ colors: {
624
+ background: '#fafafa',
625
+ text: '#18181b',
626
+ textMuted: '#71717a',
627
+ primary: '#8b5cf6',
628
+ secondary: '#71717a',
629
+ accent: '#a855f7',
630
+ surface: '#ffffff',
631
+ surfaceAlt: '#f4f4f5',
632
+ border: '#e4e4e7',
633
+ borderStrong: '#d4d4d8',
634
+ success: '#22c55e',
635
+ warning: '#eab308',
636
+ error: '#ef4444',
637
+ info: '#6366f1',
638
+ },
639
+ styles: {
640
+ borderRadius: 'large',
641
+ shadow: 'medium',
642
+ spacing: 'relaxed',
643
+ },
644
+ isSystem: true,
645
+ },
646
+ ];
647
+
648
+ // ============================================
649
+ // ヘルパー関数
650
+ // ============================================
651
+
652
+ /**
653
+ * テーマからコンポーネントの完全なスタイルを取得
654
+ * デフォルト値とテーマ値をマージ
655
+ */
656
+ export function getComponentStyles(theme: WebsiteTheme): ComponentStyles {
657
+ return {
658
+ link: {
659
+ ...DEFAULT_COMPONENT_STYLES.link,
660
+ color: theme.colors.accent || theme.colors.primary,
661
+ hoverColor: theme.colors.primary,
662
+ ...theme.components?.link,
663
+ },
664
+ button: {
665
+ ...DEFAULT_COMPONENT_STYLES.button,
666
+ primary: {
667
+ backgroundColor: theme.colors.primary,
668
+ textColor: '#ffffff',
669
+ ...theme.components?.button?.primary,
670
+ },
671
+ secondary: {
672
+ backgroundColor: theme.colors.secondary || theme.colors.surface,
673
+ textColor: theme.colors.text,
674
+ borderColor: theme.colors.border,
675
+ ...theme.components?.button?.secondary,
676
+ },
677
+ outline: {
678
+ backgroundColor: 'transparent',
679
+ textColor: theme.colors.primary,
680
+ borderColor: theme.colors.primary,
681
+ ...theme.components?.button?.outline,
682
+ },
683
+ ghost: {
684
+ backgroundColor: 'transparent',
685
+ textColor: theme.colors.text,
686
+ ...theme.components?.button?.ghost,
687
+ },
688
+ ...theme.components?.button,
689
+ },
690
+ table: {
691
+ ...DEFAULT_COMPONENT_STYLES.table,
692
+ headerBackgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
693
+ headerTextColor: theme.colors.text,
694
+ headerBorderColor: theme.colors.border,
695
+ cellBorderColor: theme.colors.border,
696
+ stripedBackgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
697
+ hoverBackgroundColor: theme.colors.surface,
698
+ ...theme.components?.table,
699
+ },
700
+ blockquote: {
701
+ ...DEFAULT_COMPONENT_STYLES.blockquote,
702
+ backgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
703
+ borderLeftColor: theme.colors.primary,
704
+ textColor: theme.colors.textMuted || theme.colors.text,
705
+ ...theme.components?.blockquote,
706
+ },
707
+ list: {
708
+ ...DEFAULT_COMPONENT_STYLES.list,
709
+ markerColor: theme.colors.primary,
710
+ ...theme.components?.list,
711
+ },
712
+ code: {
713
+ ...DEFAULT_COMPONENT_STYLES.code,
714
+ inlineBackgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
715
+ inlineTextColor: theme.colors.accent || theme.colors.primary,
716
+ blockBackgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
717
+ blockTextColor: theme.colors.text,
718
+ blockBorderColor: theme.colors.border,
719
+ ...theme.components?.code,
720
+ },
721
+ card: {
722
+ ...DEFAULT_COMPONENT_STYLES.card,
723
+ backgroundColor: theme.colors.surface,
724
+ borderColor: theme.colors.border,
725
+ shadow: SHADOW_OPTIONS.find(s => s.value === theme.styles?.shadow)?.css || 'none',
726
+ ...theme.components?.card,
727
+ },
728
+ form: {
729
+ ...DEFAULT_COMPONENT_STYLES.form,
730
+ inputBackgroundColor: theme.colors.background,
731
+ inputTextColor: theme.colors.text,
732
+ inputBorderColor: theme.colors.border,
733
+ inputFocusBorderColor: theme.colors.primary,
734
+ inputFocusRingColor: `${theme.colors.primary}33`,
735
+ placeholderColor: theme.colors.textMuted || theme.colors.secondary,
736
+ labelColor: theme.colors.text,
737
+ errorBorderColor: theme.colors.error,
738
+ errorTextColor: theme.colors.error,
739
+ ...theme.components?.form,
740
+ },
741
+ divider: {
742
+ ...DEFAULT_COMPONENT_STYLES.divider,
743
+ color: theme.colors.border,
744
+ ...theme.components?.divider,
745
+ },
746
+ badge: {
747
+ ...DEFAULT_COMPONENT_STYLES.badge,
748
+ backgroundColor: theme.colors.surfaceAlt || theme.colors.surface,
749
+ textColor: theme.colors.text,
750
+ ...theme.components?.badge,
751
+ },
752
+ alert: {
753
+ ...DEFAULT_COMPONENT_STYLES.alert,
754
+ successBackgroundColor: `${theme.colors.success}15`,
755
+ successBorderColor: theme.colors.success,
756
+ successTextColor: theme.colors.success,
757
+ warningBackgroundColor: `${theme.colors.warning}15`,
758
+ warningBorderColor: theme.colors.warning,
759
+ warningTextColor: theme.colors.warning,
760
+ errorBackgroundColor: `${theme.colors.error}15`,
761
+ errorBorderColor: theme.colors.error,
762
+ errorTextColor: theme.colors.error,
763
+ infoBackgroundColor: `${theme.colors.info}15`,
764
+ infoBorderColor: theme.colors.info,
765
+ infoTextColor: theme.colors.info,
766
+ ...theme.components?.alert,
767
+ },
768
+ };
769
+ }
770
+
771
+ /**
772
+ * テーマから完全なタイポグラフィ設定を取得
773
+ * デフォルト値とテーマ値をマージ
774
+ */
775
+ export function getTypography(theme: WebsiteTheme): WebsiteTypography {
776
+ return {
777
+ ...DEFAULT_WEBSITE_TYPOGRAPHY,
778
+ ...theme.typography,
779
+ headings: {
780
+ ...DEFAULT_HEADING_STYLES,
781
+ ...theme.typography?.headings,
782
+ },
783
+ body: {
784
+ ...DEFAULT_BODY_STYLES,
785
+ ...theme.typography?.body,
786
+ },
787
+ };
788
+ }