@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,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* スマートガイド(整列ガイド)とスナップ。
|
|
3
|
+
*
|
|
4
|
+
* ドラッグ中の要素が、他の要素やアートボードの「端・中央」と揃う瞬間に
|
|
5
|
+
* 赤いガイド線を出し、そこへ吸着させる(Figma/PowerPointと同じ挙動)。
|
|
6
|
+
*
|
|
7
|
+
* 座標はすべてアートボード座標(1920×1080の素のpx)。measure-distance.ts と同じく
|
|
8
|
+
* 描画レイヤーは #artboard 直下に置くので、ズームはアートボードごと transform
|
|
9
|
+
* されて線も自動で追従する。レイヤーは表示専用(pointer-events:none)で、
|
|
10
|
+
* 保存対象にもならない(getCleanHtml が #gg-smart-guides を除去する)。
|
|
11
|
+
*
|
|
12
|
+
* 【性能の約束】候補座標の収集はドラッグ開始時の1回だけ。毎フレームやるのは
|
|
13
|
+
* ソート済み配列への二分探索3本(x)と3本(y)だけで、要素数が数百でも一定時間で終わる。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { getOverlayRect } from './dom-utils';
|
|
17
|
+
|
|
18
|
+
const LAYER_ID = 'gg-smart-guides';
|
|
19
|
+
const RED = '#f24822'; // Figmaの計測色(measure-distance.ts と揃える)
|
|
20
|
+
|
|
21
|
+
/** 吸着する距離。画面上のpxで定義し、使う側でズーム倍率を割り戻す */
|
|
22
|
+
export const SNAP_THRESHOLD_SCREEN_PX = 4;
|
|
23
|
+
|
|
24
|
+
/** ガイドの候補にしないオーバーレイ類(エディタが描いている飾り) */
|
|
25
|
+
const OVERLAY_SELECTOR =
|
|
26
|
+
'.selection-box,.marquee-selection-box,.resize-handle,.rotation-handle,' +
|
|
27
|
+
'.size-label,.element-breadcrumb,.gg-comment-layer,.gg-crop-ui,' +
|
|
28
|
+
'#gg-measure-layer,#gg-smart-guides,[data-drag-ghost],[data-flex-drop-indicator]';
|
|
29
|
+
|
|
30
|
+
/** 整列の候補座標。x/y ともに昇順ソート済み */
|
|
31
|
+
export interface GuideCandidates {
|
|
32
|
+
xs: number[];
|
|
33
|
+
ys: number[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** アートボード座標の矩形 */
|
|
37
|
+
export interface MovingRect {
|
|
38
|
+
left: number;
|
|
39
|
+
top: number;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** スナップの結果。dx/dy は「今の位置に足す補正量」 */
|
|
45
|
+
export interface SnapResult {
|
|
46
|
+
dx: number;
|
|
47
|
+
dy: number;
|
|
48
|
+
/** 揃った縦線のx座標(揃っていなければ null) */
|
|
49
|
+
guideX: number | null;
|
|
50
|
+
/** 揃った横線のy座標 */
|
|
51
|
+
guideY: number | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 昇順ソート + 近い値の重複除去(0.5px以内は同じ線とみなす) */
|
|
55
|
+
function normalize(values: number[]): number[] {
|
|
56
|
+
const sorted = values.filter((v) => Number.isFinite(v)).sort((a, b) => a - b);
|
|
57
|
+
const out: number[] = [];
|
|
58
|
+
for (const v of sorted) {
|
|
59
|
+
if (out.length === 0 || Math.abs(v - out[out.length - 1]) > 0.5) out.push(v);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** ソート済み配列から value に最も近い値を二分探索で返す */
|
|
65
|
+
function nearest(sorted: number[], value: number): number | null {
|
|
66
|
+
if (sorted.length === 0) return null;
|
|
67
|
+
let lo = 0;
|
|
68
|
+
let hi = sorted.length - 1;
|
|
69
|
+
while (lo < hi) {
|
|
70
|
+
const mid = (lo + hi) >> 1;
|
|
71
|
+
if (sorted[mid] < value) lo = mid + 1;
|
|
72
|
+
else hi = mid;
|
|
73
|
+
}
|
|
74
|
+
// lo は value 以上の最初の位置。その1つ手前と比べて近いほうを採る
|
|
75
|
+
const a = sorted[lo];
|
|
76
|
+
const b = lo > 0 ? sorted[lo - 1] : a;
|
|
77
|
+
return Math.abs(a - value) <= Math.abs(b - value) ? a : b;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 整列の候補座標を集める(ドラッグ開始時に1回だけ呼ぶ)
|
|
82
|
+
*
|
|
83
|
+
* 候補は「動かしている要素と同じ親を持つ兄弟」と「アートボードの端・中央」。
|
|
84
|
+
* 動かしている要素自身は除く(自分の辺に吸着してしまうため)。
|
|
85
|
+
*/
|
|
86
|
+
export function collectGuideCandidates(
|
|
87
|
+
doc: Document,
|
|
88
|
+
moving: HTMLElement[],
|
|
89
|
+
): GuideCandidates | null {
|
|
90
|
+
const artboard = doc.getElementById('artboard');
|
|
91
|
+
if (!artboard) return null;
|
|
92
|
+
|
|
93
|
+
const width = artboard.offsetWidth || 1920;
|
|
94
|
+
const height = artboard.offsetHeight || 1080;
|
|
95
|
+
|
|
96
|
+
// アートボードの端と中央(スライドの版面に対する整列)
|
|
97
|
+
const xs: number[] = [0, width / 2, width];
|
|
98
|
+
const ys: number[] = [0, height / 2, height];
|
|
99
|
+
|
|
100
|
+
const movingSet = new Set<HTMLElement>(moving);
|
|
101
|
+
const seen = new Set<HTMLElement>();
|
|
102
|
+
|
|
103
|
+
for (const el of moving) {
|
|
104
|
+
const parent = el.parentElement;
|
|
105
|
+
if (!parent) continue;
|
|
106
|
+
for (const node of Array.from(parent.children)) {
|
|
107
|
+
// [注意] `node instanceof HTMLElement` は使えない。
|
|
108
|
+
// ここは親ウィンドウで動くが、要素は iframe の realm に属するので
|
|
109
|
+
// 親の HTMLElement とは別のコンストラクタになり、常に false になる
|
|
110
|
+
// (これで兄弟が1つも候補に入らず、スナップが版面の端だけに効いていた)。
|
|
111
|
+
const child = node as HTMLElement;
|
|
112
|
+
if (typeof child.matches !== 'function') continue;
|
|
113
|
+
if (movingSet.has(child) || seen.has(child)) continue;
|
|
114
|
+
if (child.matches(OVERLAY_SELECTOR)) continue;
|
|
115
|
+
seen.add(child);
|
|
116
|
+
|
|
117
|
+
const r = getOverlayRect(doc, child);
|
|
118
|
+
// 描画されていない要素(display:none 等)は整列の相手にならない
|
|
119
|
+
if (r.width <= 0 && r.height <= 0) continue;
|
|
120
|
+
|
|
121
|
+
xs.push(r.left, r.left + r.width / 2, r.left + r.width);
|
|
122
|
+
ys.push(r.top, r.top + r.height / 2, r.top + r.height);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { xs: normalize(xs), ys: normalize(ys) };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 吸着量を求める
|
|
131
|
+
*
|
|
132
|
+
* 動かしている矩形の「左辺・中央・右辺」(y は上辺・中央・下辺)のうち、
|
|
133
|
+
* 候補にいちばん近いものを1本だけ選ぶ。同時に2本吸わせると、
|
|
134
|
+
* 幅の違う要素が引き伸ばされたように見えるため軸ごとに1本に絞る。
|
|
135
|
+
*/
|
|
136
|
+
export function snapToGuides(
|
|
137
|
+
candidates: GuideCandidates,
|
|
138
|
+
rect: MovingRect,
|
|
139
|
+
threshold: number,
|
|
140
|
+
): SnapResult {
|
|
141
|
+
const result: SnapResult = { dx: 0, dy: 0, guideX: null, guideY: null };
|
|
142
|
+
|
|
143
|
+
const xEdges = [rect.left, rect.left + rect.width / 2, rect.left + rect.width];
|
|
144
|
+
let bestX = threshold;
|
|
145
|
+
for (const edge of xEdges) {
|
|
146
|
+
const target = nearest(candidates.xs, edge);
|
|
147
|
+
if (target === null) break;
|
|
148
|
+
const diff = target - edge;
|
|
149
|
+
if (Math.abs(diff) <= bestX) {
|
|
150
|
+
bestX = Math.abs(diff);
|
|
151
|
+
result.dx = diff;
|
|
152
|
+
result.guideX = target;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const yEdges = [rect.top, rect.top + rect.height / 2, rect.top + rect.height];
|
|
157
|
+
let bestY = threshold;
|
|
158
|
+
for (const edge of yEdges) {
|
|
159
|
+
const target = nearest(candidates.ys, edge);
|
|
160
|
+
if (target === null) break;
|
|
161
|
+
const diff = target - edge;
|
|
162
|
+
if (Math.abs(diff) <= bestY) {
|
|
163
|
+
bestY = Math.abs(diff);
|
|
164
|
+
result.dy = diff;
|
|
165
|
+
result.guideY = target;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** ガイド線を消す */
|
|
173
|
+
export function clearSmartGuides(doc: Document): void {
|
|
174
|
+
doc.getElementById(LAYER_ID)?.remove();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* ガイド線を描く。揃っている軸だけ、アートボードを端から端まで貫く線を出す
|
|
179
|
+
* (どの座標で揃ったのかが一目で分かる。PowerPointの整列ガイドと同じ見せ方)
|
|
180
|
+
*/
|
|
181
|
+
export function drawSmartGuides(
|
|
182
|
+
doc: Document,
|
|
183
|
+
guideX: number | null,
|
|
184
|
+
guideY: number | null,
|
|
185
|
+
): void {
|
|
186
|
+
clearSmartGuides(doc);
|
|
187
|
+
if (guideX === null && guideY === null) return;
|
|
188
|
+
|
|
189
|
+
const artboard = doc.getElementById('artboard');
|
|
190
|
+
if (!artboard) return;
|
|
191
|
+
|
|
192
|
+
const layer = doc.createElement('div');
|
|
193
|
+
layer.id = LAYER_ID;
|
|
194
|
+
layer.style.cssText = 'position:absolute;inset:0;z-index:9500;pointer-events:none;';
|
|
195
|
+
|
|
196
|
+
// 線の太さは画面上で常に1pxに見えるよう --overlay-scale(=1/zoom)を掛ける
|
|
197
|
+
const w = 'calc(1px * var(--overlay-scale, 1))';
|
|
198
|
+
const half = 'calc(0.5px * var(--overlay-scale, 1))';
|
|
199
|
+
|
|
200
|
+
if (guideX !== null) {
|
|
201
|
+
const line = doc.createElement('div');
|
|
202
|
+
line.dataset.guide = 'x';
|
|
203
|
+
line.style.cssText =
|
|
204
|
+
`position:absolute;top:0;bottom:0;left:${guideX}px;` +
|
|
205
|
+
`width:${w};margin-left:calc(${half} * -1);background:${RED};`;
|
|
206
|
+
layer.appendChild(line);
|
|
207
|
+
}
|
|
208
|
+
if (guideY !== null) {
|
|
209
|
+
const line = doc.createElement('div');
|
|
210
|
+
line.dataset.guide = 'y';
|
|
211
|
+
line.style.cssText =
|
|
212
|
+
`position:absolute;left:0;right:0;top:${guideY}px;` +
|
|
213
|
+
`height:${w};margin-top:calc(${half} * -1);background:${RED};`;
|
|
214
|
+
layer.appendChild(line);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
artboard.appendChild(layer);
|
|
218
|
+
}
|