@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,645 @@
1
+ /**
2
+ * CSS変数システムの型定義
3
+ * FigmaライクなCSS変数(デザイントークン)管理用
4
+ */
5
+
6
+ import { Timestamp } from '../vendor/firebase-firestore';
7
+
8
+ // ============================================
9
+ // 変数カテゴリと基本型
10
+ // ============================================
11
+
12
+ /**
13
+ * CSS変数のカテゴリ
14
+ */
15
+ export type CSSVariableCategory = 'color' | 'spacing' | 'typography' | 'border' | 'shadow' | 'other';
16
+
17
+ /**
18
+ * CSS変数のスコープ(現在はprojectのみ対応)
19
+ */
20
+ export type CSSVariableScope = 'project';
21
+
22
+ /**
23
+ * 数値変数のメタ情報
24
+ */
25
+ export interface NumericMeta {
26
+ unit: 'px' | 'rem' | 'em' | '%' | 'none';
27
+ numericValue: number;
28
+ }
29
+
30
+ // ============================================
31
+ // ブレークポイント対応
32
+ // ============================================
33
+
34
+ /**
35
+ * ブレークポイントID(BREAKPOINT_PRESETSと同期)
36
+ */
37
+ export type BreakpointId = 'default' | 'small' | 'tablet' | 'mobile' | 'mini';
38
+
39
+ /**
40
+ * ブレークポイント固有の値
41
+ */
42
+ export interface BreakpointValue {
43
+ /** ブレークポイントID */
44
+ breakpoint: BreakpointId;
45
+ /** 値 */
46
+ value: string;
47
+ /** 数値メタ情報(オプション) */
48
+ numericMeta?: NumericMeta;
49
+ }
50
+
51
+ /**
52
+ * ブレークポイント設定
53
+ */
54
+ export interface BreakpointConfig {
55
+ id: BreakpointId;
56
+ name: string;
57
+ label: string;
58
+ maxWidth?: number;
59
+ icon: 'Monitor' | 'Tablet' | 'Smartphone' | 'Watch';
60
+ }
61
+
62
+ /**
63
+ * デフォルトのブレークポイント設定
64
+ */
65
+ export const BREAKPOINT_CONFIGS: BreakpointConfig[] = [
66
+ { id: 'default', name: 'Desktop', label: 'デスクトップ', icon: 'Monitor' },
67
+ { id: 'tablet', name: 'Tablet', label: 'タブレット', maxWidth: 1024, icon: 'Tablet' },
68
+ { id: 'mobile', name: 'Mobile', label: 'モバイル', maxWidth: 768, icon: 'Smartphone' },
69
+ ];
70
+
71
+ // ============================================
72
+ // 変数定義
73
+ // ============================================
74
+
75
+ /**
76
+ * CSS変数の定義
77
+ */
78
+ export interface CSSVariableDefinition {
79
+ /** 一意のID */
80
+ id: string;
81
+ /** 表示名(例: "primary") */
82
+ name: string;
83
+ /** CSS変数名(例: "--color-primary") */
84
+ cssName: string;
85
+ /** 値(例: "#3b82f6")- デフォルト(Desktop)の値 */
86
+ value: string;
87
+ /** ブレークポイント固有の値(オプション) */
88
+ breakpointValues?: BreakpointValue[];
89
+ /** カテゴリ */
90
+ category: CSSVariableCategory;
91
+ /** 説明(オプション) */
92
+ description?: string;
93
+ /** 数値メタ情報(スペーシング等の場合) */
94
+ numericMeta?: NumericMeta;
95
+ /** 作成日時 */
96
+ createdAt?: Timestamp | Date;
97
+ /** 更新日時 */
98
+ updatedAt?: Timestamp | Date;
99
+ }
100
+
101
+ /**
102
+ * CSS変数コレクション(プロジェクト単位)
103
+ */
104
+ export interface CSSVariableCollection {
105
+ /** コレクションID */
106
+ id: string;
107
+ /** スコープ */
108
+ scope: CSSVariableScope;
109
+ /** スコープID(websiteId) */
110
+ scopeId: string;
111
+ /** 変数リスト */
112
+ variables: CSSVariableDefinition[];
113
+ /** テーマから継承フラグ */
114
+ syncedFromTheme?: boolean;
115
+ /** 最終同期日時 */
116
+ lastSyncedAt?: Timestamp | Date;
117
+ /** 作成日時 */
118
+ createdAt: Timestamp | Date;
119
+ /** 更新日時 */
120
+ updatedAt: Timestamp | Date;
121
+ }
122
+
123
+ // ============================================
124
+ // 変数グループ(UIでの表示用)
125
+ // ============================================
126
+
127
+ /**
128
+ * カテゴリごとの変数グループ
129
+ */
130
+ export interface CSSVariableGroup {
131
+ category: CSSVariableCategory;
132
+ label: string;
133
+ icon: string;
134
+ variables: CSSVariableDefinition[];
135
+ }
136
+
137
+ // ============================================
138
+ // API リクエスト型
139
+ // ============================================
140
+
141
+ /**
142
+ * 変数作成リクエスト
143
+ */
144
+ export interface CreateCSSVariableRequest {
145
+ name: string;
146
+ value: string;
147
+ category: CSSVariableCategory;
148
+ description?: string;
149
+ }
150
+
151
+ /**
152
+ * 変数更新リクエスト
153
+ */
154
+ export interface UpdateCSSVariableRequest {
155
+ name?: string;
156
+ value?: string;
157
+ category?: CSSVariableCategory;
158
+ description?: string;
159
+ }
160
+
161
+ /**
162
+ * 変数コレクション保存リクエスト
163
+ */
164
+ export interface SaveCSSVariablesRequest {
165
+ variables: CSSVariableDefinition[];
166
+ syncedFromTheme?: boolean;
167
+ }
168
+
169
+ // ============================================
170
+ // カテゴリ定義と設定
171
+ // ============================================
172
+
173
+ /**
174
+ * カテゴリ設定
175
+ */
176
+ export interface CSSVariableCategoryConfig {
177
+ id: CSSVariableCategory;
178
+ label: string;
179
+ labelEn: string;
180
+ icon: string;
181
+ prefix: string;
182
+ defaultUnit?: 'px' | 'rem' | 'em' | '%' | 'none';
183
+ description: string;
184
+ }
185
+
186
+ /**
187
+ * カテゴリ設定リスト
188
+ */
189
+ export const CSS_VARIABLE_CATEGORIES: CSSVariableCategoryConfig[] = [
190
+ {
191
+ id: 'color',
192
+ label: 'カラー',
193
+ labelEn: 'Colors',
194
+ icon: 'Palette',
195
+ prefix: '--color-',
196
+ description: '背景色、テキスト色、ボーダー色など',
197
+ },
198
+ {
199
+ id: 'spacing',
200
+ label: 'スペーシング',
201
+ labelEn: 'Spacing',
202
+ icon: 'Ruler',
203
+ prefix: '--spacing-',
204
+ defaultUnit: 'px',
205
+ description: '余白、パディング、ギャップなど',
206
+ },
207
+ {
208
+ id: 'typography',
209
+ label: 'タイポグラフィ',
210
+ labelEn: 'Typography',
211
+ icon: 'Type',
212
+ prefix: '--font-',
213
+ description: 'フォントサイズ、行間、文字間など',
214
+ },
215
+ {
216
+ id: 'border',
217
+ label: 'ボーダー',
218
+ labelEn: 'Border',
219
+ icon: 'Square',
220
+ prefix: '--border-',
221
+ defaultUnit: 'px',
222
+ description: 'ボーダー幅、角丸など',
223
+ },
224
+ {
225
+ id: 'shadow',
226
+ label: 'シャドウ',
227
+ labelEn: 'Shadow',
228
+ icon: 'Layers',
229
+ prefix: '--shadow-',
230
+ description: 'ボックスシャドウ、テキストシャドウなど',
231
+ },
232
+ {
233
+ id: 'other',
234
+ label: 'その他',
235
+ labelEn: 'Other',
236
+ icon: 'Settings',
237
+ prefix: '--',
238
+ description: 'その他のカスタムプロパティ',
239
+ },
240
+ ];
241
+
242
+ /**
243
+ * カテゴリIDからカテゴリ設定を取得
244
+ */
245
+ export function getCategoryConfig(category: CSSVariableCategory): CSSVariableCategoryConfig {
246
+ return CSS_VARIABLE_CATEGORIES.find(c => c.id === category) ?? CSS_VARIABLE_CATEGORIES[5]; // fallback to 'other'
247
+ }
248
+
249
+ // ============================================
250
+ // ヘルパー関数
251
+ // ============================================
252
+
253
+ /**
254
+ * 変数名からCSS変数名を生成
255
+ */
256
+ export function generateCSSName(name: string, category: CSSVariableCategory): string {
257
+ const config = getCategoryConfig(category);
258
+ const safeName = name
259
+ .toLowerCase()
260
+ .replace(/[^a-z0-9-]/g, '-')
261
+ .replace(/-+/g, '-')
262
+ .replace(/^-|-$/g, '');
263
+ return `${config.prefix}${safeName}`;
264
+ }
265
+
266
+ /**
267
+ * 新しい変数IDを生成
268
+ */
269
+ export function generateVariableId(): string {
270
+ return `var-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
271
+ }
272
+
273
+ /**
274
+ * 変数をカテゴリごとにグループ化
275
+ */
276
+ export function groupVariablesByCategory(variables: CSSVariableDefinition[]): CSSVariableGroup[] {
277
+ return CSS_VARIABLE_CATEGORIES.map(config => ({
278
+ category: config.id,
279
+ label: config.label,
280
+ icon: config.icon,
281
+ variables: variables.filter(v => v.category === config.id),
282
+ })).filter(group => group.variables.length > 0);
283
+ }
284
+
285
+ /**
286
+ * 変数コレクションからCSS文字列を生成
287
+ */
288
+ export function generateCSSFromVariables(variables: CSSVariableDefinition[]): string {
289
+ if (variables.length === 0) return '';
290
+
291
+ const lines = variables.map(v => ` ${v.cssName}: ${v.value};`);
292
+ return `:root {\n${lines.join('\n')}\n}`;
293
+ }
294
+
295
+ /**
296
+ * ブレークポイント対応のCSS変数を生成
297
+ */
298
+ export function generateResponsiveCSSFromVariables(variables: CSSVariableDefinition[]): string {
299
+ if (variables.length === 0) return '';
300
+
301
+ // ベース(Desktop)スタイル
302
+ const baseLines = variables.map(v => ` ${v.cssName}: ${v.value};`);
303
+ let css = `:root {\n${baseLines.join('\n')}\n}`;
304
+
305
+ // ブレークポイント別のスタイル
306
+ for (const bp of BREAKPOINT_CONFIGS) {
307
+ if (bp.id === 'default' || !bp.maxWidth) continue;
308
+
309
+ const bpLines: string[] = [];
310
+ for (const v of variables) {
311
+ const bpValue = v.breakpointValues?.find(bv => bv.breakpoint === bp.id);
312
+ if (bpValue) {
313
+ bpLines.push(` ${v.cssName}: ${bpValue.value};`);
314
+ }
315
+ }
316
+
317
+ if (bpLines.length > 0) {
318
+ css += `\n\n@media (max-width: ${bp.maxWidth}px) {\n :root {\n${bpLines.join('\n')}\n }\n}`;
319
+ }
320
+ }
321
+
322
+ return css;
323
+ }
324
+
325
+ /**
326
+ * 特定のブレークポイントの値を取得
327
+ */
328
+ export function getValueForBreakpoint(
329
+ variable: CSSVariableDefinition,
330
+ breakpoint: BreakpointId
331
+ ): string {
332
+ if (breakpoint === 'default') return variable.value;
333
+ const bpValue = variable.breakpointValues?.find(v => v.breakpoint === breakpoint);
334
+ return bpValue?.value ?? variable.value;
335
+ }
336
+
337
+ /**
338
+ * 特定のブレークポイントに値を設定した新しい変数を返す
339
+ */
340
+ export function setValueForBreakpoint(
341
+ variable: CSSVariableDefinition,
342
+ breakpoint: BreakpointId,
343
+ value: string
344
+ ): CSSVariableDefinition {
345
+ if (breakpoint === 'default') {
346
+ return { ...variable, value };
347
+ }
348
+
349
+ const existingBpValues = variable.breakpointValues ?? [];
350
+ const existingIndex = existingBpValues.findIndex(v => v.breakpoint === breakpoint);
351
+
352
+ const newBpValues = [...existingBpValues];
353
+ if (existingIndex >= 0) {
354
+ // 既存のブレークポイント値を更新(値がデフォルトと同じ場合は削除)
355
+ if (value === variable.value) {
356
+ newBpValues.splice(existingIndex, 1);
357
+ } else {
358
+ newBpValues[existingIndex] = { breakpoint, value };
359
+ }
360
+ } else if (value !== variable.value) {
361
+ // 新しいブレークポイント値を追加
362
+ newBpValues.push({ breakpoint, value });
363
+ }
364
+
365
+ return {
366
+ ...variable,
367
+ breakpointValues: newBpValues.length > 0 ? newBpValues : undefined,
368
+ };
369
+ }
370
+
371
+ /**
372
+ * CSS変数参照値を生成
373
+ */
374
+ export function generateVarReference(variable: CSSVariableDefinition): string {
375
+ return `var(${variable.cssName})`;
376
+ }
377
+
378
+ /**
379
+ * 値がCSS変数参照かどうかをチェック
380
+ */
381
+ export function isVariableReference(value: string): boolean {
382
+ return /^var\(--[a-z0-9-]+\)$/i.test(value);
383
+ }
384
+
385
+ /**
386
+ * CSS変数参照から変数名を抽出
387
+ */
388
+ export function extractVariableName(varReference: string): string | null {
389
+ const match = varReference.match(/^var\((--[a-z0-9-]+)\)$/i);
390
+ return match ? match[1] : null;
391
+ }
392
+
393
+ // ============================================
394
+ // デフォルト変数セット
395
+ // ============================================
396
+
397
+ /**
398
+ * デフォルトのカラー変数
399
+ */
400
+ export const DEFAULT_COLOR_VARIABLES: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>[] = [
401
+ {
402
+ name: 'primary',
403
+ cssName: '--color-primary',
404
+ value: '#3b82f6',
405
+ category: 'color',
406
+ description: 'プライマリカラー',
407
+ },
408
+ {
409
+ name: 'secondary',
410
+ cssName: '--color-secondary',
411
+ value: '#6b7280',
412
+ category: 'color',
413
+ description: 'セカンダリカラー',
414
+ },
415
+ {
416
+ name: 'accent',
417
+ cssName: '--color-accent',
418
+ value: '#2563eb',
419
+ category: 'color',
420
+ description: 'アクセントカラー',
421
+ },
422
+ {
423
+ name: 'background',
424
+ cssName: '--color-background',
425
+ value: '#ffffff',
426
+ category: 'color',
427
+ description: '背景色',
428
+ },
429
+ {
430
+ name: 'text',
431
+ cssName: '--color-text',
432
+ value: '#1f2937',
433
+ category: 'color',
434
+ description: 'テキスト色',
435
+ },
436
+ {
437
+ name: 'text-muted',
438
+ cssName: '--color-text-muted',
439
+ value: '#6b7280',
440
+ category: 'color',
441
+ description: '薄いテキスト色',
442
+ },
443
+ {
444
+ name: 'surface',
445
+ cssName: '--color-surface',
446
+ value: '#f9fafb',
447
+ category: 'color',
448
+ description: 'サーフェス色',
449
+ },
450
+ {
451
+ name: 'border',
452
+ cssName: '--color-border',
453
+ value: '#e5e7eb',
454
+ category: 'color',
455
+ description: 'ボーダー色',
456
+ },
457
+ ];
458
+
459
+ /**
460
+ * デフォルトのスペーシング変数
461
+ */
462
+ export const DEFAULT_SPACING_VARIABLES: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>[] = [
463
+ {
464
+ name: 'xs',
465
+ cssName: '--spacing-xs',
466
+ value: '4px',
467
+ category: 'spacing',
468
+ description: '極小スペース',
469
+ numericMeta: { unit: 'px', numericValue: 4 },
470
+ },
471
+ {
472
+ name: 'sm',
473
+ cssName: '--spacing-sm',
474
+ value: '8px',
475
+ category: 'spacing',
476
+ description: '小スペース',
477
+ numericMeta: { unit: 'px', numericValue: 8 },
478
+ },
479
+ {
480
+ name: 'md',
481
+ cssName: '--spacing-md',
482
+ value: '16px',
483
+ category: 'spacing',
484
+ description: '中スペース',
485
+ numericMeta: { unit: 'px', numericValue: 16 },
486
+ },
487
+ {
488
+ name: 'lg',
489
+ cssName: '--spacing-lg',
490
+ value: '24px',
491
+ category: 'spacing',
492
+ description: '大スペース',
493
+ numericMeta: { unit: 'px', numericValue: 24 },
494
+ },
495
+ {
496
+ name: 'xl',
497
+ cssName: '--spacing-xl',
498
+ value: '32px',
499
+ category: 'spacing',
500
+ description: '特大スペース',
501
+ numericMeta: { unit: 'px', numericValue: 32 },
502
+ },
503
+ ];
504
+
505
+ /**
506
+ * デフォルトのタイポグラフィ変数
507
+ */
508
+ export const DEFAULT_TYPOGRAPHY_VARIABLES: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>[] = [
509
+ {
510
+ name: 'size-xs',
511
+ cssName: '--font-size-xs',
512
+ value: '12px',
513
+ category: 'typography',
514
+ description: '極小フォント',
515
+ numericMeta: { unit: 'px', numericValue: 12 },
516
+ },
517
+ {
518
+ name: 'size-sm',
519
+ cssName: '--font-size-sm',
520
+ value: '14px',
521
+ category: 'typography',
522
+ description: '小フォント',
523
+ numericMeta: { unit: 'px', numericValue: 14 },
524
+ },
525
+ {
526
+ name: 'size-base',
527
+ cssName: '--font-size-base',
528
+ value: '16px',
529
+ category: 'typography',
530
+ description: '基本フォント',
531
+ numericMeta: { unit: 'px', numericValue: 16 },
532
+ },
533
+ {
534
+ name: 'size-lg',
535
+ cssName: '--font-size-lg',
536
+ value: '18px',
537
+ category: 'typography',
538
+ description: '大フォント',
539
+ numericMeta: { unit: 'px', numericValue: 18 },
540
+ },
541
+ {
542
+ name: 'size-xl',
543
+ cssName: '--font-size-xl',
544
+ value: '20px',
545
+ category: 'typography',
546
+ description: '特大フォント',
547
+ numericMeta: { unit: 'px', numericValue: 20 },
548
+ },
549
+ {
550
+ name: 'size-2xl',
551
+ cssName: '--font-size-2xl',
552
+ value: '24px',
553
+ category: 'typography',
554
+ description: '見出し大',
555
+ numericMeta: { unit: 'px', numericValue: 24 },
556
+ },
557
+ ];
558
+
559
+ /**
560
+ * デフォルトのボーダー変数
561
+ */
562
+ export const DEFAULT_BORDER_VARIABLES: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>[] = [
563
+ {
564
+ name: 'radius-sm',
565
+ cssName: '--border-radius-sm',
566
+ value: '4px',
567
+ category: 'border',
568
+ description: '小角丸',
569
+ numericMeta: { unit: 'px', numericValue: 4 },
570
+ },
571
+ {
572
+ name: 'radius-md',
573
+ cssName: '--border-radius-md',
574
+ value: '8px',
575
+ category: 'border',
576
+ description: '中角丸',
577
+ numericMeta: { unit: 'px', numericValue: 8 },
578
+ },
579
+ {
580
+ name: 'radius-lg',
581
+ cssName: '--border-radius-lg',
582
+ value: '16px',
583
+ category: 'border',
584
+ description: '大角丸',
585
+ numericMeta: { unit: 'px', numericValue: 16 },
586
+ },
587
+ {
588
+ name: 'radius-full',
589
+ cssName: '--border-radius-full',
590
+ value: '9999px',
591
+ category: 'border',
592
+ description: '完全丸',
593
+ numericMeta: { unit: 'px', numericValue: 9999 },
594
+ },
595
+ ];
596
+
597
+ /**
598
+ * デフォルトのシャドウ変数
599
+ */
600
+ export const DEFAULT_SHADOW_VARIABLES: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>[] = [
601
+ {
602
+ name: 'sm',
603
+ cssName: '--shadow-sm',
604
+ value: '0 1px 2px rgba(0,0,0,0.05)',
605
+ category: 'shadow',
606
+ description: '小シャドウ',
607
+ },
608
+ {
609
+ name: 'md',
610
+ cssName: '--shadow-md',
611
+ value: '0 4px 6px rgba(0,0,0,0.1)',
612
+ category: 'shadow',
613
+ description: '中シャドウ',
614
+ },
615
+ {
616
+ name: 'lg',
617
+ cssName: '--shadow-lg',
618
+ value: '0 10px 15px rgba(0,0,0,0.15)',
619
+ category: 'shadow',
620
+ description: '大シャドウ',
621
+ },
622
+ ];
623
+
624
+ /**
625
+ * 全デフォルト変数を統合
626
+ */
627
+ export function getDefaultVariables(): CSSVariableDefinition[] {
628
+ const now = new Date();
629
+ let index = 0;
630
+
631
+ const createVar = (def: Omit<CSSVariableDefinition, 'id' | 'createdAt' | 'updatedAt'>): CSSVariableDefinition => ({
632
+ ...def,
633
+ id: `default-var-${index++}`,
634
+ createdAt: now,
635
+ updatedAt: now,
636
+ });
637
+
638
+ return [
639
+ ...DEFAULT_COLOR_VARIABLES.map(createVar),
640
+ ...DEFAULT_SPACING_VARIABLES.map(createVar),
641
+ ...DEFAULT_TYPOGRAPHY_VARIABLES.map(createVar),
642
+ ...DEFAULT_BORDER_VARIABLES.map(createVar),
643
+ ...DEFAULT_SHADOW_VARIABLES.map(createVar),
644
+ ];
645
+ }