@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.
- package/LICENSE +21 -0
- package/NOTICE +52 -0
- package/README.md +143 -0
- package/dist/editor.css +2 -0
- package/package.json +94 -0
- package/src/components/DeckSlideRender.tsx +21 -0
- package/src/components/SaveNote.tsx +21 -0
- package/src/components/auth/AuthProvider.tsx +44 -0
- package/src/components/ui/accordion.tsx +57 -0
- package/src/components/ui/alert-dialog.tsx +141 -0
- package/src/components/ui/badge.tsx +36 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/card.tsx +76 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/collapsible.tsx +11 -0
- package/src/components/ui/context-menu.tsx +200 -0
- package/src/components/ui/dialog.tsx +122 -0
- package/src/components/ui/dropdown-menu.tsx +201 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/popover.tsx +33 -0
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/scrubbable-label.tsx +95 -0
- package/src/components/ui/select.tsx +159 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/slider.tsx +28 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/tabs.tsx +55 -0
- package/src/components/ui/textarea.tsx +22 -0
- package/src/components/ui/tooltip.tsx +32 -0
- package/src/components/viewer/useDeck.ts +58 -0
- package/src/editor/EditorContext.tsx +632 -0
- package/src/editor/EditorToolbar.tsx +446 -0
- package/src/editor/FrontendVisualEditor.tsx +2595 -0
- package/src/editor/autosave.ts +34 -0
- package/src/editor/components/AiPromptPopover.tsx +378 -0
- package/src/editor/components/BreakpointGuides.tsx +323 -0
- package/src/editor/components/BreakpointSelector.tsx +180 -0
- package/src/editor/components/ComponentPropertyEditor.tsx +426 -0
- package/src/editor/components/CssEditorDialog.tsx +168 -0
- package/src/editor/components/EditorCanvas.tsx +987 -0
- package/src/editor/components/EditorContextMenu.tsx +515 -0
- package/src/editor/components/EditorFooter.tsx +81 -0
- package/src/editor/components/EditorHeader.tsx +524 -0
- package/src/editor/components/EditorLayerPanel.tsx +1197 -0
- package/src/editor/components/EditorPropertyPanel.tsx +2996 -0
- package/src/editor/components/EditorSidebar.tsx +226 -0
- package/src/editor/components/FigmaColorPicker.tsx +1577 -0
- package/src/editor/components/HtmlEditorDialog.tsx +71 -0
- package/src/editor/components/HtmlImportDialog.tsx +346 -0
- package/src/editor/components/JsEditorDialog.tsx +175 -0
- package/src/editor/components/LayerTreeItem.tsx +494 -0
- package/src/editor/components/MasterComponentEditor.tsx +846 -0
- package/src/editor/components/MediaLibraryDialog.tsx +447 -0
- package/src/editor/components/PageSettingsDialog.tsx +776 -0
- package/src/editor/components/VariablePicker.tsx +355 -0
- package/src/editor/components/VariablesDialog.tsx +564 -0
- package/src/editor/components/VariantEditor.tsx +687 -0
- package/src/editor/components/VariantMatrix.tsx +507 -0
- package/src/editor/components/component-panel/CategoryAccordion.tsx +139 -0
- package/src/editor/components/component-panel/ComponentGrid.tsx +51 -0
- package/src/editor/components/component-panel/ComponentItem.tsx +368 -0
- package/src/editor/components/component-panel/ComponentPanel.tsx +275 -0
- package/src/editor/components/component-panel/ComponentSearch.tsx +82 -0
- package/src/editor/components/component-panel/VariantList.tsx +260 -0
- package/src/editor/components/component-panel/index.ts +12 -0
- package/src/editor/components/index.ts +48 -0
- package/src/editor/components/multi-page/CanvasZoomControls.tsx +71 -0
- package/src/editor/components/multi-page/InfiniteCanvas.tsx +95 -0
- package/src/editor/components/multi-page/MultiPageCanvasView.tsx +1404 -0
- package/src/editor/components/multi-page/PageFrameOverlay.tsx +76 -0
- package/src/editor/components/multi-page/PageLabel.tsx +34 -0
- package/src/editor/components/multi-page/PageLivePreview.tsx +242 -0
- package/src/editor/components/multi-page/PageThumbnail.tsx +59 -0
- package/src/editor/components/multi-page/index.ts +7 -0
- package/src/editor/components/ppt/PptChrome.tsx +2508 -0
- package/src/editor/components/ppt/PptComments.tsx +589 -0
- package/src/editor/components/ppt/PptDesignProposals.tsx +275 -0
- package/src/editor/components/ppt/PptFormatPane.tsx +320 -0
- package/src/editor/components/ppt/PptNotes.tsx +246 -0
- package/src/editor/components/property-panel/AlignmentPanel.tsx +110 -0
- package/src/editor/components/property-panel/AutoLayoutPanel.tsx +615 -0
- package/src/editor/components/property-panel/BorderSection.tsx +104 -0
- package/src/editor/components/property-panel/CompactNumberInput.tsx +237 -0
- package/src/editor/components/property-panel/CompactSizeInput.tsx +148 -0
- package/src/editor/components/property-panel/EffectSection.tsx +157 -0
- package/src/editor/components/property-panel/FillSection.tsx +69 -0
- package/src/editor/components/property-panel/GoogleFontPicker.tsx +192 -0
- package/src/editor/components/property-panel/ImageSection.tsx +206 -0
- package/src/editor/components/property-panel/ImgSrcSection.tsx +125 -0
- package/src/editor/components/property-panel/InstanceOverrideSection.tsx +413 -0
- package/src/editor/components/property-panel/LayoutSection.tsx +105 -0
- package/src/editor/components/property-panel/LinkSection.tsx +103 -0
- package/src/editor/components/property-panel/PropertyVariablePicker.tsx +311 -0
- package/src/editor/components/property-panel/ScalePanel.tsx +212 -0
- package/src/editor/components/property-panel/TypographySection.tsx +230 -0
- package/src/editor/components/property-panel/UnitAwareNumberInput.tsx +238 -0
- package/src/editor/components/property-panel/VariableAwareColorInput.tsx +477 -0
- package/src/editor/components/property-panel/VariableAwareInput.tsx +606 -0
- package/src/editor/components/property-panel/VariableAwareSizeInput.tsx +588 -0
- package/src/editor/components/property-panel/VariableAwareUnitInput.tsx +546 -0
- package/src/editor/components/property-panel/index.ts +24 -0
- package/src/editor/components/property-panel/unit-utils.ts +261 -0
- package/src/editor/components/shell/EditorTopBar.tsx +392 -0
- package/src/editor/components/shell/LeftPanel.tsx +47 -0
- package/src/editor/components/shell/PagesPanel.tsx +118 -0
- package/src/editor/components/variables-panel/ColorValueCell.tsx +165 -0
- package/src/editor/components/variables-panel/TextValueCell.tsx +116 -0
- package/src/editor/components/variables-panel/VariablesPanel.tsx +518 -0
- package/src/editor/components/variables-panel/index.ts +7 -0
- package/src/editor/constants.ts +468 -0
- package/src/editor/contexts/EditorArtboardContext.tsx +229 -0
- package/src/editor/contexts/EditorComponentsContext.tsx +1320 -0
- package/src/editor/contexts/EditorDocumentContext.tsx +113 -0
- package/src/editor/contexts/EditorHistoryContext.tsx +516 -0
- package/src/editor/contexts/EditorRefsContext.tsx +204 -0
- package/src/editor/contexts/EditorSelectionContext.tsx +54 -0
- package/src/editor/contexts/EditorToolContext.tsx +58 -0
- package/src/editor/contexts/EditorUIStateContext.tsx +122 -0
- package/src/editor/contexts/EditorVariablesContext.tsx +397 -0
- package/src/editor/contexts/EditorViewContext.tsx +101 -0
- package/src/editor/contexts/MultiPageCanvasContext.tsx +498 -0
- package/src/editor/contexts/index.ts +17 -0
- package/src/editor/editor-skin.css +122 -0
- package/src/editor/hooks/index.ts +38 -0
- package/src/editor/hooks/useAiReplace.ts +397 -0
- package/src/editor/hooks/useAltMeasure.ts +67 -0
- package/src/editor/hooks/useBrowserZoomPrevention.ts +121 -0
- package/src/editor/hooks/useCanvasControls.ts +1222 -0
- package/src/editor/hooks/useComponentEditMode.ts +658 -0
- package/src/editor/hooks/useComponentInstances.ts +515 -0
- package/src/editor/hooks/useContextMenuHandler.ts +157 -0
- package/src/editor/hooks/useCoordinateTransform.ts +207 -0
- package/src/editor/hooks/useDragResize.ts +1317 -0
- package/src/editor/hooks/useDrawingMode.ts +472 -0
- package/src/editor/hooks/useEditorColors.ts +144 -0
- package/src/editor/hooks/useEditorMessages.ts +108 -0
- package/src/editor/hooks/useElementActions.ts +1754 -0
- package/src/editor/hooks/useElementSelection.ts +1573 -0
- package/src/editor/hooks/useFocusManagement.ts +249 -0
- package/src/editor/hooks/useGoogleFonts.ts +305 -0
- package/src/editor/hooks/useIframeInitializer.ts +584 -0
- package/src/editor/hooks/useIframeSetup.ts +360 -0
- package/src/editor/hooks/useImageUpload.ts +270 -0
- package/src/editor/hooks/useInfiniteCanvas.ts +301 -0
- package/src/editor/hooks/useKeyboardShortcuts.ts +205 -0
- package/src/editor/hooks/useMarqueeSelection.ts +388 -0
- package/src/editor/hooks/useMediaLibrary.ts +129 -0
- package/src/editor/hooks/usePageSettingsManager.ts +739 -0
- package/src/editor/hooks/useResizablePanel.ts +163 -0
- package/src/editor/hooks/useRichPaste.ts +255 -0
- package/src/editor/hooks/useTouchGestures.ts +197 -0
- package/src/editor/index.ts +27 -0
- package/src/editor/types/page-settings.ts +513 -0
- package/src/editor/types.ts +382 -0
- package/src/editor/utils/align-elements.ts +169 -0
- package/src/editor/utils/api-json.ts +21 -0
- package/src/editor/utils/aspect-lock.ts +50 -0
- package/src/editor/utils/component-renderer.ts +702 -0
- package/src/editor/utils/component-sync.ts +845 -0
- package/src/editor/utils/crop-mode.ts +265 -0
- package/src/editor/utils/dom-utils.ts +2238 -0
- package/src/editor/utils/element-effects.ts +218 -0
- package/src/editor/utils/eyedropper.ts +35 -0
- package/src/editor/utils/figma-export.ts +560 -0
- package/src/editor/utils/figma-kiwi-decoder.ts +722 -0
- package/src/editor/utils/figma-kiwi-encoder.ts +583 -0
- package/src/editor/utils/figma-paste.ts +2262 -0
- package/src/editor/utils/flex-reorder.ts +231 -0
- package/src/editor/utils/flex-utils.ts +1230 -0
- package/src/editor/utils/geometry.ts +232 -0
- package/src/editor/utils/grid-layout.ts +210 -0
- package/src/editor/utils/html-utils.ts +470 -0
- package/src/editor/utils/index.ts +11 -0
- package/src/editor/utils/ink-style.ts +57 -0
- package/src/editor/utils/inline-format.ts +236 -0
- package/src/editor/utils/measure-distance.ts +120 -0
- package/src/editor/utils/override-apply.ts +526 -0
- package/src/editor/utils/override-detection.ts +613 -0
- package/src/editor/utils/paste-processors.ts +609 -0
- package/src/editor/utils/paste-sanitizer.ts +244 -0
- package/src/editor/utils/restore-flow.ts +188 -0
- package/src/editor/utils/shape-library.ts +171 -0
- package/src/editor/utils/slide-root.ts +29 -0
- package/src/editor/utils/smart-guides.ts +218 -0
- package/src/editor/utils/style-utils.ts +685 -0
- package/src/editor/utils/table-edit.ts +151 -0
- package/src/editor/utils/tailwind-mappings.ts +778 -0
- package/src/editor/utils/tailwind-utils.ts +804 -0
- package/src/editor/utils/text-highlight.ts +216 -0
- package/src/editor/utils/theme-to-variables.ts +341 -0
- package/src/editor/utils/variant-resolver.ts +456 -0
- package/src/editor/utils/viewport-utils.ts +295 -0
- package/src/hooks/useEditorHistory.ts +195 -0
- package/src/hooks/useEditorShortcuts.ts +260 -0
- package/src/index.ts +40 -0
- package/src/io.ts +134 -0
- package/src/lib/agent/slide-agent/types.ts +547 -0
- package/src/lib/agent/website-agent/types.ts +805 -0
- package/src/lib/api/auth-fetch.ts +58 -0
- package/src/lib/deck.ts +69 -0
- package/src/lib/export.ts +47 -0
- package/src/lib/firebase/config.ts +29 -0
- package/src/lib/firebase/css-variables.ts +378 -0
- package/src/lib/firebase/editor-components.ts +677 -0
- package/src/lib/firebase/storage.ts +469 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/editor.css +52 -0
- package/src/styles/skin.css +122 -0
- package/src/types/css-variables.ts +645 -0
- package/src/types/editor-components.ts +944 -0
- package/src/types/editor.ts +420 -0
- package/src/types/page-master.ts +197 -0
- package/src/types/page.ts +419 -0
- package/src/types/slide.ts +402 -0
- package/src/types/website-theme.ts +788 -0
- package/src/types/website.ts +374 -0
- package/src/vendor/firebase-firestore.ts +13 -0
- 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
|
+
}
|