@ashraf_mizo/htmlcanvas 1.0.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/bin/cli.js +28 -0
- package/editor/alignment.js +211 -0
- package/editor/assets.js +724 -0
- package/editor/clipboard.js +177 -0
- package/editor/coords.js +121 -0
- package/editor/crop.js +325 -0
- package/editor/cssVars.js +134 -0
- package/editor/domModel.js +161 -0
- package/editor/editor.css +1996 -0
- package/editor/editor.js +833 -0
- package/editor/guides.js +513 -0
- package/editor/history.js +135 -0
- package/editor/index.html +540 -0
- package/editor/layers.js +389 -0
- package/editor/logo-final.svg +21 -0
- package/editor/logo-toolbar.svg +21 -0
- package/editor/manipulation.js +864 -0
- package/editor/multiSelect.js +436 -0
- package/editor/properties.js +1583 -0
- package/editor/selection.js +432 -0
- package/editor/serializer.js +160 -0
- package/editor/shortcuts.js +143 -0
- package/editor/slidePanel.js +361 -0
- package/editor/slides.js +101 -0
- package/editor/snap.js +98 -0
- package/editor/textEdit.js +538 -0
- package/editor/zoom.js +96 -0
- package/package.json +28 -0
- package/server.js +588 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Ashraf.Builds Canvas</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=Podkova:wght@700&display=swap" rel="stylesheet">
|
|
9
|
+
<link rel="stylesheet" href="editor.css?v=20260330a">
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
|
|
13
|
+
<!-- ── Editor layout ────────────────────────────────────────────────────── -->
|
|
14
|
+
<div class="editor-layout">
|
|
15
|
+
|
|
16
|
+
<!-- Toolbar -->
|
|
17
|
+
<header class="toolbar">
|
|
18
|
+
<span class="toolbar-wordmark">
|
|
19
|
+
<img class="toolbar-logo" src="logo-toolbar.svg" alt="Ashraf.Builds logo" height="28">
|
|
20
|
+
|
|
21
|
+
</span>
|
|
22
|
+
<div class="toolbar-separator"></div>
|
|
23
|
+
<span id="current-filename">No file open</span>
|
|
24
|
+
<span id="toolbar-status"></span>
|
|
25
|
+
<div class="toolbar-history">
|
|
26
|
+
<button class="btn-toolbar btn-icon" id="btn-undo" title="Undo (Ctrl+Z)">
|
|
27
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>
|
|
28
|
+
</button>
|
|
29
|
+
<button class="btn-toolbar btn-icon" id="btn-redo" title="Redo (Ctrl+Y)">
|
|
30
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.13-9.36L23 10"/></svg>
|
|
31
|
+
</button>
|
|
32
|
+
<button class="btn-toolbar btn-icon" id="btn-deselect" title="Deselect (Esc)">
|
|
33
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="toolbar-separator"></div>
|
|
37
|
+
<div class="toolbar-zoom">
|
|
38
|
+
<button class="btn-zoom" id="btn-zoom-out" title="Zoom out (Ctrl+-)">−</button>
|
|
39
|
+
<button class="btn-zoom-level" id="btn-zoom-level" title="Click to reset to 100%">100%</button>
|
|
40
|
+
<button class="btn-zoom" id="btn-zoom-in" title="Zoom in (Ctrl+=)">+</button>
|
|
41
|
+
</div>
|
|
42
|
+
<span id="slide-count" class="toolbar-slide-count" style="display:none;"></span>
|
|
43
|
+
<div class="toolbar-separator"></div>
|
|
44
|
+
<button class="btn-toolbar btn-snap active" id="btn-snap" title="Toggle snap guides">Snap</button>
|
|
45
|
+
<button class="btn-toolbar btn-snap active" id="btn-guides" title="Toggle rulers & guides">Guides</button>
|
|
46
|
+
<div class="toolbar-separator"></div>
|
|
47
|
+
<div class="toolbar-shapes">
|
|
48
|
+
<div class="shape-picker-wrapper">
|
|
49
|
+
<button class="btn-toolbar btn-icon" id="btn-shapes" title="Insert shape">
|
|
50
|
+
<svg width="16" height="16"><rect x="1" y="3" width="14" height="10" fill="none" stroke="currentColor" stroke-width="1.5" rx="1"/></svg>
|
|
51
|
+
<svg class="btn-shapes-caret" width="8" height="5" viewBox="0 0 8 5"><path d="M0,0 L4,4 L8,0" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
|
|
52
|
+
</button>
|
|
53
|
+
<div class="shape-picker-dropdown" id="shape-picker" style="display:none;"></div>
|
|
54
|
+
</div>
|
|
55
|
+
<button class="btn-toolbar btn-icon" id="btn-insert-image" title="Insert image from file">
|
|
56
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="m21 15-5-5L5 21"/></svg>
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="toolbar-separator"></div>
|
|
60
|
+
<div class="toolbar-align" id="toolbar-align" style="display:none;">
|
|
61
|
+
<button class="btn-toolbar btn-icon" data-align="left" title="Align left">
|
|
62
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="2" y1="2" x2="2" y2="14" stroke="currentColor" stroke-width="1.5"/><rect x="4" y="4" width="10" height="3" rx="0.5" fill="currentColor"/><rect x="4" y="9" width="6" height="3" rx="0.5" fill="currentColor"/></svg>
|
|
63
|
+
</button>
|
|
64
|
+
<button class="btn-toolbar btn-icon" data-align="center" title="Align center">
|
|
65
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="8" y1="2" x2="8" y2="14" stroke="currentColor" stroke-width="1.5"/><rect x="3" y="4" width="10" height="3" rx="0.5" fill="currentColor"/><rect x="5" y="9" width="6" height="3" rx="0.5" fill="currentColor"/></svg>
|
|
66
|
+
</button>
|
|
67
|
+
<button class="btn-toolbar btn-icon" data-align="right" title="Align right">
|
|
68
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="14" y1="2" x2="14" y2="14" stroke="currentColor" stroke-width="1.5"/><rect x="2" y="4" width="10" height="3" rx="0.5" fill="currentColor"/><rect x="6" y="9" width="6" height="3" rx="0.5" fill="currentColor"/></svg>
|
|
69
|
+
</button>
|
|
70
|
+
<button class="btn-toolbar btn-icon" data-align="top" title="Align top">
|
|
71
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="2" y1="2" x2="14" y2="2" stroke="currentColor" stroke-width="1.5"/><rect x="4" y="4" width="3" height="10" rx="0.5" fill="currentColor"/><rect x="9" y="4" width="3" height="6" rx="0.5" fill="currentColor"/></svg>
|
|
72
|
+
</button>
|
|
73
|
+
<button class="btn-toolbar btn-icon" data-align="middle" title="Align middle">
|
|
74
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="2" y1="8" x2="14" y2="8" stroke="currentColor" stroke-width="1.5"/><rect x="4" y="3" width="3" height="10" rx="0.5" fill="currentColor"/><rect x="9" y="5" width="3" height="6" rx="0.5" fill="currentColor"/></svg>
|
|
75
|
+
</button>
|
|
76
|
+
<button class="btn-toolbar btn-icon" data-align="bottom" title="Align bottom">
|
|
77
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="2" y1="14" x2="14" y2="14" stroke="currentColor" stroke-width="1.5"/><rect x="4" y="2" width="3" height="10" rx="0.5" fill="currentColor"/><rect x="9" y="6" width="3" height="6" rx="0.5" fill="currentColor"/></svg>
|
|
78
|
+
</button>
|
|
79
|
+
<div class="toolbar-separator"></div>
|
|
80
|
+
<button class="btn-toolbar btn-icon" data-distribute="horizontal" title="Distribute horizontally">
|
|
81
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="1" y1="2" x2="1" y2="14" stroke="currentColor" stroke-width="1"/><line x1="15" y1="2" x2="15" y2="14" stroke="currentColor" stroke-width="1"/><rect x="4" y="5" width="3" height="6" rx="0.5" fill="currentColor"/><rect x="9" y="5" width="3" height="6" rx="0.5" fill="currentColor"/></svg>
|
|
82
|
+
</button>
|
|
83
|
+
<button class="btn-toolbar btn-icon" data-distribute="vertical" title="Distribute vertically">
|
|
84
|
+
<svg width="16" height="16" viewBox="0 0 16 16"><line x1="2" y1="1" x2="14" y2="1" stroke="currentColor" stroke-width="1"/><line x1="2" y1="15" x2="14" y2="15" stroke="currentColor" stroke-width="1"/><rect x="5" y="4" width="6" height="3" rx="0.5" fill="currentColor"/><rect x="5" y="9" width="6" height="3" rx="0.5" fill="currentColor"/></svg>
|
|
85
|
+
</button>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="toolbar-separator"></div>
|
|
88
|
+
<div class="toolbar-actions">
|
|
89
|
+
<button class="btn-toolbar" id="btn-save" disabled>Save</button>
|
|
90
|
+
<button class="btn-toolbar" id="btn-export">Export</button>
|
|
91
|
+
<button class="btn-toolbar" id="btn-export-pdf" title="Export as PDF (Playwright)">PDF</button>
|
|
92
|
+
</div>
|
|
93
|
+
</header>
|
|
94
|
+
|
|
95
|
+
<!-- Left panel: Slides + Assets + Components -->
|
|
96
|
+
<aside class="panel-layers" id="panel-left">
|
|
97
|
+
<button class="panel-collapse-btn panel-collapse-btn-left" id="btn-toggle-left" title="Toggle left panel (Alt+1)">
|
|
98
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path class="collapse-icon-open" d="M9 3L5 7l4 4"/><path class="collapse-icon-closed" d="M5 3l4 4-4 4"/></svg>
|
|
99
|
+
</button>
|
|
100
|
+
<div class="panel-inner">
|
|
101
|
+
<!-- Slide thumbnails (shown for multi-page decks, populated by slidePanel.js) -->
|
|
102
|
+
<div class="slide-panel" style="display:none;"></div>
|
|
103
|
+
|
|
104
|
+
<div class="panel-header panel-header-collapsible" data-section="assets">Assets</div>
|
|
105
|
+
<div class="panel-body panel-section-assets" style="display:none;">
|
|
106
|
+
<div class="asset-grid" id="asset-grid">
|
|
107
|
+
<p class="panel-placeholder">No assets found</p>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="panel-header panel-header-collapsible" data-section="components">Components</div>
|
|
111
|
+
<div class="panel-body panel-section-components" style="display:none;">
|
|
112
|
+
<div class="component-list" id="component-list">
|
|
113
|
+
<p class="panel-placeholder">No components saved</p>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</aside>
|
|
118
|
+
|
|
119
|
+
<!-- Canvas area -->
|
|
120
|
+
<main class="canvas-area" id="canvas-area">
|
|
121
|
+
<div id="iframe-container" style="display:none;">
|
|
122
|
+
<iframe id="render-iframe" sandbox="allow-same-origin allow-scripts" frameborder="0"></iframe>
|
|
123
|
+
</div>
|
|
124
|
+
<div id="hover-overlay" style="display:none;"></div>
|
|
125
|
+
<div id="selection-overlay" style="display:none;">
|
|
126
|
+
<div class="sel-drag-surface"></div>
|
|
127
|
+
<div class="sel-handle" data-pos="tl"></div>
|
|
128
|
+
<div class="sel-handle" data-pos="tm"></div>
|
|
129
|
+
<div class="sel-handle" data-pos="tr"></div>
|
|
130
|
+
<div class="sel-handle" data-pos="ml"></div>
|
|
131
|
+
<div class="sel-handle" data-pos="mr"></div>
|
|
132
|
+
<div class="sel-handle" data-pos="bl"></div>
|
|
133
|
+
<div class="sel-handle" data-pos="bm"></div>
|
|
134
|
+
<div class="sel-handle" data-pos="br"></div>
|
|
135
|
+
<div class="sel-dim-label"></div>
|
|
136
|
+
</div>
|
|
137
|
+
<div id="multi-selection-overlay" style="display:none;">
|
|
138
|
+
<div class="multi-drag-surface"></div>
|
|
139
|
+
</div>
|
|
140
|
+
<div id="canvas-empty-state">
|
|
141
|
+
<div class="empty-icon">▢</div>
|
|
142
|
+
<p>Open a file to begin</p>
|
|
143
|
+
</div>
|
|
144
|
+
</main>
|
|
145
|
+
|
|
146
|
+
<!-- Right panel: Properties -->
|
|
147
|
+
<aside class="panel-properties" id="panel-right">
|
|
148
|
+
<button class="panel-collapse-btn panel-collapse-btn-right" id="btn-toggle-right" title="Toggle right panel (Alt+2)">
|
|
149
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path class="collapse-icon-open" d="M5 3l4 4-4 4"/><path class="collapse-icon-closed" d="M9 3L5 7l4 4"/></svg>
|
|
150
|
+
</button>
|
|
151
|
+
<div class="panel-inner">
|
|
152
|
+
<div class="panel-header panel-header-collapsible" data-section="right-layers">Layers</div>
|
|
153
|
+
<div class="panel-body panel-section-right-layers">
|
|
154
|
+
<ul class="layer-list right-layer-list"></ul>
|
|
155
|
+
</div>
|
|
156
|
+
<div class="panel-header">Properties</div>
|
|
157
|
+
<div class="panel-body panel-body-properties">
|
|
158
|
+
<p class="panel-placeholder">Select an element</p>
|
|
159
|
+
|
|
160
|
+
<!-- ── Actions section (context-sensitive buttons) ── -->
|
|
161
|
+
<div class="prop-section prop-section-actions" style="display:none;">
|
|
162
|
+
<div class="prop-actions-row">
|
|
163
|
+
<button class="prop-action-btn" id="prop-edit-text" title="Double-click element to edit text">
|
|
164
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></svg>
|
|
165
|
+
Edit Text
|
|
166
|
+
</button>
|
|
167
|
+
<button class="prop-action-btn" id="prop-replace-image" style="display:none;" title="Replace this image with a new file">
|
|
168
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="m21 15-5-5L5 21"/></svg>
|
|
169
|
+
Replace Image
|
|
170
|
+
</button>
|
|
171
|
+
<button class="prop-action-btn" id="prop-crop-image" style="display:none;" title="Crop this image">
|
|
172
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 2v14a2 2 0 0 0 2 2h14"/><path d="M18 22V8a2 2 0 0 0-2-2H2"/></svg>
|
|
173
|
+
Crop
|
|
174
|
+
</button>
|
|
175
|
+
<div class="prop-mask-wrapper">
|
|
176
|
+
<button class="prop-action-btn" id="prop-mask-shape" title="Mask to shape">
|
|
177
|
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.3"><circle cx="8" cy="8" r="6"/><rect x="2" y="2" width="12" height="12" rx="1" stroke-opacity="0.4"/></svg>
|
|
178
|
+
Mask
|
|
179
|
+
</button>
|
|
180
|
+
<div class="mask-picker" id="mask-picker" style="display:none;"></div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="prop-zorder-row" id="prop-zorder">
|
|
184
|
+
<button class="prop-zorder-btn" data-zorder="front" title="Bring to front">
|
|
185
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M6 10V2M3 4l3-3 3 3"/></svg>
|
|
186
|
+
Front
|
|
187
|
+
</button>
|
|
188
|
+
<button class="prop-zorder-btn" data-zorder="forward" title="Bring forward">
|
|
189
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M6 8V3M4 5l2-2 2 2"/></svg>
|
|
190
|
+
Fwd
|
|
191
|
+
</button>
|
|
192
|
+
<button class="prop-zorder-btn" data-zorder="backward" title="Send backward">
|
|
193
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M6 4v5M4 7l2 2 2-2"/></svg>
|
|
194
|
+
Back
|
|
195
|
+
</button>
|
|
196
|
+
<button class="prop-zorder-btn" data-zorder="back" title="Send to back">
|
|
197
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M6 2v8M3 8l3 3 3-3"/></svg>
|
|
198
|
+
Bottom
|
|
199
|
+
</button>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<!-- ── Dimensions section ── -->
|
|
204
|
+
<div class="prop-section" style="display:none;">
|
|
205
|
+
<div class="prop-section-header">
|
|
206
|
+
<span class="prop-section-arrow">▾</span> Dimensions
|
|
207
|
+
</div>
|
|
208
|
+
<div class="prop-section-body">
|
|
209
|
+
<div class="prop-grid-2x2">
|
|
210
|
+
<div class="prop-row">
|
|
211
|
+
<label class="prop-label">X</label>
|
|
212
|
+
<input type="number" id="prop-x" class="prop-input" placeholder="0">
|
|
213
|
+
</div>
|
|
214
|
+
<div class="prop-row">
|
|
215
|
+
<label class="prop-label">Y</label>
|
|
216
|
+
<input type="number" id="prop-y" class="prop-input" placeholder="0">
|
|
217
|
+
</div>
|
|
218
|
+
<div class="prop-row">
|
|
219
|
+
<label class="prop-label">W</label>
|
|
220
|
+
<input type="number" id="prop-w" class="prop-input" placeholder="0">
|
|
221
|
+
</div>
|
|
222
|
+
<div class="prop-row prop-row-linked">
|
|
223
|
+
<label class="prop-label">H</label>
|
|
224
|
+
<input type="number" id="prop-h" class="prop-input" placeholder="0">
|
|
225
|
+
<button class="prop-link-btn" id="prop-aspect-lock" title="Lock aspect ratio">
|
|
226
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.2"><path d="M4 3V2a2 2 0 0 1 4 0v1"/><rect x="3" y="5" width="6" height="5" rx="1"/></svg>
|
|
227
|
+
</button>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="prop-row">
|
|
231
|
+
<label class="prop-label">R</label>
|
|
232
|
+
<input type="number" id="prop-rotation" class="prop-input" placeholder="0" step="1">
|
|
233
|
+
<span class="prop-unit">°</span>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<!-- ── Text section ── -->
|
|
239
|
+
<div class="prop-section" style="display:none;">
|
|
240
|
+
<div class="prop-section-header">
|
|
241
|
+
<span class="prop-section-arrow">▾</span> Text
|
|
242
|
+
</div>
|
|
243
|
+
<div class="prop-section-body">
|
|
244
|
+
<div class="prop-row prop-row-full">
|
|
245
|
+
<div id="prop-font-family" class="font-picker">
|
|
246
|
+
<button class="font-picker-trigger" type="button">
|
|
247
|
+
<span class="font-picker-value">DM Sans</span>
|
|
248
|
+
<svg class="font-picker-arrow" width="10" height="6" viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="#888" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
249
|
+
</button>
|
|
250
|
+
<div class="font-picker-dropdown" style="display:none;">
|
|
251
|
+
<input class="font-picker-search" type="text" placeholder="Search fonts...">
|
|
252
|
+
<div class="font-picker-list"></div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
<div class="prop-row">
|
|
257
|
+
<label class="prop-label">Size</label>
|
|
258
|
+
<input type="number" id="prop-font-size" class="prop-input" min="1" step="1">
|
|
259
|
+
<span class="prop-unit">px</span>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="prop-row">
|
|
262
|
+
<label class="prop-label">Weight</label>
|
|
263
|
+
<select id="prop-font-weight" class="prop-select">
|
|
264
|
+
<option value="300">300</option>
|
|
265
|
+
<option value="400">400</option>
|
|
266
|
+
<option value="500">500</option>
|
|
267
|
+
<option value="600">600</option>
|
|
268
|
+
<option value="700">700</option>
|
|
269
|
+
</select>
|
|
270
|
+
</div>
|
|
271
|
+
<div class="prop-row">
|
|
272
|
+
<label class="prop-label">Color</label>
|
|
273
|
+
<input type="color" id="prop-color" class="prop-color-swatch">
|
|
274
|
+
<input type="text" id="prop-color-hex" class="prop-input prop-hex-input" maxlength="7" placeholder="#000000">
|
|
275
|
+
<span id="prop-color-lock" class="prop-var-lock" style="display:none;">var()</span>
|
|
276
|
+
</div>
|
|
277
|
+
<div class="prop-recent-colors" data-css-prop="color"></div>
|
|
278
|
+
<div class="prop-row">
|
|
279
|
+
<label class="prop-label">Leading</label>
|
|
280
|
+
<input type="number" id="prop-line-height" class="prop-input" min="0.5" step="0.1">
|
|
281
|
+
</div>
|
|
282
|
+
<div class="prop-row">
|
|
283
|
+
<label class="prop-label">Spacing</label>
|
|
284
|
+
<input type="number" id="prop-letter-spacing" class="prop-input" step="0.5" placeholder="0">
|
|
285
|
+
<span class="prop-unit">px</span>
|
|
286
|
+
</div>
|
|
287
|
+
<div class="prop-row">
|
|
288
|
+
<label class="prop-label">H Align</label>
|
|
289
|
+
<div class="prop-btn-group" id="prop-text-align">
|
|
290
|
+
<button class="prop-btn-toggle" data-value="left" title="Align left">
|
|
291
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="2" x2="13" y2="2" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="5.5" x2="9" y2="5.5" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="9" x2="11" y2="9" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="12.5" x2="7" y2="12.5" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
292
|
+
</button>
|
|
293
|
+
<button class="prop-btn-toggle" data-value="center" title="Align center">
|
|
294
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="2" x2="13" y2="2" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="5.5" x2="11" y2="5.5" stroke="currentColor" stroke-width="1.5"/><line x1="2" y1="9" x2="12" y2="9" stroke="currentColor" stroke-width="1.5"/><line x1="4" y1="12.5" x2="10" y2="12.5" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
295
|
+
</button>
|
|
296
|
+
<button class="prop-btn-toggle" data-value="right" title="Align right">
|
|
297
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="2" x2="13" y2="2" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="5.5" x2="13" y2="5.5" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="9" x2="13" y2="9" stroke="currentColor" stroke-width="1.5"/><line x1="7" y1="12.5" x2="13" y2="12.5" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
298
|
+
</button>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
<div class="prop-row">
|
|
302
|
+
<label class="prop-label">V Align</label>
|
|
303
|
+
<div class="prop-btn-group" id="prop-text-valign">
|
|
304
|
+
<button class="prop-btn-toggle" data-value="flex-start" title="Align top">
|
|
305
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="1" x2="13" y2="1" stroke="currentColor" stroke-width="1.5"/><rect x="5" y="3" width="4" height="7" rx="0.5" fill="currentColor"/></svg>
|
|
306
|
+
</button>
|
|
307
|
+
<button class="prop-btn-toggle" data-value="center" title="Align middle">
|
|
308
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="7" x2="13" y2="7" stroke="currentColor" stroke-width="1.5"/><rect x="5" y="3" width="4" height="8" rx="0.5" fill="currentColor"/></svg>
|
|
309
|
+
</button>
|
|
310
|
+
<button class="prop-btn-toggle" data-value="flex-end" title="Align bottom">
|
|
311
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="1" y1="13" x2="13" y2="13" stroke="currentColor" stroke-width="1.5"/><rect x="5" y="4" width="4" height="7" rx="0.5" fill="currentColor"/></svg>
|
|
312
|
+
</button>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
<div class="prop-row">
|
|
316
|
+
<label class="prop-label">Style</label>
|
|
317
|
+
<div class="prop-btn-group" id="prop-text-style">
|
|
318
|
+
<button class="prop-btn-toggle" data-prop="text-decoration" data-value="underline" title="Underline">
|
|
319
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><path d="M3 2v5a4 4 0 0 0 8 0V2" stroke="currentColor" stroke-width="1.5" fill="none"/><line x1="2" y1="13" x2="12" y2="13" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
320
|
+
</button>
|
|
321
|
+
<button class="prop-btn-toggle" data-prop="text-transform" data-value="uppercase" title="Uppercase">
|
|
322
|
+
<span style="font-size:11px;font-weight:700;line-height:14px;">AA</span>
|
|
323
|
+
</button>
|
|
324
|
+
<button class="prop-btn-toggle" data-prop="font-style" data-value="italic" title="Italic">
|
|
325
|
+
<svg width="14" height="14" viewBox="0 0 14 14"><line x1="6" y1="2" x2="10" y2="2" stroke="currentColor" stroke-width="1.5"/><line x1="4" y1="12" x2="8" y2="12" stroke="currentColor" stroke-width="1.5"/><line x1="9" y1="2" x2="5" y2="12" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
326
|
+
</button>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
<!-- ── Fill section ── -->
|
|
333
|
+
<div class="prop-section" style="display:none;">
|
|
334
|
+
<div class="prop-section-header">
|
|
335
|
+
<span class="prop-section-arrow">▾</span> Fill
|
|
336
|
+
</div>
|
|
337
|
+
<div class="prop-section-body">
|
|
338
|
+
<div class="prop-row">
|
|
339
|
+
<div class="prop-chip-group">
|
|
340
|
+
<button class="prop-chip active" id="prop-fill-chip-color">Color</button>
|
|
341
|
+
<button class="prop-chip" id="prop-fill-chip-none">None</button>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
<div class="prop-row" id="prop-fill-color-row">
|
|
345
|
+
<input type="color" id="prop-bg-color" class="prop-color-swatch">
|
|
346
|
+
<input type="text" id="prop-bg-hex" class="prop-input prop-hex-input" maxlength="7" placeholder="#ffffff">
|
|
347
|
+
<span id="prop-bg-lock" class="prop-var-lock" style="display:none;">var()</span>
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<!-- ── Border section ── -->
|
|
353
|
+
<div class="prop-section" style="display:none;">
|
|
354
|
+
<div class="prop-section-header">
|
|
355
|
+
<span class="prop-section-arrow">▾</span> Border
|
|
356
|
+
</div>
|
|
357
|
+
<div class="prop-section-body">
|
|
358
|
+
<div class="prop-row">
|
|
359
|
+
<div class="prop-chip-group">
|
|
360
|
+
<button class="prop-chip" id="prop-border-chip-on">On</button>
|
|
361
|
+
<button class="prop-chip active" id="prop-border-chip-none">None</button>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
<div id="prop-border-controls" style="display:none;">
|
|
365
|
+
<div class="prop-row">
|
|
366
|
+
<label class="prop-label">Width</label>
|
|
367
|
+
<input type="number" id="prop-border-width" class="prop-input" min="0" step="1">
|
|
368
|
+
<span class="prop-unit">px</span>
|
|
369
|
+
</div>
|
|
370
|
+
<div class="prop-row">
|
|
371
|
+
<label class="prop-label">Style</label>
|
|
372
|
+
<select id="prop-border-style" class="prop-select">
|
|
373
|
+
<option value="solid">solid</option>
|
|
374
|
+
<option value="dashed">dashed</option>
|
|
375
|
+
<option value="dotted">dotted</option>
|
|
376
|
+
<option value="double">double</option>
|
|
377
|
+
</select>
|
|
378
|
+
</div>
|
|
379
|
+
<div class="prop-row">
|
|
380
|
+
<label class="prop-label">Color</label>
|
|
381
|
+
<input type="color" id="prop-border-color" class="prop-color-swatch">
|
|
382
|
+
<input type="text" id="prop-border-hex" class="prop-input prop-hex-input" maxlength="7" placeholder="#000000">
|
|
383
|
+
</div>
|
|
384
|
+
<div class="prop-row">
|
|
385
|
+
<label class="prop-label">Radius</label>
|
|
386
|
+
<input type="number" id="prop-border-radius" class="prop-input" min="0" step="1">
|
|
387
|
+
<span class="prop-unit">px</span>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
</div>
|
|
391
|
+
</div>
|
|
392
|
+
|
|
393
|
+
<!-- ── Opacity section ── -->
|
|
394
|
+
<div class="prop-section" style="display:none;">
|
|
395
|
+
<div class="prop-section-header">
|
|
396
|
+
<span class="prop-section-arrow">▾</span> Opacity
|
|
397
|
+
</div>
|
|
398
|
+
<div class="prop-section-body">
|
|
399
|
+
<div class="prop-row">
|
|
400
|
+
<input type="range" id="prop-opacity" class="prop-range" min="0" max="1" step="0.01" value="1">
|
|
401
|
+
<input type="number" id="prop-opacity-val" class="prop-input prop-input-sm" min="0" max="100" step="1" value="100">
|
|
402
|
+
<span class="prop-unit">%</span>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<!-- ── Shadow section ── -->
|
|
408
|
+
<div class="prop-section" style="display:none;">
|
|
409
|
+
<div class="prop-section-header">
|
|
410
|
+
<span class="prop-section-arrow">▾</span> Shadow
|
|
411
|
+
</div>
|
|
412
|
+
<div class="prop-section-body">
|
|
413
|
+
<div class="prop-grid-2x2">
|
|
414
|
+
<div class="prop-row">
|
|
415
|
+
<label class="prop-label">X</label>
|
|
416
|
+
<input type="number" id="prop-shadow-x" class="prop-input" value="0" step="1">
|
|
417
|
+
</div>
|
|
418
|
+
<div class="prop-row">
|
|
419
|
+
<label class="prop-label">Y</label>
|
|
420
|
+
<input type="number" id="prop-shadow-y" class="prop-input" value="4" step="1">
|
|
421
|
+
</div>
|
|
422
|
+
<div class="prop-row">
|
|
423
|
+
<label class="prop-label">Blur</label>
|
|
424
|
+
<input type="number" id="prop-shadow-blur" class="prop-input" value="8" min="0" step="1">
|
|
425
|
+
</div>
|
|
426
|
+
<div class="prop-row">
|
|
427
|
+
<label class="prop-label">Spread</label>
|
|
428
|
+
<input type="number" id="prop-shadow-spread" class="prop-input" value="0" step="1">
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
431
|
+
<div class="prop-row">
|
|
432
|
+
<label class="prop-label">Color</label>
|
|
433
|
+
<input type="color" id="prop-shadow-color" class="prop-color-swatch" value="#000000">
|
|
434
|
+
<input type="text" id="prop-shadow-hex" class="prop-input prop-hex-input" maxlength="9" placeholder="#00000040">
|
|
435
|
+
</div>
|
|
436
|
+
<div class="prop-row">
|
|
437
|
+
<button class="prop-action-btn prop-action-btn-sm" id="prop-shadow-remove" title="Remove shadow">Remove Shadow</button>
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<!-- ── Spacing section (padding/margin) ── -->
|
|
443
|
+
<div class="prop-section" style="display:none;">
|
|
444
|
+
<div class="prop-section-header">
|
|
445
|
+
<span class="prop-section-arrow">▾</span> Spacing
|
|
446
|
+
</div>
|
|
447
|
+
<div class="prop-section-body">
|
|
448
|
+
<div class="prop-grid-2x2">
|
|
449
|
+
<div class="prop-row">
|
|
450
|
+
<label class="prop-label">P-T</label>
|
|
451
|
+
<input type="number" id="prop-padding-top" class="prop-input" min="0" step="1" placeholder="0">
|
|
452
|
+
</div>
|
|
453
|
+
<div class="prop-row">
|
|
454
|
+
<label class="prop-label">P-R</label>
|
|
455
|
+
<input type="number" id="prop-padding-right" class="prop-input" min="0" step="1" placeholder="0">
|
|
456
|
+
</div>
|
|
457
|
+
<div class="prop-row">
|
|
458
|
+
<label class="prop-label">P-B</label>
|
|
459
|
+
<input type="number" id="prop-padding-bottom" class="prop-input" min="0" step="1" placeholder="0">
|
|
460
|
+
</div>
|
|
461
|
+
<div class="prop-row">
|
|
462
|
+
<label class="prop-label">P-L</label>
|
|
463
|
+
<input type="number" id="prop-padding-left" class="prop-input" min="0" step="1" placeholder="0">
|
|
464
|
+
</div>
|
|
465
|
+
</div>
|
|
466
|
+
<div class="prop-grid-2x2" style="margin-top:6px;">
|
|
467
|
+
<div class="prop-row">
|
|
468
|
+
<label class="prop-label">M-T</label>
|
|
469
|
+
<input type="number" id="prop-margin-top" class="prop-input" step="1" placeholder="0">
|
|
470
|
+
</div>
|
|
471
|
+
<div class="prop-row">
|
|
472
|
+
<label class="prop-label">M-R</label>
|
|
473
|
+
<input type="number" id="prop-margin-right" class="prop-input" step="1" placeholder="0">
|
|
474
|
+
</div>
|
|
475
|
+
<div class="prop-row">
|
|
476
|
+
<label class="prop-label">M-B</label>
|
|
477
|
+
<input type="number" id="prop-margin-bottom" class="prop-input" step="1" placeholder="0">
|
|
478
|
+
</div>
|
|
479
|
+
<div class="prop-row">
|
|
480
|
+
<label class="prop-label">M-L</label>
|
|
481
|
+
<input type="number" id="prop-margin-left" class="prop-input" step="1" placeholder="0">
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
</div>
|
|
486
|
+
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
</aside>
|
|
490
|
+
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
<!-- ── Welcome screen ───────────────────────────────────────────────────── -->
|
|
494
|
+
<div id="welcome-screen">
|
|
495
|
+
<div class="welcome-blob welcome-blob-1"></div>
|
|
496
|
+
<div class="welcome-blob welcome-blob-2"></div>
|
|
497
|
+
<div class="welcome-blob welcome-blob-3"></div>
|
|
498
|
+
<div class="welcome-logo">
|
|
499
|
+
<img src="logo-toolbar.svg" alt="Ashraf.Builds" class="welcome-logo-img">
|
|
500
|
+
</div>
|
|
501
|
+
<p class="welcome-subtitle">Open an HTML file to begin editing</p>
|
|
502
|
+
<button id="btn-open">Open File</button>
|
|
503
|
+
<div class="recent-files-section">
|
|
504
|
+
<h3>Recent Files</h3>
|
|
505
|
+
<ul id="recent-files-list">
|
|
506
|
+
<!-- Populated by editor.js -->
|
|
507
|
+
</ul>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
|
|
511
|
+
<!-- ── Drop overlay ─────────────────────────────────────────────────────── -->
|
|
512
|
+
<div id="drop-overlay">
|
|
513
|
+
<p>Drop HTML file to open</p>
|
|
514
|
+
</div>
|
|
515
|
+
|
|
516
|
+
<!-- ── File-changed banner ──────────────────────────────────────────────── -->
|
|
517
|
+
<div id="file-changed-banner">
|
|
518
|
+
<span>File changed on disk.</span>
|
|
519
|
+
<button id="btn-banner-reload">Reload</button>
|
|
520
|
+
<button id="btn-banner-dismiss">Dismiss</button>
|
|
521
|
+
</div>
|
|
522
|
+
|
|
523
|
+
<script>
|
|
524
|
+
// Debug: catch any JS errors that prevent modules from loading
|
|
525
|
+
window.onerror = function(msg, src, line, col, err) {
|
|
526
|
+
var el = document.getElementById('toolbar-status');
|
|
527
|
+
if (el) { el.textContent = 'JS Error: ' + msg; el.classList.add('visible'); el.style.color = '#ff4444'; }
|
|
528
|
+
console.error('JS Error:', msg, src, line, col, err);
|
|
529
|
+
};
|
|
530
|
+
window.addEventListener('unhandledrejection', function(e) {
|
|
531
|
+
var el = document.getElementById('toolbar-status');
|
|
532
|
+
if (el) { el.textContent = 'Promise Error: ' + e.reason; el.classList.add('visible'); el.style.color = '#ff4444'; }
|
|
533
|
+
console.error('Unhandled rejection:', e.reason);
|
|
534
|
+
});
|
|
535
|
+
</script>
|
|
536
|
+
<script src="lib/sortable.min.js"></script>
|
|
537
|
+
<script type="module" src="editor.js?v=20260324g"></script>
|
|
538
|
+
<script defer src="/_vercel/insights/script.js"></script>
|
|
539
|
+
</body>
|
|
540
|
+
</html>
|