@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,204 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * EditorRefsContext
5
+ *
6
+ * エディタのRef関連を管理するContext
7
+ * 変更頻度: 極低(初期化後は変更なし)
8
+ *
9
+ * 含まれる状態:
10
+ * - iframeRef: iframeのRef
11
+ * - containerRef: コンテナのRef
12
+ * - clipboardRef: クリップボードデータのRef
13
+ * - styleClipboardRef: スタイルクリップボードのRef
14
+ * - iframeHtmlRef: iframeのHTML状態のRef
15
+ * - isUndoRedoRef: Undo/Redo実行中フラグ
16
+ * - drawingStateRef: 描画状態のRef
17
+ * - getIframeDoc: iframeドキュメント取得ヘルパー
18
+ */
19
+
20
+ import React, { createContext, useContext, useRef, useCallback, useState, MutableRefObject } from 'react';
21
+ import type { ClipboardData, DrawingState, StyleClipboard } from '../types';
22
+
23
+ // スタイルクリップボードをモジュールレベルで保持(スライド間で共有するため)
24
+ let globalStyleClipboard: StyleClipboard | null = null;
25
+
26
+ // グローバルスタイルクリップボードへのRef-likeアクセサ
27
+ export const globalStyleClipboardRef = {
28
+ get current() {
29
+ return globalStyleClipboard;
30
+ },
31
+ set current(value: StyleClipboard | null) {
32
+ globalStyleClipboard = value;
33
+ },
34
+ };
35
+
36
+ /**
37
+ * 最後に使用したスタイル(Figmaスタイル継承用)
38
+ * 要素タイプごとにスタイルを保持
39
+ */
40
+ export interface LastUsedStyles {
41
+ // 図形(rectangle, ellipse, frame)用
42
+ shape: {
43
+ backgroundColor: string;
44
+ borderRadius: string;
45
+ borderColor: string;
46
+ borderWidth: string;
47
+ borderStyle: string;
48
+ opacity: string;
49
+ };
50
+ // テキスト用
51
+ text: {
52
+ color: string;
53
+ fontSize: string;
54
+ fontFamily: string;
55
+ fontWeight: string;
56
+ lineHeight: string;
57
+ letterSpacing: string;
58
+ textAlign: string;
59
+ };
60
+ // 線・矢印用
61
+ line: {
62
+ stroke: string;
63
+ strokeWidth: string;
64
+ };
65
+ }
66
+
67
+ // デフォルトのスタイル
68
+ const defaultLastUsedStyles: LastUsedStyles = {
69
+ shape: {
70
+ backgroundColor: '#3B82F6',
71
+ borderRadius: '4px',
72
+ borderColor: 'transparent',
73
+ borderWidth: '0',
74
+ borderStyle: 'solid',
75
+ opacity: '1',
76
+ },
77
+ text: {
78
+ color: '#1F2937',
79
+ fontSize: '16px',
80
+ fontFamily: 'inherit',
81
+ fontWeight: '400',
82
+ lineHeight: '1.5',
83
+ letterSpacing: '0',
84
+ textAlign: 'left',
85
+ },
86
+ line: {
87
+ stroke: '#1F2937',
88
+ strokeWidth: '2',
89
+ },
90
+ };
91
+
92
+ // 最後に使用したスタイルをモジュールレベルで保持
93
+ let globalLastUsedStyles: LastUsedStyles = { ...defaultLastUsedStyles };
94
+
95
+ // グローバル最後使用スタイルへのRef-likeアクセサ
96
+ export const globalLastUsedStylesRef = {
97
+ get current() {
98
+ return globalLastUsedStyles;
99
+ },
100
+ set current(value: LastUsedStyles) {
101
+ globalLastUsedStyles = value;
102
+ },
103
+ // 部分更新用ヘルパー
104
+ updateShape(styles: Partial<LastUsedStyles['shape']>) {
105
+ globalLastUsedStyles = {
106
+ ...globalLastUsedStyles,
107
+ shape: { ...globalLastUsedStyles.shape, ...styles },
108
+ };
109
+ },
110
+ updateText(styles: Partial<LastUsedStyles['text']>) {
111
+ globalLastUsedStyles = {
112
+ ...globalLastUsedStyles,
113
+ text: { ...globalLastUsedStyles.text, ...styles },
114
+ };
115
+ },
116
+ updateLine(styles: Partial<LastUsedStyles['line']>) {
117
+ globalLastUsedStyles = {
118
+ ...globalLastUsedStyles,
119
+ line: { ...globalLastUsedStyles.line, ...styles },
120
+ };
121
+ },
122
+ };
123
+
124
+ export interface EditorRefsContextValue {
125
+ iframeRef: MutableRefObject<HTMLIFrameElement | null>;
126
+ containerRef: MutableRefObject<HTMLDivElement | null>;
127
+ clipboardRef: MutableRefObject<ClipboardData | null>;
128
+ styleClipboardRef: typeof globalStyleClipboardRef;
129
+ lastUsedStylesRef: typeof globalLastUsedStylesRef;
130
+ iframeHtmlRef: MutableRefObject<string>;
131
+ isUndoRedoRef: MutableRefObject<boolean>;
132
+ drawingStateRef: MutableRefObject<DrawingState>;
133
+ getIframeDoc: () => Document | null;
134
+ /** iframeが読み込み完了したかどうか */
135
+ iframeReady: boolean;
136
+ /** iframeの読み込み完了状態をセット */
137
+ setIframeReady: (ready: boolean) => void;
138
+ }
139
+
140
+ const EditorRefsContext = createContext<EditorRefsContextValue | null>(null);
141
+
142
+ export function useEditorRefs(): EditorRefsContextValue {
143
+ const context = useContext(EditorRefsContext);
144
+ if (!context) {
145
+ throw new Error('useEditorRefs must be used within EditorRefsProvider');
146
+ }
147
+ return context;
148
+ }
149
+
150
+ interface EditorRefsProviderProps {
151
+ initialHtml: string;
152
+ children: React.ReactNode;
153
+ }
154
+
155
+ export function EditorRefsProvider({
156
+ initialHtml,
157
+ children,
158
+ }: EditorRefsProviderProps) {
159
+ // Refs
160
+ const iframeRef = useRef<HTMLIFrameElement | null>(null);
161
+ const containerRef = useRef<HTMLDivElement | null>(null);
162
+ const clipboardRef = useRef<ClipboardData | null>(null);
163
+ const styleClipboardRef = globalStyleClipboardRef;
164
+ const iframeHtmlRef = useRef<string>(initialHtml);
165
+ const isUndoRedoRef = useRef<boolean>(false);
166
+ const drawingStateRef = useRef<DrawingState>({
167
+ isDrawing: false,
168
+ startX: 0,
169
+ startY: 0,
170
+ currentX: 0,
171
+ currentY: 0,
172
+ previewElement: null,
173
+ points: [],
174
+ });
175
+
176
+ // iframeの読み込み完了状態
177
+ const [iframeReady, setIframeReady] = useState(false);
178
+
179
+ // iframeドキュメント取得
180
+ const getIframeDoc = useCallback(() => {
181
+ const iframe = iframeRef.current;
182
+ return iframe?.contentDocument || iframe?.contentWindow?.document || null;
183
+ }, []);
184
+
185
+ const value: EditorRefsContextValue = {
186
+ iframeRef,
187
+ containerRef,
188
+ clipboardRef,
189
+ styleClipboardRef,
190
+ lastUsedStylesRef: globalLastUsedStylesRef,
191
+ iframeHtmlRef,
192
+ isUndoRedoRef,
193
+ drawingStateRef,
194
+ getIframeDoc,
195
+ iframeReady,
196
+ setIframeReady,
197
+ };
198
+
199
+ return (
200
+ <EditorRefsContext.Provider value={value}>
201
+ {children}
202
+ </EditorRefsContext.Provider>
203
+ );
204
+ }
@@ -0,0 +1,54 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * EditorSelectionContext
5
+ *
6
+ * エディタの選択状態を管理するContext
7
+ * 変更頻度: 高(ユーザー操作で頻繁に変更)
8
+ *
9
+ * 含まれる状態:
10
+ * - selectedElement: 選択された要素の詳細情報
11
+ * - selectedElementIds: 選択された要素のID配列(複数選択対応)
12
+ */
13
+
14
+ import React, { createContext, useContext, useState } from 'react';
15
+ import type { SelectedElementInfo } from '../types';
16
+
17
+ export interface EditorSelectionContextValue {
18
+ selectedElement: SelectedElementInfo | null;
19
+ setSelectedElement: (element: SelectedElementInfo | null) => void;
20
+ selectedElementIds: string[];
21
+ setSelectedElementIds: (ids: string[]) => void;
22
+ }
23
+
24
+ const EditorSelectionContext = createContext<EditorSelectionContextValue | null>(null);
25
+
26
+ export function useEditorSelection(): EditorSelectionContextValue {
27
+ const context = useContext(EditorSelectionContext);
28
+ if (!context) {
29
+ throw new Error('useEditorSelection must be used within EditorSelectionProvider');
30
+ }
31
+ return context;
32
+ }
33
+
34
+ interface EditorSelectionProviderProps {
35
+ children: React.ReactNode;
36
+ }
37
+
38
+ export function EditorSelectionProvider({ children }: EditorSelectionProviderProps) {
39
+ const [selectedElement, setSelectedElement] = useState<SelectedElementInfo | null>(null);
40
+ const [selectedElementIds, setSelectedElementIds] = useState<string[]>([]);
41
+
42
+ const value: EditorSelectionContextValue = {
43
+ selectedElement,
44
+ setSelectedElement,
45
+ selectedElementIds,
46
+ setSelectedElementIds,
47
+ };
48
+
49
+ return (
50
+ <EditorSelectionContext.Provider value={value}>
51
+ {children}
52
+ </EditorSelectionContext.Provider>
53
+ );
54
+ }
@@ -0,0 +1,58 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * EditorToolContext
5
+ *
6
+ * エディタのツール状態を管理するContext
7
+ * 変更頻度: 低(ツール切り替え時のみ)
8
+ *
9
+ * 含まれる状態:
10
+ * - activeTool: 現在選択されているツール
11
+ * - editorMode: エディタモード(slide/webpage)
12
+ */
13
+
14
+ import React, { createContext, useContext, useState } from 'react';
15
+ import type { EditorTool } from '../types';
16
+
17
+ /** エディタモード: スライド(16:9固定)またはWebページ(可変高さ) */
18
+ export type EditorMode = 'slide' | 'webpage';
19
+
20
+ export interface EditorToolContextValue {
21
+ activeTool: EditorTool;
22
+ setActiveTool: (tool: EditorTool) => void;
23
+ editorMode: EditorMode;
24
+ }
25
+
26
+ const EditorToolContext = createContext<EditorToolContextValue | null>(null);
27
+
28
+ export function useEditorTool(): EditorToolContextValue {
29
+ const context = useContext(EditorToolContext);
30
+ if (!context) {
31
+ throw new Error('useEditorTool must be used within EditorToolProvider');
32
+ }
33
+ return context;
34
+ }
35
+
36
+ interface EditorToolProviderProps {
37
+ editorMode?: EditorMode;
38
+ children: React.ReactNode;
39
+ }
40
+
41
+ export function EditorToolProvider({
42
+ editorMode = 'slide',
43
+ children,
44
+ }: EditorToolProviderProps) {
45
+ const [activeTool, setActiveTool] = useState<EditorTool>('select');
46
+
47
+ const value: EditorToolContextValue = {
48
+ activeTool,
49
+ setActiveTool,
50
+ editorMode,
51
+ };
52
+
53
+ return (
54
+ <EditorToolContext.Provider value={value}>
55
+ {children}
56
+ </EditorToolContext.Provider>
57
+ );
58
+ }
@@ -0,0 +1,122 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * EditorUIStateContext
5
+ *
6
+ * エディタのUI状態を管理するContext
7
+ * 変更頻度: 中〜高(DOMツリー、パネル状態、マーキー等)
8
+ *
9
+ * 含まれる状態:
10
+ * - domTree: DOMツリー構造
11
+ * - searchQuery: レイヤー検索クエリ
12
+ * - expandedNodes: 展開されたノードのSet
13
+ * - openSections: プロパティパネルのセクション開閉状態
14
+ * - marqueeState: マーキー選択状態
15
+ * - restoreFocus: フォーカス復元関数
16
+ */
17
+
18
+ import React, { createContext, useContext, useState, useCallback } from 'react';
19
+ import type { DOMTreeNode, PanelSections, MarqueeState } from '../types';
20
+ import { DEFAULT_PANEL_SECTIONS } from '../constants';
21
+
22
+ export interface EditorUIStateContextValue {
23
+ // DOMツリー
24
+ domTree: DOMTreeNode[];
25
+ setDomTree: (tree: DOMTreeNode[]) => void;
26
+ searchQuery: string;
27
+ setSearchQuery: (query: string) => void;
28
+ expandedNodes: Set<string>;
29
+ setExpandedNodes: React.Dispatch<React.SetStateAction<Set<string>>>;
30
+
31
+ // パネル状態
32
+ openSections: PanelSections;
33
+ setOpenSections: React.Dispatch<React.SetStateAction<PanelSections>>;
34
+
35
+ // マーキー選択
36
+ marqueeState: MarqueeState;
37
+ setMarqueeState: React.Dispatch<React.SetStateAction<MarqueeState>>;
38
+
39
+ // フォーカス管理
40
+ restoreFocus: () => void;
41
+ }
42
+
43
+ const EditorUIStateContext = createContext<EditorUIStateContextValue | null>(null);
44
+
45
+ export function useEditorUIState(): EditorUIStateContextValue {
46
+ const context = useContext(EditorUIStateContext);
47
+ if (!context) {
48
+ throw new Error('useEditorUIState must be used within EditorUIStateProvider');
49
+ }
50
+ return context;
51
+ }
52
+
53
+ interface EditorUIStateProviderProps {
54
+ // フォーカス復元用のgetIframeDoc関数
55
+ getIframeDoc: () => Document | null;
56
+ children: React.ReactNode;
57
+ }
58
+
59
+ export function EditorUIStateProvider({
60
+ getIframeDoc,
61
+ children,
62
+ }: EditorUIStateProviderProps) {
63
+ // DOMツリー
64
+ const [domTree, setDomTree] = useState<DOMTreeNode[]>([]);
65
+ const [searchQuery, setSearchQuery] = useState('');
66
+ const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());
67
+
68
+ // パネル状態
69
+ const [openSections, setOpenSections] = useState<PanelSections>(DEFAULT_PANEL_SECTIONS);
70
+
71
+ // マーキー選択状態
72
+ const [marqueeState, setMarqueeState] = useState<MarqueeState>({
73
+ isActive: false,
74
+ startX: 0,
75
+ startY: 0,
76
+ currentX: 0,
77
+ currentY: 0,
78
+ });
79
+
80
+ // フォーカス復元(ショートカットが効かなくなる問題対策)
81
+ const restoreFocus = useCallback(() => {
82
+ const iframeDoc = getIframeDoc();
83
+ if (!iframeDoc) {
84
+ console.log('[EditorUIStateContext] restoreFocus: iframe doc not available');
85
+ return;
86
+ }
87
+
88
+ // テキスト編集中の要素があればそこにフォーカス
89
+ const editingElement = iframeDoc.querySelector('[contenteditable="true"]') as HTMLElement;
90
+ if (editingElement) {
91
+ editingElement.focus();
92
+ console.log('[EditorUIStateContext] restoreFocus: focused editing element');
93
+ return;
94
+ }
95
+
96
+ // iframeのbodyにフォーカスを設定
97
+ if (iframeDoc.body) {
98
+ iframeDoc.body.focus();
99
+ console.log('[EditorUIStateContext] restoreFocus: focused iframe body');
100
+ }
101
+ }, [getIframeDoc]);
102
+
103
+ const value: EditorUIStateContextValue = {
104
+ domTree,
105
+ setDomTree,
106
+ searchQuery,
107
+ setSearchQuery,
108
+ expandedNodes,
109
+ setExpandedNodes,
110
+ openSections,
111
+ setOpenSections,
112
+ marqueeState,
113
+ setMarqueeState,
114
+ restoreFocus,
115
+ };
116
+
117
+ return (
118
+ <EditorUIStateContext.Provider value={value}>
119
+ {children}
120
+ </EditorUIStateContext.Provider>
121
+ );
122
+ }