@popmelt.com/core 0.1.0 → 0.3.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/README.md +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1287 -811
- package/dist/server.mjs +101 -32
- package/package.json +2 -4
package/dist/index.mjs
CHANGED
|
@@ -35,7 +35,7 @@ var __objRest = (source, exclude) => {
|
|
|
35
35
|
// src/components/PopmeltProvider.tsx
|
|
36
36
|
import {
|
|
37
37
|
createContext,
|
|
38
|
-
useCallback as
|
|
38
|
+
useCallback as useCallback9,
|
|
39
39
|
useContext,
|
|
40
40
|
useEffect as useEffect20,
|
|
41
41
|
useMemo as useMemo4,
|
|
@@ -71,13 +71,20 @@ async function checkBridgeHealth(bridgeUrl = DEFAULT_BRIDGE_URL) {
|
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
async function sendToBridge(screenshotBlob, feedbackJson, bridgeUrl = DEFAULT_BRIDGE_URL, color, provider, model) {
|
|
74
|
+
async function sendToBridge(screenshotBlob, feedbackJson, bridgeUrl = DEFAULT_BRIDGE_URL, color, provider, model, pastedImages) {
|
|
75
75
|
const formData = new FormData();
|
|
76
76
|
formData.append("screenshot", screenshotBlob, "screenshot.png");
|
|
77
77
|
formData.append("feedback", feedbackJson);
|
|
78
78
|
if (color) formData.append("color", color);
|
|
79
79
|
if (provider) formData.append("provider", provider);
|
|
80
80
|
if (model) formData.append("model", model);
|
|
81
|
+
if (pastedImages) {
|
|
82
|
+
for (const [annotationId, blobs] of pastedImages) {
|
|
83
|
+
for (let i = 0; i < blobs.length; i++) {
|
|
84
|
+
formData.append(`image-${annotationId}-${i}`, blobs[i], `image-${annotationId}-${i}.png`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
81
88
|
const res = await fetch(`${bridgeUrl}/send`, {
|
|
82
89
|
method: "POST",
|
|
83
90
|
body: formData
|
|
@@ -153,12 +160,94 @@ async function sendPlanExecution(screenshotBlob, planId, tasks, bridgeUrl = DEFA
|
|
|
153
160
|
}
|
|
154
161
|
return res.json();
|
|
155
162
|
}
|
|
156
|
-
async function sendReplyToBridge(threadId, reply, bridgeUrl = DEFAULT_BRIDGE_URL, color, provider, model) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
async function sendReplyToBridge(threadId, reply, bridgeUrl = DEFAULT_BRIDGE_URL, color, provider, model, images) {
|
|
164
|
+
let res;
|
|
165
|
+
if (images && images.length > 0) {
|
|
166
|
+
const formData = new FormData();
|
|
167
|
+
const placeholder = new Blob([new Uint8Array([
|
|
168
|
+
137,
|
|
169
|
+
80,
|
|
170
|
+
78,
|
|
171
|
+
71,
|
|
172
|
+
13,
|
|
173
|
+
10,
|
|
174
|
+
26,
|
|
175
|
+
10,
|
|
176
|
+
0,
|
|
177
|
+
0,
|
|
178
|
+
0,
|
|
179
|
+
13,
|
|
180
|
+
73,
|
|
181
|
+
72,
|
|
182
|
+
68,
|
|
183
|
+
82,
|
|
184
|
+
0,
|
|
185
|
+
0,
|
|
186
|
+
0,
|
|
187
|
+
1,
|
|
188
|
+
0,
|
|
189
|
+
0,
|
|
190
|
+
0,
|
|
191
|
+
1,
|
|
192
|
+
8,
|
|
193
|
+
6,
|
|
194
|
+
0,
|
|
195
|
+
0,
|
|
196
|
+
0,
|
|
197
|
+
31,
|
|
198
|
+
21,
|
|
199
|
+
196,
|
|
200
|
+
137,
|
|
201
|
+
0,
|
|
202
|
+
0,
|
|
203
|
+
0,
|
|
204
|
+
10,
|
|
205
|
+
73,
|
|
206
|
+
68,
|
|
207
|
+
65,
|
|
208
|
+
84,
|
|
209
|
+
120,
|
|
210
|
+
156,
|
|
211
|
+
98,
|
|
212
|
+
0,
|
|
213
|
+
0,
|
|
214
|
+
0,
|
|
215
|
+
2,
|
|
216
|
+
0,
|
|
217
|
+
1,
|
|
218
|
+
229,
|
|
219
|
+
39,
|
|
220
|
+
222,
|
|
221
|
+
252,
|
|
222
|
+
0,
|
|
223
|
+
0,
|
|
224
|
+
0,
|
|
225
|
+
0,
|
|
226
|
+
73,
|
|
227
|
+
69,
|
|
228
|
+
78,
|
|
229
|
+
68,
|
|
230
|
+
174,
|
|
231
|
+
66,
|
|
232
|
+
96,
|
|
233
|
+
130
|
|
234
|
+
])], { type: "image/png" });
|
|
235
|
+
formData.append("screenshot", placeholder, "screenshot.png");
|
|
236
|
+
formData.append("feedback", JSON.stringify({ threadId, reply, color, provider, model }));
|
|
237
|
+
for (let i = 0; i < images.length; i++) {
|
|
238
|
+
formData.append(`image-reply-${i}`, images[i], `reply-image-${i}.png`);
|
|
239
|
+
}
|
|
240
|
+
res = await fetch(`${bridgeUrl}/reply`, {
|
|
241
|
+
method: "POST",
|
|
242
|
+
body: formData
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
res = await fetch(`${bridgeUrl}/reply`, {
|
|
246
|
+
method: "POST",
|
|
247
|
+
headers: { "Content-Type": "application/json" },
|
|
248
|
+
body: JSON.stringify({ threadId, reply, color, provider, model })
|
|
249
|
+
});
|
|
250
|
+
}
|
|
162
251
|
if (!res.ok) {
|
|
163
252
|
const body = await res.text();
|
|
164
253
|
throw new Error(`Bridge returned ${res.status}: ${body}`);
|
|
@@ -487,7 +576,7 @@ function handleSetAnnotating(state, payload) {
|
|
|
487
576
|
return __spreadProps(__spreadValues({}, state), { isAnnotating: payload });
|
|
488
577
|
}
|
|
489
578
|
function handleSetTool(state, payload) {
|
|
490
|
-
return __spreadProps(__spreadValues({}, state), { activeTool: payload });
|
|
579
|
+
return __spreadProps(__spreadValues({}, state), { activeTool: payload, inspectedElement: null });
|
|
491
580
|
}
|
|
492
581
|
function handleSetColor(state, payload) {
|
|
493
582
|
return __spreadProps(__spreadValues({}, state), { activeColor: payload });
|
|
@@ -526,8 +615,9 @@ function handleFinishPath(state, payload) {
|
|
|
526
615
|
});
|
|
527
616
|
}
|
|
528
617
|
function handleAddText(state, payload) {
|
|
529
|
-
|
|
530
|
-
|
|
618
|
+
var _a;
|
|
619
|
+
const textAnnotation = __spreadValues({
|
|
620
|
+
id: (_a = payload.id) != null ? _a : generateId(),
|
|
531
621
|
type: "text",
|
|
532
622
|
points: [payload.point],
|
|
533
623
|
text: payload.text,
|
|
@@ -540,7 +630,7 @@ function handleAddText(state, payload) {
|
|
|
540
630
|
linkedSelector: payload.linkedSelector,
|
|
541
631
|
linkedAnchor: payload.linkedAnchor,
|
|
542
632
|
elements: payload.elements
|
|
543
|
-
};
|
|
633
|
+
}, payload.imageCount ? { imageCount: payload.imageCount } : {});
|
|
544
634
|
const baseState = payload.groupId ? state : pushToUndoStack(state);
|
|
545
635
|
return __spreadProps(__spreadValues({}, baseState), {
|
|
546
636
|
annotations: [...state.annotations, textAnnotation]
|
|
@@ -550,7 +640,7 @@ function handleUpdateText(state, payload) {
|
|
|
550
640
|
const stateWithUndo = pushToUndoStack(state);
|
|
551
641
|
return __spreadProps(__spreadValues({}, stateWithUndo), {
|
|
552
642
|
annotations: state.annotations.map(
|
|
553
|
-
(a) => a.id === payload.id ? __spreadProps(__spreadValues({}, a), { text: payload.text }) : a
|
|
643
|
+
(a) => a.id === payload.id ? __spreadValues(__spreadProps(__spreadValues({}, a), { text: payload.text }), payload.imageCount != null ? { imageCount: payload.imageCount } : {}) : a
|
|
554
644
|
)
|
|
555
645
|
});
|
|
556
646
|
}
|
|
@@ -884,17 +974,25 @@ function handleSetAnnotationStatus(state, payload) {
|
|
|
884
974
|
}
|
|
885
975
|
function handleSetAnnotationThread(state, payload) {
|
|
886
976
|
const idSet = new Set(payload.ids);
|
|
977
|
+
const groupIds = /* @__PURE__ */ new Set();
|
|
978
|
+
for (const a of state.annotations) {
|
|
979
|
+
if (idSet.has(a.id) && a.groupId) groupIds.add(a.groupId);
|
|
980
|
+
}
|
|
887
981
|
return __spreadProps(__spreadValues({}, state), {
|
|
888
982
|
annotations: state.annotations.map(
|
|
889
|
-
(a) => idSet.has(a.id) ? __spreadProps(__spreadValues({}, a), { threadId: payload.threadId }) : a
|
|
983
|
+
(a) => idSet.has(a.id) || a.groupId && groupIds.has(a.groupId) ? __spreadProps(__spreadValues({}, a), { threadId: payload.threadId }) : a
|
|
890
984
|
)
|
|
891
985
|
});
|
|
892
986
|
}
|
|
893
987
|
function handleSetAnnotationQuestion(state, payload) {
|
|
894
988
|
const idSet = new Set(payload.ids);
|
|
989
|
+
const groupIds = /* @__PURE__ */ new Set();
|
|
990
|
+
for (const a of state.annotations) {
|
|
991
|
+
if (idSet.has(a.id) && a.groupId) groupIds.add(a.groupId);
|
|
992
|
+
}
|
|
895
993
|
return __spreadProps(__spreadValues({}, state), {
|
|
896
994
|
annotations: state.annotations.map(
|
|
897
|
-
(a) => idSet.has(a.id) ? __spreadProps(__spreadValues({}, a), { status: "waiting_input", question: payload.question, threadId: payload.threadId }) : a
|
|
995
|
+
(a) => idSet.has(a.id) || a.groupId && groupIds.has(a.groupId) ? __spreadProps(__spreadValues({}, a), { status: "waiting_input", question: payload.question, threadId: payload.threadId }) : a
|
|
898
996
|
)
|
|
899
997
|
});
|
|
900
998
|
}
|
|
@@ -1917,25 +2015,26 @@ function buildFeedbackData(annotations, styleModifications = [], inspectedElemen
|
|
|
1917
2015
|
const text = group.find((a) => a.type === "text");
|
|
1918
2016
|
if (shape) {
|
|
1919
2017
|
const linkedSelector = shape.linkedSelector || (text == null ? void 0 : text.linkedSelector);
|
|
1920
|
-
|
|
2018
|
+
const imageCount = (text == null ? void 0 : text.imageCount) || shape.imageCount;
|
|
2019
|
+
annotationDataList.push(__spreadValues(__spreadProps(__spreadValues({
|
|
1921
2020
|
id: shape.id,
|
|
1922
2021
|
type: shape.type,
|
|
1923
2022
|
instruction: text == null ? void 0 : text.text
|
|
1924
2023
|
}, linkedSelector ? { linkedSelector } : {}), {
|
|
1925
2024
|
// Use stored elements (captured at creation time) or empty array
|
|
1926
2025
|
elements: shape.elements || []
|
|
1927
|
-
}));
|
|
2026
|
+
}), imageCount ? { imageCount } : {}));
|
|
1928
2027
|
}
|
|
1929
2028
|
}
|
|
1930
2029
|
for (const annotation of standaloneAnnotations) {
|
|
1931
|
-
annotationDataList.push(__spreadProps(__spreadValues({
|
|
2030
|
+
annotationDataList.push(__spreadValues(__spreadProps(__spreadValues({
|
|
1932
2031
|
id: annotation.id,
|
|
1933
2032
|
type: annotation.type,
|
|
1934
2033
|
instruction: annotation.type === "text" ? annotation.text : void 0
|
|
1935
2034
|
}, annotation.linkedSelector ? { linkedSelector: annotation.linkedSelector } : {}), {
|
|
1936
2035
|
// Use stored elements (captured at creation time) or empty array
|
|
1937
2036
|
elements: annotation.elements || []
|
|
1938
|
-
}));
|
|
2037
|
+
}), annotation.imageCount ? { imageCount: annotation.imageCount } : {}));
|
|
1939
2038
|
}
|
|
1940
2039
|
return __spreadValues({
|
|
1941
2040
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2076,7 +2175,8 @@ function drawAnnotationsToCanvas(ctx, annotations, scrollY, dpr) {
|
|
|
2076
2175
|
const fontSize = annotation.fontSize || 16;
|
|
2077
2176
|
ctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
2078
2177
|
ctx.fillStyle = annotation.color;
|
|
2079
|
-
const
|
|
2178
|
+
const displayText = annotation.imageCount && annotation.imageCount > 0 ? `[${annotation.imageCount} image${annotation.imageCount > 1 ? "s" : ""}] ${annotation.text}` : annotation.text;
|
|
2179
|
+
const lines = displayText.split("\n");
|
|
2080
2180
|
const lineHeight = fontSize * 1.2;
|
|
2081
2181
|
const padding = 4;
|
|
2082
2182
|
let maxWidth = 0;
|
|
@@ -3706,6 +3806,16 @@ function PaddingHandles({ element, padding, accentColor, hoveredSide, draggingSi
|
|
|
3706
3806
|
// src/components/StylePanel.tsx
|
|
3707
3807
|
import { useCallback as useCallback4, useEffect as useEffect12, useMemo, useRef as useRef4, useState as useState9 } from "react";
|
|
3708
3808
|
import { AlignCenter, AlignHorizontalSpaceAround, AlignJustify, AlignLeft, AlignRight, AlignVerticalSpaceAround, Baseline, Check, ChevronDown, Columns3, Grid2x2, MoveHorizontal, Plus, RectangleHorizontal, RotateCcw, Rows3, Shrink, UnfoldHorizontal, UnfoldVertical, WholeWord, X } from "lucide-react";
|
|
3809
|
+
|
|
3810
|
+
// src/styles/border.ts
|
|
3811
|
+
var DIAG_SVG = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMicgaGVpZ2h0PScxMic+PGRlZnM+PHBhdHRlcm4gaWQ9J2QnIHdpZHRoPSc0JyBoZWlnaHQ9JzQnIHBhdHRlcm5Vbml0cz0ndXNlclNwYWNlT25Vc2UnPjxwYXRoIGQ9J00tMSwxIGwyLC0yIE0wLDQgbDQsLTQgTTMsNSBsMiwtMicgc3Ryb2tlPSdibGFjaycgc3Ryb2tlLXdpZHRoPScuNScvPjwvcGF0dGVybj48L2RlZnM+PHJlY3Qgd2lkdGg9JzEyJyBoZWlnaHQ9JzEyJyBmaWxsPSd1cmwoI2QpJy8+PC9zdmc+";
|
|
3812
|
+
var POPMELT_BORDER = {
|
|
3813
|
+
borderWidth: 3,
|
|
3814
|
+
borderStyle: "solid",
|
|
3815
|
+
borderImage: `url("${DIAG_SVG}") 4 / 1.9 / 0 round`
|
|
3816
|
+
};
|
|
3817
|
+
|
|
3818
|
+
// src/components/StylePanel.tsx
|
|
3709
3819
|
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3710
3820
|
function colorWithAlpha6(color, alpha) {
|
|
3711
3821
|
const oklchMatch = color.match(/^oklch\(([^)]+)\)$/i);
|
|
@@ -4675,10 +4785,16 @@ function UnitInput({
|
|
|
4675
4785
|
style: inputStyle,
|
|
4676
4786
|
placeholder,
|
|
4677
4787
|
showUnit = true,
|
|
4678
|
-
unitStyle: customUnitStyle
|
|
4788
|
+
unitStyle: customUnitStyle,
|
|
4789
|
+
preferredUnit,
|
|
4790
|
+
onUnitCycle
|
|
4679
4791
|
}) {
|
|
4680
4792
|
const parsed = parseValue(value);
|
|
4681
|
-
const
|
|
4793
|
+
const propertyDefault = getDefaultUnit(property);
|
|
4794
|
+
const units = PROPERTY_UNITS[property];
|
|
4795
|
+
const canUsePreference = preferredUnit && units && units.includes(preferredUnit);
|
|
4796
|
+
const defaultUnit = canUsePreference ? preferredUnit : propertyDefault;
|
|
4797
|
+
const effectiveUnit = isModified ? parsed.unit || defaultUnit : defaultUnit;
|
|
4682
4798
|
const displayNum = !isModified && parsed.unit && parsed.unit !== effectiveUnit ? convertFromPx(parsed.num, effectiveUnit) : parsed.num;
|
|
4683
4799
|
const [isFocused, setIsFocused] = useState9(false);
|
|
4684
4800
|
const [editText, setEditText] = useState9("");
|
|
@@ -4737,12 +4853,17 @@ function UnitInput({
|
|
|
4737
4853
|
const displayValue = isFocused ? editText : isNumericValue ? String(displayNum) : "";
|
|
4738
4854
|
const hasTypedUnit = isFocused && /\s*(rem|em|px|%)\s*$/i.test(editText);
|
|
4739
4855
|
const shownUnit = hasTypedUnit ? "" : effectiveUnit;
|
|
4856
|
+
const isUnitClickable = onUnitCycle && (shownUnit === "rem" || shownUnit === "px");
|
|
4740
4857
|
const defaultUnitSuffix = {
|
|
4741
4858
|
fontSize: 10,
|
|
4742
4859
|
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
4743
4860
|
color: "#999",
|
|
4744
4861
|
pointerEvents: "none"
|
|
4745
4862
|
};
|
|
4863
|
+
const clickableUnitStyle = __spreadProps(__spreadValues({}, customUnitStyle != null ? customUnitStyle : defaultUnitSuffix), {
|
|
4864
|
+
pointerEvents: "auto",
|
|
4865
|
+
cursor: "pointer"
|
|
4866
|
+
});
|
|
4746
4867
|
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
4747
4868
|
/* @__PURE__ */ jsx7(
|
|
4748
4869
|
"input",
|
|
@@ -4758,7 +4879,15 @@ function UnitInput({
|
|
|
4758
4879
|
style: inputStyle
|
|
4759
4880
|
}
|
|
4760
4881
|
),
|
|
4761
|
-
showUnit && shownUnit && /* @__PURE__ */ jsx7(
|
|
4882
|
+
showUnit && shownUnit && /* @__PURE__ */ jsx7(
|
|
4883
|
+
"span",
|
|
4884
|
+
{
|
|
4885
|
+
style: isUnitClickable ? clickableUnitStyle : customUnitStyle != null ? customUnitStyle : defaultUnitSuffix,
|
|
4886
|
+
onClick: isUnitClickable ? onUnitCycle : void 0,
|
|
4887
|
+
title: isUnitClickable ? "Click to switch units" : void 0,
|
|
4888
|
+
children: shownUnit
|
|
4889
|
+
}
|
|
4890
|
+
)
|
|
4762
4891
|
] });
|
|
4763
4892
|
}
|
|
4764
4893
|
function ColorInput({
|
|
@@ -5179,7 +5308,10 @@ function LayoutSection({
|
|
|
5179
5308
|
activeDropdown,
|
|
5180
5309
|
onDropdownChange,
|
|
5181
5310
|
panelContentRef,
|
|
5182
|
-
accentColor
|
|
5311
|
+
accentColor,
|
|
5312
|
+
onFieldHover,
|
|
5313
|
+
preferredUnit,
|
|
5314
|
+
onUnitCycle
|
|
5183
5315
|
}) {
|
|
5184
5316
|
const setActiveDropdown = onDropdownChange;
|
|
5185
5317
|
const display = getValue("display");
|
|
@@ -5207,7 +5339,10 @@ function LayoutSection({
|
|
|
5207
5339
|
const overflow = getValue("overflow");
|
|
5208
5340
|
const gridCols = gridTemplateCols.split(/\s+/).filter((v) => v && v !== "none").length || 1;
|
|
5209
5341
|
const gridRows = gridTemplateRows.split(/\s+/).filter((v) => v && v !== "none").length || 1;
|
|
5342
|
+
const [gridHovered, setGridHovered] = useState9(false);
|
|
5210
5343
|
const hasActiveDropdown = activeDropdown !== null;
|
|
5344
|
+
const dimSiblings = hasActiveDropdown || gridHovered;
|
|
5345
|
+
const siblingOpacity = hasActiveDropdown ? 0.3 : gridHovered ? 0.65 : 1;
|
|
5211
5346
|
const DisplayModeButton = ({ mode, icon, active }) => /* @__PURE__ */ jsx7(
|
|
5212
5347
|
"button",
|
|
5213
5348
|
{
|
|
@@ -5246,84 +5381,159 @@ function LayoutSection({
|
|
|
5246
5381
|
const v = value || "0";
|
|
5247
5382
|
handleChange("padding", `${v} ${current.right} ${v} ${current.left}`);
|
|
5248
5383
|
};
|
|
5249
|
-
const
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
const
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5384
|
+
const [scrubDisplay, setScrubDisplay] = useState9({});
|
|
5385
|
+
const scrubPreview = useCallback4((key, domUpdate) => (v) => {
|
|
5386
|
+
domUpdate(v);
|
|
5387
|
+
setScrubDisplay((prev) => __spreadProps(__spreadValues({}, prev), { [key]: v }));
|
|
5388
|
+
}, []);
|
|
5389
|
+
const clearScrub = useCallback4((key) => {
|
|
5390
|
+
setScrubDisplay((prev) => {
|
|
5391
|
+
const next = __spreadValues({}, prev);
|
|
5392
|
+
delete next[key];
|
|
5393
|
+
return next;
|
|
5394
|
+
});
|
|
5395
|
+
}, []);
|
|
5396
|
+
const previewPaddingHorizontal = useCallback4((v) => {
|
|
5397
|
+
const current = parseSpacing(getValue("padding"));
|
|
5398
|
+
applyInlineStyle(element, "padding", `${current.top} ${v} ${current.bottom} ${v}`);
|
|
5399
|
+
}, [element, getValue]);
|
|
5400
|
+
const previewPaddingVertical = useCallback4((v) => {
|
|
5401
|
+
const current = parseSpacing(getValue("padding"));
|
|
5402
|
+
applyInlineStyle(element, "padding", `${v} ${current.right} ${v} ${current.left}`);
|
|
5403
|
+
}, [element, getValue]);
|
|
5404
|
+
const previewProperty = useCallback4((property) => (v) => {
|
|
5405
|
+
applyInlineStyle(element, property, v);
|
|
5406
|
+
}, [element]);
|
|
5407
|
+
const isColumn = flexDirection === "column" || flexDirection === "column-reverse";
|
|
5408
|
+
const getAxisIndex = (val) => {
|
|
5409
|
+
if (val === "center") return 1;
|
|
5410
|
+
if (val === "flex-end" || val === "end") return 2;
|
|
5411
|
+
return 0;
|
|
5412
|
+
};
|
|
5413
|
+
const justifyIdx = getAxisIndex(getValue("justify-content"));
|
|
5414
|
+
const alignIdx = getAxisIndex(getValue("align-items"));
|
|
5415
|
+
const gridActiveCol = isColumn ? alignIdx : justifyIdx;
|
|
5416
|
+
const gridActiveRow = isColumn ? justifyIdx : alignIdx;
|
|
5417
|
+
const gridRef = useRef4(null);
|
|
5418
|
+
const gridSwipeAccum = useRef4({ x: 0, y: 0 });
|
|
5419
|
+
const gridPosRef = useRef4({ col: gridActiveCol, row: gridActiveRow });
|
|
5420
|
+
gridPosRef.current = { col: gridActiveCol, row: gridActiveRow };
|
|
5421
|
+
const applyGridPosition = useCallback4((col, row) => {
|
|
5422
|
+
const vals = ["flex-start", "center", "flex-end"];
|
|
5423
|
+
if (isColumn) {
|
|
5424
|
+
handleChange("justify-content", vals[row]);
|
|
5425
|
+
handleChange("align-items", vals[col]);
|
|
5426
|
+
} else {
|
|
5427
|
+
handleChange("justify-content", vals[col]);
|
|
5428
|
+
handleChange("align-items", vals[row]);
|
|
5429
|
+
}
|
|
5430
|
+
}, [isColumn, handleChange]);
|
|
5431
|
+
const applyGridRef = useRef4(applyGridPosition);
|
|
5432
|
+
applyGridRef.current = applyGridPosition;
|
|
5433
|
+
useEffect12(() => {
|
|
5434
|
+
const THRESHOLD = 30;
|
|
5435
|
+
const onWheel = (e) => {
|
|
5436
|
+
const grid = gridRef.current;
|
|
5437
|
+
if (!grid || !grid.contains(e.target)) return;
|
|
5438
|
+
e.preventDefault();
|
|
5439
|
+
e.stopPropagation();
|
|
5440
|
+
gridSwipeAccum.current.x += e.deltaX;
|
|
5441
|
+
gridSwipeAccum.current.y += e.deltaY;
|
|
5442
|
+
let { col, row } = gridPosRef.current;
|
|
5443
|
+
let moved = false;
|
|
5444
|
+
if (Math.abs(gridSwipeAccum.current.x) >= THRESHOLD) {
|
|
5445
|
+
col = Math.max(0, Math.min(2, col + (gridSwipeAccum.current.x > 0 ? 1 : -1)));
|
|
5446
|
+
gridSwipeAccum.current.x = 0;
|
|
5447
|
+
gridSwipeAccum.current.y = 0;
|
|
5448
|
+
moved = true;
|
|
5449
|
+
}
|
|
5450
|
+
if (!moved && Math.abs(gridSwipeAccum.current.y) >= THRESHOLD) {
|
|
5451
|
+
row = Math.max(0, Math.min(2, row + (gridSwipeAccum.current.y > 0 ? 1 : -1)));
|
|
5452
|
+
gridSwipeAccum.current.x = 0;
|
|
5453
|
+
gridSwipeAccum.current.y = 0;
|
|
5454
|
+
moved = true;
|
|
5455
|
+
}
|
|
5456
|
+
if (moved && (col !== gridPosRef.current.col || row !== gridPosRef.current.row)) {
|
|
5457
|
+
applyGridRef.current(col, row);
|
|
5278
5458
|
}
|
|
5279
5459
|
};
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5460
|
+
document.addEventListener("wheel", onWheel, { passive: false, capture: true });
|
|
5461
|
+
return () => document.removeEventListener("wheel", onWheel, { capture: true });
|
|
5462
|
+
}, []);
|
|
5463
|
+
const renderAlignmentGrid = () => /* @__PURE__ */ jsx7(
|
|
5464
|
+
"div",
|
|
5465
|
+
{
|
|
5466
|
+
ref: gridRef,
|
|
5467
|
+
onMouseEnter: () => {
|
|
5468
|
+
setGridHovered(true);
|
|
5469
|
+
if (panelContentRef.current) panelContentRef.current.style.overflowY = "hidden";
|
|
5470
|
+
},
|
|
5471
|
+
onMouseLeave: () => {
|
|
5472
|
+
setGridHovered(false);
|
|
5473
|
+
if (panelContentRef.current) panelContentRef.current.style.overflowY = "auto";
|
|
5474
|
+
},
|
|
5475
|
+
style: {
|
|
5476
|
+
width: 56,
|
|
5477
|
+
height: 56,
|
|
5478
|
+
backgroundColor: FIELD_BG,
|
|
5479
|
+
borderRadius: 2,
|
|
5480
|
+
display: "grid",
|
|
5481
|
+
gridTemplateColumns: "repeat(3, 1fr)",
|
|
5482
|
+
gridTemplateRows: "repeat(3, 1fr)",
|
|
5483
|
+
padding: 6,
|
|
5484
|
+
gap: 2,
|
|
5485
|
+
touchAction: "none"
|
|
5486
|
+
},
|
|
5487
|
+
children: [0, 1, 2].map(
|
|
5488
|
+
(row) => [0, 1, 2].map((col) => {
|
|
5489
|
+
const isActive = col === gridActiveCol && row === gridActiveRow;
|
|
5490
|
+
return /* @__PURE__ */ jsx7(
|
|
5491
|
+
"button",
|
|
5492
|
+
{
|
|
5493
|
+
type: "button",
|
|
5494
|
+
onClick: () => applyGridPosition(col, row),
|
|
5495
|
+
style: {
|
|
5496
|
+
width: "100%",
|
|
5497
|
+
height: "100%",
|
|
5498
|
+
display: "flex",
|
|
5499
|
+
alignItems: "center",
|
|
5500
|
+
justifyContent: "center",
|
|
5501
|
+
border: "none",
|
|
5502
|
+
backgroundColor: "transparent",
|
|
5503
|
+
cursor: "pointer",
|
|
5504
|
+
padding: 0
|
|
5505
|
+
},
|
|
5506
|
+
children: isActive ? /* @__PURE__ */ jsx7("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", style: { flexShrink: 0 }, children: col === 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
5507
|
+
/* @__PURE__ */ jsx7("rect", { x: "1", y: "1.5", width: "8", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5508
|
+
/* @__PURE__ */ jsx7("rect", { x: "1", y: "4.4", width: "5", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5509
|
+
/* @__PURE__ */ jsx7("rect", { x: "1", y: "7.3", width: "7", height: "1.2", rx: "0.5", fill: accentColor })
|
|
5510
|
+
] }) : col === 1 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
5511
|
+
/* @__PURE__ */ jsx7("rect", { x: "1", y: "1.5", width: "8", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5512
|
+
/* @__PURE__ */ jsx7("rect", { x: "2.5", y: "4.4", width: "5", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5513
|
+
/* @__PURE__ */ jsx7("rect", { x: "1.5", y: "7.3", width: "7", height: "1.2", rx: "0.5", fill: accentColor })
|
|
5514
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
5515
|
+
/* @__PURE__ */ jsx7("rect", { x: "1", y: "1.5", width: "8", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5516
|
+
/* @__PURE__ */ jsx7("rect", { x: "4", y: "4.4", width: "5", height: "1.2", rx: "0.5", fill: accentColor }),
|
|
5517
|
+
/* @__PURE__ */ jsx7("rect", { x: "2", y: "7.3", width: "7", height: "1.2", rx: "0.5", fill: accentColor })
|
|
5518
|
+
] }) }) : /* @__PURE__ */ jsx7("div", { style: {
|
|
5519
|
+
width: 5,
|
|
5520
|
+
height: 5,
|
|
5521
|
+
borderRadius: "50%",
|
|
5522
|
+
backgroundColor: "#aaa"
|
|
5523
|
+
} })
|
|
5308
5524
|
},
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
},
|
|
5316
|
-
`${row}-${col}`
|
|
5317
|
-
);
|
|
5318
|
-
})
|
|
5319
|
-
) });
|
|
5320
|
-
};
|
|
5525
|
+
`${row}-${col}`
|
|
5526
|
+
);
|
|
5527
|
+
})
|
|
5528
|
+
)
|
|
5529
|
+
}
|
|
5530
|
+
);
|
|
5321
5531
|
const gridModified = isModified("grid-template-columns") || isModified("grid-template-rows");
|
|
5322
5532
|
const sectionTitle = isFlexOrGrid2 ? "Auto layout" : "Layout";
|
|
5323
5533
|
return /* @__PURE__ */ jsxs6("div", { style: { borderBottom: "1px solid rgba(0,0,0,0.08)" }, children: [
|
|
5324
5534
|
/* @__PURE__ */ jsx7("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsx7("span", { children: sectionTitle }) }),
|
|
5325
5535
|
/* @__PURE__ */ jsxs6("div", { style: { padding: "8px 12px" }, children: [
|
|
5326
|
-
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 2, marginBottom: 8, backgroundColor: FIELD_BG, borderRadius: 2, padding: 2, opacity:
|
|
5536
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 2, marginBottom: 8, backgroundColor: FIELD_BG, borderRadius: 2, padding: 2, opacity: siblingOpacity, transition: "opacity 150ms ease" }, children: [
|
|
5327
5537
|
/* @__PURE__ */ jsx7(DisplayModeButton, { mode: "block", icon: /* @__PURE__ */ jsx7(RectangleHorizontal, { size: 16 }), active: displayMode === "block" }),
|
|
5328
5538
|
/* @__PURE__ */ jsx7(DisplayModeButton, { mode: "flex-col", icon: /* @__PURE__ */ jsx7(Rows3, { size: 16 }), active: displayMode === "flex-col" }),
|
|
5329
5539
|
/* @__PURE__ */ jsx7(DisplayModeButton, { mode: "flex-row", icon: /* @__PURE__ */ jsx7(Columns3, { size: 16 }), active: displayMode === "flex-row" }),
|
|
@@ -5397,9 +5607,9 @@ function LayoutSection({
|
|
|
5397
5607
|
}
|
|
5398
5608
|
)
|
|
5399
5609
|
] }),
|
|
5400
|
-
isFlex && /* @__PURE__ */ jsxs6("div", {
|
|
5401
|
-
/* @__PURE__ */ jsx7(
|
|
5402
|
-
/* @__PURE__ */ jsxs6("div", { style: { flex: 1 }, children: [
|
|
5610
|
+
isFlex && /* @__PURE__ */ jsxs6("div", { onMouseEnter: () => onFieldHover == null ? void 0 : onFieldHover("gap"), onMouseLeave: () => onFieldHover == null ? void 0 : onFieldHover("element"), style: { display: "flex", gap: 8, marginBottom: 8 }, children: [
|
|
5611
|
+
/* @__PURE__ */ jsx7("div", { style: { opacity: hasActiveDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: renderAlignmentGrid() }),
|
|
5612
|
+
/* @__PURE__ */ jsxs6("div", { style: { flex: 1, opacity: siblingOpacity, transition: "opacity 150ms ease" }, children: [
|
|
5403
5613
|
/* @__PURE__ */ jsx7(
|
|
5404
5614
|
"div",
|
|
5405
5615
|
{
|
|
@@ -5418,17 +5628,19 @@ function LayoutSection({
|
|
|
5418
5628
|
),
|
|
5419
5629
|
/* @__PURE__ */ jsx7(FieldWrapper, { dimmed: hasActiveDropdown, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5420
5630
|
/* @__PURE__ */ jsx7(
|
|
5421
|
-
|
|
5631
|
+
ScrubLabel,
|
|
5422
5632
|
{
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
padding: "0 4px",
|
|
5428
|
-
display: "flex",
|
|
5429
|
-
alignItems: "center",
|
|
5430
|
-
cursor: isModified("gap") ? "pointer" : "default"
|
|
5633
|
+
value: gap,
|
|
5634
|
+
onChange: (v) => {
|
|
5635
|
+
clearScrub("gap");
|
|
5636
|
+
handleChange("gap", v);
|
|
5431
5637
|
},
|
|
5638
|
+
onPreview: scrubPreview("gap", previewProperty("gap")),
|
|
5639
|
+
onScrubEnd: () => clearScrub("gap"),
|
|
5640
|
+
onReset: () => onResetProperty("gap"),
|
|
5641
|
+
isModified: isModified("gap"),
|
|
5642
|
+
accentColor,
|
|
5643
|
+
defaultUnit: preferredUnit,
|
|
5432
5644
|
children: flexDirection === "column" || flexDirection === "column-reverse" ? /* @__PURE__ */ jsx7(UnfoldVertical, { size: 12, strokeWidth: isModified("gap") ? 2.5 : 1.5 }) : /* @__PURE__ */ jsx7(UnfoldHorizontal, { size: 12, strokeWidth: isModified("gap") ? 2.5 : 1.5 })
|
|
5433
5645
|
}
|
|
5434
5646
|
),
|
|
@@ -5436,17 +5648,19 @@ function LayoutSection({
|
|
|
5436
5648
|
UnitInput,
|
|
5437
5649
|
{
|
|
5438
5650
|
property: "gap",
|
|
5439
|
-
value: gap,
|
|
5651
|
+
value: scrubDisplay["gap"] || gap,
|
|
5440
5652
|
onChange: (v) => handleChange("gap", v),
|
|
5441
|
-
isModified: isModified("gap"),
|
|
5653
|
+
isModified: isModified("gap") || "gap" in scrubDisplay,
|
|
5442
5654
|
style: __spreadProps(__spreadValues({}, compactInputStyle), { flex: 1, minWidth: 0 }),
|
|
5443
|
-
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" }
|
|
5655
|
+
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" },
|
|
5656
|
+
preferredUnit,
|
|
5657
|
+
onUnitCycle
|
|
5444
5658
|
}
|
|
5445
5659
|
)
|
|
5446
5660
|
] }) })
|
|
5447
5661
|
] })
|
|
5448
5662
|
] }),
|
|
5449
|
-
isGrid && /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8, marginBottom: 8, opacity:
|
|
5663
|
+
isGrid && /* @__PURE__ */ jsxs6("div", { onMouseEnter: () => onFieldHover == null ? void 0 : onFieldHover("gap"), onMouseLeave: () => onFieldHover == null ? void 0 : onFieldHover("element"), style: { display: "flex", gap: 8, marginBottom: 8, opacity: siblingOpacity, transition: "opacity 150ms ease" }, children: [
|
|
5450
5664
|
/* @__PURE__ */ jsx7(
|
|
5451
5665
|
GridDimensions,
|
|
5452
5666
|
{
|
|
@@ -5461,17 +5675,19 @@ function LayoutSection({
|
|
|
5461
5675
|
/* @__PURE__ */ jsxs6("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 4 }, children: [
|
|
5462
5676
|
/* @__PURE__ */ jsx7(FieldWrapper, { dimmed: hasActiveDropdown, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5463
5677
|
/* @__PURE__ */ jsx7(
|
|
5464
|
-
|
|
5678
|
+
ScrubLabel,
|
|
5465
5679
|
{
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
padding: "0 4px",
|
|
5471
|
-
display: "flex",
|
|
5472
|
-
alignItems: "center",
|
|
5473
|
-
cursor: isModified("column-gap") ? "pointer" : "default"
|
|
5680
|
+
value: columnGap || gap,
|
|
5681
|
+
onChange: (v) => {
|
|
5682
|
+
clearScrub("column-gap");
|
|
5683
|
+
handleChange("column-gap", v);
|
|
5474
5684
|
},
|
|
5685
|
+
onPreview: scrubPreview("column-gap", previewProperty("column-gap")),
|
|
5686
|
+
onScrubEnd: () => clearScrub("column-gap"),
|
|
5687
|
+
onReset: () => onResetProperty("column-gap"),
|
|
5688
|
+
isModified: isModified("column-gap"),
|
|
5689
|
+
accentColor,
|
|
5690
|
+
defaultUnit: preferredUnit,
|
|
5475
5691
|
children: /* @__PURE__ */ jsx7(UnfoldHorizontal, { size: 12, strokeWidth: isModified("column-gap") ? 2.5 : 1.5 })
|
|
5476
5692
|
}
|
|
5477
5693
|
),
|
|
@@ -5479,28 +5695,32 @@ function LayoutSection({
|
|
|
5479
5695
|
UnitInput,
|
|
5480
5696
|
{
|
|
5481
5697
|
property: "column-gap",
|
|
5482
|
-
value: columnGap || gap,
|
|
5698
|
+
value: scrubDisplay["column-gap"] || columnGap || gap,
|
|
5483
5699
|
onChange: (v) => handleChange("column-gap", v),
|
|
5484
|
-
isModified: isModified("column-gap"),
|
|
5700
|
+
isModified: isModified("column-gap") || "column-gap" in scrubDisplay,
|
|
5485
5701
|
placeholder: "col",
|
|
5486
5702
|
style: __spreadProps(__spreadValues({}, compactInputStyle), { flex: 1, minWidth: 0 }),
|
|
5487
|
-
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" }
|
|
5703
|
+
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" },
|
|
5704
|
+
preferredUnit,
|
|
5705
|
+
onUnitCycle
|
|
5488
5706
|
}
|
|
5489
5707
|
)
|
|
5490
5708
|
] }) }),
|
|
5491
5709
|
/* @__PURE__ */ jsx7(FieldWrapper, { dimmed: hasActiveDropdown, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5492
5710
|
/* @__PURE__ */ jsx7(
|
|
5493
|
-
|
|
5711
|
+
ScrubLabel,
|
|
5494
5712
|
{
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
padding: "0 4px",
|
|
5500
|
-
display: "flex",
|
|
5501
|
-
alignItems: "center",
|
|
5502
|
-
cursor: isModified("row-gap") ? "pointer" : "default"
|
|
5713
|
+
value: rowGap || gap,
|
|
5714
|
+
onChange: (v) => {
|
|
5715
|
+
clearScrub("row-gap");
|
|
5716
|
+
handleChange("row-gap", v);
|
|
5503
5717
|
},
|
|
5718
|
+
onPreview: scrubPreview("row-gap", previewProperty("row-gap")),
|
|
5719
|
+
onScrubEnd: () => clearScrub("row-gap"),
|
|
5720
|
+
onReset: () => onResetProperty("row-gap"),
|
|
5721
|
+
isModified: isModified("row-gap"),
|
|
5722
|
+
accentColor,
|
|
5723
|
+
defaultUnit: preferredUnit,
|
|
5504
5724
|
children: /* @__PURE__ */ jsx7(UnfoldVertical, { size: 12, strokeWidth: isModified("row-gap") ? 2.5 : 1.5 })
|
|
5505
5725
|
}
|
|
5506
5726
|
),
|
|
@@ -5508,31 +5728,36 @@ function LayoutSection({
|
|
|
5508
5728
|
UnitInput,
|
|
5509
5729
|
{
|
|
5510
5730
|
property: "row-gap",
|
|
5511
|
-
value: rowGap || gap,
|
|
5731
|
+
value: scrubDisplay["row-gap"] || rowGap || gap,
|
|
5512
5732
|
onChange: (v) => handleChange("row-gap", v),
|
|
5513
|
-
isModified: isModified("row-gap"),
|
|
5733
|
+
isModified: isModified("row-gap") || "row-gap" in scrubDisplay,
|
|
5514
5734
|
placeholder: "row",
|
|
5515
5735
|
style: __spreadProps(__spreadValues({}, compactInputStyle), { flex: 1, minWidth: 0 }),
|
|
5516
|
-
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" }
|
|
5736
|
+
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" },
|
|
5737
|
+
preferredUnit,
|
|
5738
|
+
onUnitCycle
|
|
5517
5739
|
}
|
|
5518
5740
|
)
|
|
5519
5741
|
] }) })
|
|
5520
5742
|
] })
|
|
5521
5743
|
] }),
|
|
5522
|
-
isFlexOrGrid2 && /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 4, marginBottom: 8, opacity:
|
|
5744
|
+
isFlexOrGrid2 && /* @__PURE__ */ jsxs6("div", { onMouseEnter: () => onFieldHover == null ? void 0 : onFieldHover("padding"), onMouseLeave: () => onFieldHover == null ? void 0 : onFieldHover("element"), style: { display: "flex", gap: 4, marginBottom: 8, opacity: siblingOpacity, transition: "opacity 150ms ease" }, children: [
|
|
5523
5745
|
/* @__PURE__ */ jsx7(FieldWrapper, { style: { flex: 1 }, dimmed: hasActiveDropdown, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5524
5746
|
/* @__PURE__ */ jsx7(
|
|
5525
|
-
|
|
5747
|
+
ScrubLabel,
|
|
5526
5748
|
{
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
padding: "0 4px",
|
|
5532
|
-
display: "flex",
|
|
5533
|
-
alignItems: "center",
|
|
5534
|
-
cursor: isModified("padding") ? "pointer" : "default"
|
|
5749
|
+
value: padding.left,
|
|
5750
|
+
onChange: (v) => {
|
|
5751
|
+
clearScrub("padding-h");
|
|
5752
|
+
handlePaddingHorizontal(v);
|
|
5535
5753
|
},
|
|
5754
|
+
onPreview: scrubPreview("padding-h", previewPaddingHorizontal),
|
|
5755
|
+
onScrubEnd: () => clearScrub("padding-h"),
|
|
5756
|
+
onReset: () => onResetProperty("padding"),
|
|
5757
|
+
isModified: isModified("padding"),
|
|
5758
|
+
accentColor,
|
|
5759
|
+
defaultUnit: preferredUnit,
|
|
5760
|
+
snapSteps: PADDING_SNAP_STEPS,
|
|
5536
5761
|
children: /* @__PURE__ */ jsx7(AlignHorizontalSpaceAround, { size: 12, strokeWidth: isModified("padding") ? 2.5 : 1.5 })
|
|
5537
5762
|
}
|
|
5538
5763
|
),
|
|
@@ -5540,28 +5765,33 @@ function LayoutSection({
|
|
|
5540
5765
|
UnitInput,
|
|
5541
5766
|
{
|
|
5542
5767
|
property: "padding",
|
|
5543
|
-
value: padding.left,
|
|
5768
|
+
value: scrubDisplay["padding-h"] || padding.left,
|
|
5544
5769
|
onChange: (v) => handlePaddingHorizontal(v),
|
|
5545
|
-
isModified: isModified("padding"),
|
|
5770
|
+
isModified: isModified("padding") || "padding-h" in scrubDisplay,
|
|
5546
5771
|
placeholder: "H pad",
|
|
5547
5772
|
style: __spreadProps(__spreadValues({}, compactInputStyle), { flex: 1, minWidth: 0 }),
|
|
5548
|
-
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" }
|
|
5773
|
+
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" },
|
|
5774
|
+
preferredUnit,
|
|
5775
|
+
onUnitCycle
|
|
5549
5776
|
}
|
|
5550
5777
|
)
|
|
5551
5778
|
] }) }),
|
|
5552
5779
|
/* @__PURE__ */ jsx7(FieldWrapper, { style: { flex: 1 }, dimmed: hasActiveDropdown, children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5553
5780
|
/* @__PURE__ */ jsx7(
|
|
5554
|
-
|
|
5781
|
+
ScrubLabel,
|
|
5555
5782
|
{
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
padding: "0 4px",
|
|
5561
|
-
display: "flex",
|
|
5562
|
-
alignItems: "center",
|
|
5563
|
-
cursor: isModified("padding") ? "pointer" : "default"
|
|
5783
|
+
value: padding.top,
|
|
5784
|
+
onChange: (v) => {
|
|
5785
|
+
clearScrub("padding-v");
|
|
5786
|
+
handlePaddingVertical(v);
|
|
5564
5787
|
},
|
|
5788
|
+
onPreview: scrubPreview("padding-v", previewPaddingVertical),
|
|
5789
|
+
onScrubEnd: () => clearScrub("padding-v"),
|
|
5790
|
+
onReset: () => onResetProperty("padding"),
|
|
5791
|
+
isModified: isModified("padding"),
|
|
5792
|
+
accentColor,
|
|
5793
|
+
defaultUnit: preferredUnit,
|
|
5794
|
+
snapSteps: PADDING_SNAP_STEPS,
|
|
5565
5795
|
children: /* @__PURE__ */ jsx7(AlignVerticalSpaceAround, { size: 12, strokeWidth: isModified("padding") ? 2.5 : 1.5 })
|
|
5566
5796
|
}
|
|
5567
5797
|
),
|
|
@@ -5569,17 +5799,19 @@ function LayoutSection({
|
|
|
5569
5799
|
UnitInput,
|
|
5570
5800
|
{
|
|
5571
5801
|
property: "padding",
|
|
5572
|
-
value: padding.top,
|
|
5802
|
+
value: scrubDisplay["padding-v"] || padding.top,
|
|
5573
5803
|
onChange: (v) => handlePaddingVertical(v),
|
|
5574
|
-
isModified: isModified("padding"),
|
|
5804
|
+
isModified: isModified("padding") || "padding-v" in scrubDisplay,
|
|
5575
5805
|
placeholder: "V pad",
|
|
5576
5806
|
style: __spreadProps(__spreadValues({}, compactInputStyle), { flex: 1, minWidth: 0 }),
|
|
5577
|
-
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" }
|
|
5807
|
+
unitStyle: { fontSize: 10, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#999", padding: "0 8px" },
|
|
5808
|
+
preferredUnit,
|
|
5809
|
+
onUnitCycle
|
|
5578
5810
|
}
|
|
5579
5811
|
)
|
|
5580
5812
|
] }) })
|
|
5581
5813
|
] }),
|
|
5582
|
-
/* @__PURE__ */ jsxs6("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer", fontSize: 11, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#64748b", opacity:
|
|
5814
|
+
/* @__PURE__ */ jsxs6("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer", fontSize: 11, fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace', color: "#64748b", opacity: siblingOpacity, transition: "opacity 150ms ease" }, children: [
|
|
5583
5815
|
/* @__PURE__ */ jsx7(
|
|
5584
5816
|
"input",
|
|
5585
5817
|
{
|
|
@@ -5618,7 +5850,9 @@ function TypographySection({
|
|
|
5618
5850
|
colorVariables,
|
|
5619
5851
|
activeColorDropdown,
|
|
5620
5852
|
onColorDropdownChange,
|
|
5621
|
-
panelContentRef
|
|
5853
|
+
panelContentRef,
|
|
5854
|
+
preferredUnit,
|
|
5855
|
+
onUnitCycle
|
|
5622
5856
|
}) {
|
|
5623
5857
|
var _a;
|
|
5624
5858
|
const fontFamily = getValue("font-family");
|
|
@@ -5717,9 +5951,10 @@ function TypographySection({
|
|
|
5717
5951
|
transform: "translateY(-50%)",
|
|
5718
5952
|
fontSize: 10,
|
|
5719
5953
|
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
5720
|
-
color: "#999"
|
|
5721
|
-
|
|
5722
|
-
|
|
5954
|
+
color: "#999"
|
|
5955
|
+
},
|
|
5956
|
+
preferredUnit,
|
|
5957
|
+
onUnitCycle
|
|
5723
5958
|
}
|
|
5724
5959
|
) }) })
|
|
5725
5960
|
] }),
|
|
@@ -5820,6 +6055,130 @@ function parseValue(value) {
|
|
|
5820
6055
|
}
|
|
5821
6056
|
return { num: 0, unit: "" };
|
|
5822
6057
|
}
|
|
6058
|
+
var PADDING_SNAP_STEPS = [0, 1, 2, 4, 8, 12, 16, 20, 24, 28, 32];
|
|
6059
|
+
function ScrubLabel({
|
|
6060
|
+
value,
|
|
6061
|
+
onChange,
|
|
6062
|
+
onPreview,
|
|
6063
|
+
onScrubEnd,
|
|
6064
|
+
onReset,
|
|
6065
|
+
isModified,
|
|
6066
|
+
accentColor,
|
|
6067
|
+
defaultUnit = "rem",
|
|
6068
|
+
snapSteps,
|
|
6069
|
+
color,
|
|
6070
|
+
style,
|
|
6071
|
+
children
|
|
6072
|
+
}) {
|
|
6073
|
+
const ref = useRef4(null);
|
|
6074
|
+
const scrub = useRef4(null);
|
|
6075
|
+
const resetRef = useRef4(onReset);
|
|
6076
|
+
const modifiedRef = useRef4(isModified);
|
|
6077
|
+
const lastShiftRef = useRef4(false);
|
|
6078
|
+
resetRef.current = onReset;
|
|
6079
|
+
modifiedRef.current = isModified;
|
|
6080
|
+
useEffect12(() => {
|
|
6081
|
+
const onMove = (e) => {
|
|
6082
|
+
const s = scrub.current;
|
|
6083
|
+
if (!s) return;
|
|
6084
|
+
s.hasMoved = true;
|
|
6085
|
+
lastShiftRef.current = e.shiftKey;
|
|
6086
|
+
const sens = s.unit === "rem" || s.unit === "em" ? 0.1 : 1;
|
|
6087
|
+
s.accum += e.movementX * sens;
|
|
6088
|
+
let newVal = Math.max(0, Math.round((s.startValue + s.accum) * 10) / 10);
|
|
6089
|
+
if (e.shiftKey && snapSteps) {
|
|
6090
|
+
const rootFs = s.unit === "rem" || s.unit === "em" ? parseFloat(getComputedStyle(document.documentElement).fontSize) || 16 : 1;
|
|
6091
|
+
const pxVal = s.unit === "rem" || s.unit === "em" ? newVal * rootFs : newVal;
|
|
6092
|
+
let snapped = snapSteps[snapSteps.length - 1];
|
|
6093
|
+
for (let i = 0; i < snapSteps.length - 1; i++) {
|
|
6094
|
+
const lo = snapSteps[i];
|
|
6095
|
+
const hi = snapSteps[i + 1];
|
|
6096
|
+
if (pxVal <= (lo + hi) / 2) {
|
|
6097
|
+
snapped = lo;
|
|
6098
|
+
break;
|
|
6099
|
+
}
|
|
6100
|
+
if (pxVal < hi) {
|
|
6101
|
+
snapped = hi;
|
|
6102
|
+
break;
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
6105
|
+
if (pxVal > snapSteps[snapSteps.length - 1]) {
|
|
6106
|
+
snapped = Math.round(pxVal / 8) * 8;
|
|
6107
|
+
}
|
|
6108
|
+
newVal = s.unit === "rem" || s.unit === "em" ? Math.round(snapped / rootFs * 1e3) / 1e3 : snapped;
|
|
6109
|
+
}
|
|
6110
|
+
onPreview == null ? void 0 : onPreview(`${newVal}${s.unit}`);
|
|
6111
|
+
};
|
|
6112
|
+
const onUp = () => {
|
|
6113
|
+
const s = scrub.current;
|
|
6114
|
+
if (!s) return;
|
|
6115
|
+
let finalVal = Math.max(0, Math.round((s.startValue + s.accum) * 10) / 10);
|
|
6116
|
+
if (lastShiftRef.current && snapSteps) {
|
|
6117
|
+
const rootFs = s.unit === "rem" || s.unit === "em" ? parseFloat(getComputedStyle(document.documentElement).fontSize) || 16 : 1;
|
|
6118
|
+
const pxVal = s.unit === "rem" || s.unit === "em" ? finalVal * rootFs : finalVal;
|
|
6119
|
+
let snapped = snapSteps[snapSteps.length - 1];
|
|
6120
|
+
for (let i = 0; i < snapSteps.length - 1; i++) {
|
|
6121
|
+
const lo = snapSteps[i];
|
|
6122
|
+
const hi = snapSteps[i + 1];
|
|
6123
|
+
if (pxVal <= (lo + hi) / 2) {
|
|
6124
|
+
snapped = lo;
|
|
6125
|
+
break;
|
|
6126
|
+
}
|
|
6127
|
+
if (pxVal < hi) {
|
|
6128
|
+
snapped = hi;
|
|
6129
|
+
break;
|
|
6130
|
+
}
|
|
6131
|
+
}
|
|
6132
|
+
if (pxVal > snapSteps[snapSteps.length - 1]) {
|
|
6133
|
+
snapped = Math.round(pxVal / 8) * 8;
|
|
6134
|
+
}
|
|
6135
|
+
finalVal = s.unit === "rem" || s.unit === "em" ? Math.round(snapped / rootFs * 1e3) / 1e3 : snapped;
|
|
6136
|
+
}
|
|
6137
|
+
const changed = s.hasMoved && finalVal !== s.startValue;
|
|
6138
|
+
scrub.current = null;
|
|
6139
|
+
document.exitPointerLock();
|
|
6140
|
+
if (changed) {
|
|
6141
|
+
onChange(`${finalVal}${s.unit}`);
|
|
6142
|
+
} else if (s.hasMoved) {
|
|
6143
|
+
onPreview == null ? void 0 : onPreview(`${s.startValue}${s.unit}`);
|
|
6144
|
+
} else if (modifiedRef.current && resetRef.current) {
|
|
6145
|
+
resetRef.current();
|
|
6146
|
+
}
|
|
6147
|
+
onScrubEnd == null ? void 0 : onScrubEnd();
|
|
6148
|
+
};
|
|
6149
|
+
document.addEventListener("mousemove", onMove);
|
|
6150
|
+
document.addEventListener("mouseup", onUp);
|
|
6151
|
+
return () => {
|
|
6152
|
+
document.removeEventListener("mousemove", onMove);
|
|
6153
|
+
document.removeEventListener("mouseup", onUp);
|
|
6154
|
+
};
|
|
6155
|
+
}, [onChange, onPreview, onScrubEnd]);
|
|
6156
|
+
const onMouseDown = useCallback4((e) => {
|
|
6157
|
+
var _a;
|
|
6158
|
+
if (e.button !== 0) return;
|
|
6159
|
+
e.preventDefault();
|
|
6160
|
+
const parsed = parseValue(value);
|
|
6161
|
+
const unit = parsed.unit && parsed.unit !== "px" ? parsed.unit : defaultUnit;
|
|
6162
|
+
scrub.current = { startValue: parsed.num, unit, accum: 0, hasMoved: false };
|
|
6163
|
+
(_a = ref.current) == null ? void 0 : _a.requestPointerLock();
|
|
6164
|
+
}, [value, defaultUnit]);
|
|
6165
|
+
return /* @__PURE__ */ jsx7(
|
|
6166
|
+
"span",
|
|
6167
|
+
{
|
|
6168
|
+
ref,
|
|
6169
|
+
onMouseDown,
|
|
6170
|
+
title: isModified ? "Click to reset \xB7 Drag to scrub" : "Drag to scrub",
|
|
6171
|
+
style: __spreadValues({
|
|
6172
|
+
color: isModified ? accentColor || "#3b82f6" : color || "#999",
|
|
6173
|
+
padding: "0 4px",
|
|
6174
|
+
display: "flex",
|
|
6175
|
+
alignItems: "center",
|
|
6176
|
+
cursor: "ew-resize"
|
|
6177
|
+
}, style),
|
|
6178
|
+
children
|
|
6179
|
+
}
|
|
6180
|
+
);
|
|
6181
|
+
}
|
|
5823
6182
|
function StylePanel({
|
|
5824
6183
|
element,
|
|
5825
6184
|
elementInfo,
|
|
@@ -5827,19 +6186,31 @@ function StylePanel({
|
|
|
5827
6186
|
styleModifications,
|
|
5828
6187
|
dispatch,
|
|
5829
6188
|
onClose,
|
|
6189
|
+
onHover,
|
|
5830
6190
|
accentColor = "#3b82f6"
|
|
5831
6191
|
}) {
|
|
5832
6192
|
var _a, _b;
|
|
5833
6193
|
const panelRef = useRef4(null);
|
|
5834
6194
|
const panelContentRef = useRef4(null);
|
|
5835
|
-
const [visible, setVisible] = useState9(
|
|
6195
|
+
const [visible, setVisible] = useState9(() => {
|
|
6196
|
+
try {
|
|
6197
|
+
return !!localStorage.getItem("devtools-panel-position");
|
|
6198
|
+
} catch (e) {
|
|
6199
|
+
return false;
|
|
6200
|
+
}
|
|
6201
|
+
});
|
|
5836
6202
|
useEffect12(() => {
|
|
6203
|
+
if (visible) return;
|
|
5837
6204
|
const id = setTimeout(() => setVisible(true), 50);
|
|
5838
6205
|
return () => clearTimeout(id);
|
|
5839
|
-
}, []);
|
|
6206
|
+
}, [visible]);
|
|
5840
6207
|
const [activeDropdown, setActiveDropdown] = useState9(null);
|
|
5841
6208
|
const [activeColorDropdown, setActiveColorDropdown] = useState9(null);
|
|
5842
6209
|
const hasActiveDropdown = activeDropdown !== null || activeColorDropdown !== null;
|
|
6210
|
+
const [preferredUnit, setPreferredUnit] = useState9("rem");
|
|
6211
|
+
const cycleUnit = useCallback4(() => {
|
|
6212
|
+
setPreferredUnit((u) => u === "rem" ? "px" : "rem");
|
|
6213
|
+
}, []);
|
|
5843
6214
|
const originalValuesRef = useRef4(/* @__PURE__ */ new Map());
|
|
5844
6215
|
const [rawCss, setRawCss] = useState9("");
|
|
5845
6216
|
const colorVariables = useMemo(() => getColorVariables(), []);
|
|
@@ -5856,36 +6227,121 @@ function StylePanel({
|
|
|
5856
6227
|
}, [onClose]);
|
|
5857
6228
|
const positionRef = useRef4({ top: 0, left: 0, maxHeight: 400 });
|
|
5858
6229
|
const [, forceUpdate] = useState9(0);
|
|
6230
|
+
const PANEL_POS_KEY = "devtools-panel-position";
|
|
6231
|
+
const dragOffset = useRef4({ x: 0, y: 0 });
|
|
6232
|
+
const dragState = useRef4(null);
|
|
6233
|
+
const hasSavedPosition = useRef4(false);
|
|
6234
|
+
useEffect12(() => {
|
|
6235
|
+
try {
|
|
6236
|
+
const stored = localStorage.getItem(PANEL_POS_KEY);
|
|
6237
|
+
if (stored) {
|
|
6238
|
+
const pos = JSON.parse(stored);
|
|
6239
|
+
if (typeof pos.top === "number" && typeof pos.left === "number") {
|
|
6240
|
+
hasSavedPosition.current = true;
|
|
6241
|
+
positionRef.current = __spreadProps(__spreadValues({}, positionRef.current), { top: pos.top, left: pos.left });
|
|
6242
|
+
}
|
|
6243
|
+
}
|
|
6244
|
+
} catch (e) {
|
|
6245
|
+
}
|
|
6246
|
+
}, []);
|
|
6247
|
+
useEffect12(() => {
|
|
6248
|
+
const onMouseMove = (e) => {
|
|
6249
|
+
const ds = dragState.current;
|
|
6250
|
+
if (!ds) return;
|
|
6251
|
+
const rawX = ds.startOffsetX + (e.clientX - ds.startX);
|
|
6252
|
+
const rawY = ds.startOffsetY + (e.clientY - ds.startY);
|
|
6253
|
+
const panelWidth = 280;
|
|
6254
|
+
const edgePad = 16;
|
|
6255
|
+
const clampedLeft = Math.max(edgePad, Math.min(window.innerWidth - panelWidth - edgePad, positionRef.current.left + rawX));
|
|
6256
|
+
const clampedTop = Math.max(edgePad, positionRef.current.top + rawY);
|
|
6257
|
+
dragOffset.current = {
|
|
6258
|
+
x: clampedLeft - positionRef.current.left,
|
|
6259
|
+
y: clampedTop - positionRef.current.top
|
|
6260
|
+
};
|
|
6261
|
+
const panel = panelRef.current;
|
|
6262
|
+
const wrapper = panel == null ? void 0 : panel.parentElement;
|
|
6263
|
+
if (!wrapper) return;
|
|
6264
|
+
wrapper.style.top = `${clampedTop}px`;
|
|
6265
|
+
wrapper.style.left = `${clampedLeft}px`;
|
|
6266
|
+
const toolbar = document.getElementById("devtools-toolbar");
|
|
6267
|
+
const toolbarRect = toolbar == null ? void 0 : toolbar.getBoundingClientRect();
|
|
6268
|
+
let bottomLimit = window.innerHeight - 16;
|
|
6269
|
+
if (toolbarRect && clampedLeft + panelWidth > toolbarRect.left) {
|
|
6270
|
+
bottomLimit = toolbarRect.top - 8;
|
|
6271
|
+
}
|
|
6272
|
+
const visibleTop = Math.max(0, clampedTop);
|
|
6273
|
+
const maxHeight = Math.max(200, bottomLimit - visibleTop);
|
|
6274
|
+
if (panel) panel.style.maxHeight = `${maxHeight}px`;
|
|
6275
|
+
};
|
|
6276
|
+
const onMouseUp = () => {
|
|
6277
|
+
if (!dragState.current) return;
|
|
6278
|
+
const finalTop = positionRef.current.top + dragOffset.current.y;
|
|
6279
|
+
const finalLeft = positionRef.current.left + dragOffset.current.x;
|
|
6280
|
+
positionRef.current = __spreadProps(__spreadValues({}, positionRef.current), { top: finalTop, left: finalLeft });
|
|
6281
|
+
dragOffset.current = { x: 0, y: 0 };
|
|
6282
|
+
hasSavedPosition.current = true;
|
|
6283
|
+
try {
|
|
6284
|
+
localStorage.setItem(PANEL_POS_KEY, JSON.stringify({ top: finalTop, left: finalLeft }));
|
|
6285
|
+
} catch (e) {
|
|
6286
|
+
}
|
|
6287
|
+
dragState.current = null;
|
|
6288
|
+
};
|
|
6289
|
+
window.addEventListener("mousemove", onMouseMove);
|
|
6290
|
+
window.addEventListener("mouseup", onMouseUp);
|
|
6291
|
+
return () => {
|
|
6292
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
6293
|
+
window.removeEventListener("mouseup", onMouseUp);
|
|
6294
|
+
};
|
|
6295
|
+
}, []);
|
|
6296
|
+
const handleHeaderMouseDown = useCallback4((e) => {
|
|
6297
|
+
if (e.button !== 0 || e.target.closest("button")) return;
|
|
6298
|
+
e.preventDefault();
|
|
6299
|
+
dragState.current = {
|
|
6300
|
+
startX: e.clientX,
|
|
6301
|
+
startY: e.clientY,
|
|
6302
|
+
startOffsetX: dragOffset.current.x,
|
|
6303
|
+
startOffsetY: dragOffset.current.y
|
|
6304
|
+
};
|
|
6305
|
+
}, []);
|
|
5859
6306
|
useEffect12(() => {
|
|
6307
|
+
dragOffset.current = { x: 0, y: 0 };
|
|
5860
6308
|
const updatePosition = (isScrollEvent = false) => {
|
|
5861
6309
|
const panel = panelRef.current;
|
|
5862
|
-
const rect = element.getBoundingClientRect();
|
|
5863
6310
|
const panelWidth = 280;
|
|
5864
|
-
const
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
left = rect.
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
6311
|
+
const gap = 8;
|
|
6312
|
+
let top;
|
|
6313
|
+
let left;
|
|
6314
|
+
if (hasSavedPosition.current) {
|
|
6315
|
+
top = positionRef.current.top;
|
|
6316
|
+
left = positionRef.current.left;
|
|
6317
|
+
} else {
|
|
6318
|
+
const rect = element.getBoundingClientRect();
|
|
6319
|
+
left = rect.right + gap;
|
|
6320
|
+
top = rect.top;
|
|
6321
|
+
if (left + panelWidth > window.innerWidth - gap) {
|
|
6322
|
+
left = rect.left - panelWidth - gap;
|
|
6323
|
+
}
|
|
6324
|
+
if (left < gap) {
|
|
6325
|
+
left = Math.max(gap, (window.innerWidth - panelWidth) / 2);
|
|
6326
|
+
}
|
|
6327
|
+
}
|
|
6328
|
+
const toolbar = document.getElementById("devtools-toolbar");
|
|
6329
|
+
const toolbarRect = toolbar == null ? void 0 : toolbar.getBoundingClientRect();
|
|
6330
|
+
let bottomLimit = window.innerHeight - 16;
|
|
6331
|
+
if (toolbarRect) {
|
|
6332
|
+
const panelRight = left + panelWidth;
|
|
6333
|
+
if (panelRight > toolbarRect.left) {
|
|
6334
|
+
bottomLimit = toolbarRect.top - gap;
|
|
6335
|
+
}
|
|
6336
|
+
}
|
|
5881
6337
|
const visibleTop = Math.max(0, top);
|
|
5882
6338
|
const maxHeight = Math.max(200, bottomLimit - visibleTop);
|
|
5883
6339
|
positionRef.current = { top, left, maxHeight };
|
|
5884
6340
|
if (isScrollEvent && panel) {
|
|
5885
6341
|
const wrapper = panel.parentElement;
|
|
5886
|
-
if (wrapper) {
|
|
5887
|
-
wrapper.style.top = `${top}px`;
|
|
5888
|
-
wrapper.style.left = `${left}px`;
|
|
6342
|
+
if (wrapper && !hasSavedPosition.current) {
|
|
6343
|
+
wrapper.style.top = `${top + dragOffset.current.y}px`;
|
|
6344
|
+
wrapper.style.left = `${left + dragOffset.current.x}px`;
|
|
5889
6345
|
}
|
|
5890
6346
|
panel.style.maxHeight = `${maxHeight}px`;
|
|
5891
6347
|
} else {
|
|
@@ -6079,9 +6535,10 @@ function StylePanel({
|
|
|
6079
6535
|
transform: "translateY(-50%)",
|
|
6080
6536
|
fontSize: 10,
|
|
6081
6537
|
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
6082
|
-
color: "#999"
|
|
6083
|
-
|
|
6084
|
-
|
|
6538
|
+
color: "#999"
|
|
6539
|
+
},
|
|
6540
|
+
preferredUnit,
|
|
6541
|
+
onUnitCycle: cycleUnit
|
|
6085
6542
|
}
|
|
6086
6543
|
) });
|
|
6087
6544
|
}
|
|
@@ -6150,7 +6607,7 @@ function StylePanel({
|
|
|
6150
6607
|
};
|
|
6151
6608
|
const modificationCount = (_a = currentModification == null ? void 0 : currentModification.changes.length) != null ? _a : 0;
|
|
6152
6609
|
const isCaptured = (_b = currentModification == null ? void 0 : currentModification.captured) != null ? _b : false;
|
|
6153
|
-
const panelStyle2 = {
|
|
6610
|
+
const panelStyle2 = __spreadProps(__spreadValues({
|
|
6154
6611
|
position: "fixed",
|
|
6155
6612
|
top: positionRef.current.top,
|
|
6156
6613
|
left: positionRef.current.left,
|
|
@@ -6158,9 +6615,8 @@ function StylePanel({
|
|
|
6158
6615
|
maxHeight: positionRef.current.maxHeight,
|
|
6159
6616
|
backgroundColor: "rgba(255, 255, 255, 0.85)",
|
|
6160
6617
|
backdropFilter: "blur(32px)",
|
|
6161
|
-
WebkitBackdropFilter: "blur(32px)"
|
|
6162
|
-
|
|
6163
|
-
borderRadius: 0,
|
|
6618
|
+
WebkitBackdropFilter: "blur(32px)"
|
|
6619
|
+
}, POPMELT_BORDER), {
|
|
6164
6620
|
zIndex: 1e4,
|
|
6165
6621
|
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
6166
6622
|
fontSize: 12,
|
|
@@ -6169,22 +6625,16 @@ function StylePanel({
|
|
|
6169
6625
|
flexDirection: "column",
|
|
6170
6626
|
opacity: visible ? 1 : 0,
|
|
6171
6627
|
transition: "opacity 150ms ease"
|
|
6172
|
-
};
|
|
6173
|
-
const cornerDotStyle = {
|
|
6174
|
-
position: "absolute",
|
|
6175
|
-
width: 2,
|
|
6176
|
-
height: 2,
|
|
6177
|
-
backgroundColor: "rgba(0, 0, 0, 0.25)",
|
|
6178
|
-
pointerEvents: "none",
|
|
6179
|
-
zIndex: 1
|
|
6180
|
-
};
|
|
6628
|
+
});
|
|
6181
6629
|
const headerStyle = {
|
|
6182
6630
|
display: "flex",
|
|
6183
6631
|
alignItems: "center",
|
|
6184
6632
|
justifyContent: "space-between",
|
|
6633
|
+
margin: "3px 3px 0",
|
|
6185
6634
|
padding: "8px 7px 8px 12px",
|
|
6186
6635
|
borderBottom: "1px solid rgba(0,0,0,0.1)",
|
|
6187
|
-
backgroundColor: "
|
|
6636
|
+
backgroundColor: "#f8fafc",
|
|
6637
|
+
cursor: dragState.current ? "grabbing" : "grab"
|
|
6188
6638
|
};
|
|
6189
6639
|
const sectionHeaderStyle = {
|
|
6190
6640
|
display: "flex",
|
|
@@ -6210,198 +6660,193 @@ function StylePanel({
|
|
|
6210
6660
|
color: "#64748b",
|
|
6211
6661
|
flexShrink: 0
|
|
6212
6662
|
};
|
|
6213
|
-
return /* @__PURE__ */
|
|
6663
|
+
return /* @__PURE__ */ jsx7("div", { "data-devtools": "panel-wrapper", style: {
|
|
6214
6664
|
position: "fixed",
|
|
6215
|
-
top: positionRef.current.top,
|
|
6216
|
-
left: positionRef.current.left,
|
|
6665
|
+
top: positionRef.current.top + dragOffset.current.y,
|
|
6666
|
+
left: positionRef.current.left + dragOffset.current.x,
|
|
6217
6667
|
zIndex: 1e4,
|
|
6218
6668
|
pointerEvents: "none"
|
|
6219
|
-
}, children: [
|
|
6220
|
-
/* @__PURE__ */ jsxs6("div", {
|
|
6221
|
-
/* @__PURE__ */ jsxs6("div", { style:
|
|
6222
|
-
/* @__PURE__ */
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6669
|
+
}, children: /* @__PURE__ */ jsxs6("div", { ref: panelRef, "data-devtools": "panel", style: __spreadProps(__spreadValues({}, panelStyle2), { position: "relative", top: 0, left: 0, zIndex: 0, pointerEvents: "auto" }), onMouseEnter: () => onHover == null ? void 0 : onHover("element"), onMouseLeave: () => onHover == null ? void 0 : onHover(null), children: [
|
|
6670
|
+
/* @__PURE__ */ jsxs6("div", { style: headerStyle, onMouseDown: handleHeaderMouseDown, children: [
|
|
6671
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", gap: 8, overflow: "hidden" }, children: [
|
|
6672
|
+
/* @__PURE__ */ jsx7("span", { style: {
|
|
6673
|
+
fontWeight: 600,
|
|
6674
|
+
fontSize: 11,
|
|
6675
|
+
overflow: "hidden",
|
|
6676
|
+
textOverflow: "ellipsis",
|
|
6677
|
+
whiteSpace: "nowrap"
|
|
6678
|
+
}, children: elementInfo.tagName }),
|
|
6679
|
+
modificationCount > 0 && /* @__PURE__ */ jsx7("span", { style: {
|
|
6680
|
+
backgroundColor: isCaptured ? "#999999" : accentColor,
|
|
6681
|
+
color: "#fff",
|
|
6682
|
+
fontSize: 9,
|
|
6683
|
+
padding: "1px 4px",
|
|
6684
|
+
borderRadius: 2
|
|
6685
|
+
}, children: modificationCount })
|
|
6686
|
+
] }),
|
|
6687
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 4 }, children: [
|
|
6688
|
+
modificationCount > 0 && /* @__PURE__ */ jsx7(
|
|
6689
|
+
"button",
|
|
6690
|
+
{
|
|
6691
|
+
type: "button",
|
|
6692
|
+
onClick: handleReset,
|
|
6693
|
+
title: "Reset all changes",
|
|
6694
|
+
style: {
|
|
6695
|
+
display: "flex",
|
|
6696
|
+
alignItems: "center",
|
|
6697
|
+
justifyContent: "center",
|
|
6698
|
+
width: 24,
|
|
6699
|
+
height: 24,
|
|
6700
|
+
border: "none",
|
|
6701
|
+
background: "none",
|
|
6702
|
+
cursor: "pointer",
|
|
6703
|
+
color: "#64748b",
|
|
6704
|
+
borderRadius: 2
|
|
6705
|
+
},
|
|
6706
|
+
children: /* @__PURE__ */ jsx7(RotateCcw, { size: 14 })
|
|
6707
|
+
}
|
|
6708
|
+
),
|
|
6709
|
+
/* @__PURE__ */ jsx7(
|
|
6710
|
+
"button",
|
|
6711
|
+
{
|
|
6712
|
+
type: "button",
|
|
6713
|
+
onClick: onClose,
|
|
6714
|
+
title: "Close",
|
|
6715
|
+
style: {
|
|
6716
|
+
display: "flex",
|
|
6717
|
+
alignItems: "center",
|
|
6718
|
+
justifyContent: "center",
|
|
6719
|
+
width: 24,
|
|
6720
|
+
height: 24,
|
|
6721
|
+
border: "none",
|
|
6722
|
+
background: "none",
|
|
6723
|
+
cursor: "pointer",
|
|
6724
|
+
color: "#64748b",
|
|
6725
|
+
borderRadius: 2
|
|
6726
|
+
},
|
|
6727
|
+
children: /* @__PURE__ */ jsx7(X, { size: 14 })
|
|
6728
|
+
}
|
|
6729
|
+
)
|
|
6730
|
+
] })
|
|
6731
|
+
] }),
|
|
6732
|
+
/* @__PURE__ */ jsxs6("div", { ref: panelContentRef, style: { flex: 1, overflowY: "auto", margin: "0 3px 3px" }, children: [
|
|
6733
|
+
/* @__PURE__ */ jsx7("div", { style: { opacity: activeColorDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: /* @__PURE__ */ jsx7(
|
|
6734
|
+
LayoutSection,
|
|
6735
|
+
{
|
|
6736
|
+
element,
|
|
6737
|
+
getValue,
|
|
6738
|
+
getOriginalValue,
|
|
6739
|
+
handleChange,
|
|
6740
|
+
isModified,
|
|
6741
|
+
onResetProperty: handleResetProperty,
|
|
6742
|
+
isCollapsed: false,
|
|
6743
|
+
onToggle: () => {
|
|
6744
|
+
},
|
|
6745
|
+
sectionHeaderStyle,
|
|
6746
|
+
activeDropdown,
|
|
6747
|
+
onDropdownChange: setActiveDropdown,
|
|
6748
|
+
panelContentRef,
|
|
6749
|
+
accentColor,
|
|
6750
|
+
onFieldHover: onHover,
|
|
6751
|
+
preferredUnit,
|
|
6752
|
+
onUnitCycle: cycleUnit
|
|
6753
|
+
}
|
|
6754
|
+
) }),
|
|
6755
|
+
/* @__PURE__ */ jsx7("div", { style: { opacity: activeDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: /* @__PURE__ */ jsx7(
|
|
6756
|
+
TypographySection,
|
|
6757
|
+
{
|
|
6758
|
+
element,
|
|
6759
|
+
getValue,
|
|
6760
|
+
handleChange,
|
|
6761
|
+
isModified,
|
|
6762
|
+
onResetProperty: handleResetProperty,
|
|
6763
|
+
isCollapsed: false,
|
|
6764
|
+
onToggle: () => {
|
|
6765
|
+
},
|
|
6766
|
+
sectionHeaderStyle,
|
|
6767
|
+
accentColor,
|
|
6768
|
+
colorVariables,
|
|
6769
|
+
activeColorDropdown,
|
|
6770
|
+
onColorDropdownChange: setActiveColorDropdown,
|
|
6771
|
+
panelContentRef,
|
|
6772
|
+
preferredUnit,
|
|
6773
|
+
onUnitCycle: cycleUnit
|
|
6774
|
+
}
|
|
6775
|
+
) }),
|
|
6776
|
+
SECTIONS.map((section, index) => {
|
|
6777
|
+
const isLast = index === SECTIONS.length - 1;
|
|
6778
|
+
const sectionHasActiveColorDropdown = activeColorDropdown && section.properties.some((p) => p.property === activeColorDropdown);
|
|
6779
|
+
const shouldFadeSection = hasActiveDropdown && !sectionHasActiveColorDropdown;
|
|
6780
|
+
return /* @__PURE__ */ jsxs6("div", { style: { borderBottom: isLast ? "none" : "1px solid rgba(0,0,0,0.08)", opacity: shouldFadeSection ? 0.3 : 1, transition: "opacity 150ms ease" }, children: [
|
|
6781
|
+
/* @__PURE__ */ jsx7("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsx7("span", { children: section.name }) }),
|
|
6782
|
+
/* @__PURE__ */ jsx7("div", { style: { padding: "4px 0" }, children: section.properties.map((prop) => {
|
|
6783
|
+
const modified = isModified(prop.property);
|
|
6784
|
+
const shouldFadeRow = sectionHasActiveColorDropdown && prop.property !== activeColorDropdown;
|
|
6785
|
+
return /* @__PURE__ */ jsxs6("div", { style: __spreadProps(__spreadValues({}, propertyRowStyle), { opacity: shouldFadeRow ? 0.3 : 1, transition: "opacity 150ms ease" }), children: [
|
|
6786
|
+
/* @__PURE__ */ jsx7(
|
|
6787
|
+
"span",
|
|
6788
|
+
{
|
|
6789
|
+
onClick: modified ? () => handleResetProperty(prop.property) : void 0,
|
|
6790
|
+
title: modified ? "Click to reset" : void 0,
|
|
6791
|
+
style: __spreadProps(__spreadValues({}, labelStyle), {
|
|
6792
|
+
color: modified ? accentColor : "#64748b",
|
|
6793
|
+
fontWeight: modified ? 600 : 400,
|
|
6794
|
+
cursor: modified ? "pointer" : "default"
|
|
6795
|
+
}),
|
|
6796
|
+
children: prop.label
|
|
6797
|
+
}
|
|
6798
|
+
),
|
|
6799
|
+
/* @__PURE__ */ jsx7("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: renderInput(prop) })
|
|
6800
|
+
] }, prop.property);
|
|
6801
|
+
}) })
|
|
6802
|
+
] }, section.name);
|
|
6803
|
+
}),
|
|
6804
|
+
/* @__PURE__ */ jsxs6("div", { style: { opacity: hasActiveDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: [
|
|
6805
|
+
/* @__PURE__ */ jsx7("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsx7("span", { children: "Raw CSS" }) }),
|
|
6806
|
+
/* @__PURE__ */ jsxs6("div", { style: { padding: "8px 12px" }, children: [
|
|
6807
|
+
/* @__PURE__ */ jsx7(
|
|
6808
|
+
"textarea",
|
|
6809
|
+
{
|
|
6810
|
+
value: rawCss,
|
|
6811
|
+
onChange: (e) => setRawCss(e.target.value),
|
|
6812
|
+
placeholder: "property: value; ...",
|
|
6813
|
+
style: {
|
|
6814
|
+
width: "100%",
|
|
6815
|
+
height: 60,
|
|
6816
|
+
padding: 8,
|
|
6817
|
+
fontSize: 11,
|
|
6818
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
6819
|
+
border: "1px solid rgba(0,0,0,0.1)",
|
|
6820
|
+
borderRadius: 2,
|
|
6821
|
+
resize: "vertical",
|
|
6822
|
+
outline: "none"
|
|
6823
|
+
}
|
|
6262
6824
|
}
|
|
6263
6825
|
),
|
|
6264
|
-
/* @__PURE__ */ jsx7(
|
|
6826
|
+
rawCss.trim() && /* @__PURE__ */ jsx7(
|
|
6265
6827
|
"button",
|
|
6266
6828
|
{
|
|
6267
6829
|
type: "button",
|
|
6268
|
-
onClick:
|
|
6269
|
-
title: "Close",
|
|
6830
|
+
onClick: handleApplyRawCss,
|
|
6270
6831
|
style: {
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
height: 24,
|
|
6832
|
+
marginTop: 4,
|
|
6833
|
+
padding: "4px 8px",
|
|
6834
|
+
width: "100%",
|
|
6835
|
+
fontSize: 11,
|
|
6276
6836
|
border: "none",
|
|
6277
|
-
|
|
6837
|
+
borderRadius: 2,
|
|
6838
|
+
backgroundColor: accentColor,
|
|
6839
|
+
color: "#fff",
|
|
6278
6840
|
cursor: "pointer",
|
|
6279
|
-
|
|
6280
|
-
borderRadius: 2
|
|
6841
|
+
opacity: rawCss.trim() ? 1 : 0.5
|
|
6281
6842
|
},
|
|
6282
|
-
children:
|
|
6843
|
+
children: "Apply"
|
|
6283
6844
|
}
|
|
6284
6845
|
)
|
|
6285
6846
|
] })
|
|
6286
|
-
] }),
|
|
6287
|
-
/* @__PURE__ */ jsxs6("div", { ref: panelContentRef, style: { flex: 1, overflowY: "auto" }, children: [
|
|
6288
|
-
/* @__PURE__ */ jsx7("div", { style: { opacity: activeColorDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: /* @__PURE__ */ jsx7(
|
|
6289
|
-
LayoutSection,
|
|
6290
|
-
{
|
|
6291
|
-
element,
|
|
6292
|
-
getValue,
|
|
6293
|
-
getOriginalValue,
|
|
6294
|
-
handleChange,
|
|
6295
|
-
isModified,
|
|
6296
|
-
onResetProperty: handleResetProperty,
|
|
6297
|
-
isCollapsed: false,
|
|
6298
|
-
onToggle: () => {
|
|
6299
|
-
},
|
|
6300
|
-
sectionHeaderStyle,
|
|
6301
|
-
activeDropdown,
|
|
6302
|
-
onDropdownChange: setActiveDropdown,
|
|
6303
|
-
panelContentRef,
|
|
6304
|
-
accentColor
|
|
6305
|
-
}
|
|
6306
|
-
) }),
|
|
6307
|
-
/* @__PURE__ */ jsx7("div", { style: { opacity: activeDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: /* @__PURE__ */ jsx7(
|
|
6308
|
-
TypographySection,
|
|
6309
|
-
{
|
|
6310
|
-
element,
|
|
6311
|
-
getValue,
|
|
6312
|
-
handleChange,
|
|
6313
|
-
isModified,
|
|
6314
|
-
onResetProperty: handleResetProperty,
|
|
6315
|
-
isCollapsed: false,
|
|
6316
|
-
onToggle: () => {
|
|
6317
|
-
},
|
|
6318
|
-
sectionHeaderStyle,
|
|
6319
|
-
accentColor,
|
|
6320
|
-
colorVariables,
|
|
6321
|
-
activeColorDropdown,
|
|
6322
|
-
onColorDropdownChange: setActiveColorDropdown,
|
|
6323
|
-
panelContentRef
|
|
6324
|
-
}
|
|
6325
|
-
) }),
|
|
6326
|
-
SECTIONS.map((section, index) => {
|
|
6327
|
-
const isLast = index === SECTIONS.length - 1;
|
|
6328
|
-
const sectionHasActiveColorDropdown = activeColorDropdown && section.properties.some((p) => p.property === activeColorDropdown);
|
|
6329
|
-
const shouldFadeSection = hasActiveDropdown && !sectionHasActiveColorDropdown;
|
|
6330
|
-
return /* @__PURE__ */ jsxs6("div", { style: { borderBottom: isLast ? "none" : "1px solid rgba(0,0,0,0.08)", opacity: shouldFadeSection ? 0.3 : 1, transition: "opacity 150ms ease" }, children: [
|
|
6331
|
-
/* @__PURE__ */ jsx7("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsx7("span", { children: section.name }) }),
|
|
6332
|
-
/* @__PURE__ */ jsx7("div", { style: { padding: "4px 0" }, children: section.properties.map((prop) => {
|
|
6333
|
-
const modified = isModified(prop.property);
|
|
6334
|
-
const shouldFadeRow = sectionHasActiveColorDropdown && prop.property !== activeColorDropdown;
|
|
6335
|
-
return /* @__PURE__ */ jsxs6("div", { style: __spreadProps(__spreadValues({}, propertyRowStyle), { opacity: shouldFadeRow ? 0.3 : 1, transition: "opacity 150ms ease" }), children: [
|
|
6336
|
-
/* @__PURE__ */ jsx7(
|
|
6337
|
-
"span",
|
|
6338
|
-
{
|
|
6339
|
-
onClick: modified ? () => handleResetProperty(prop.property) : void 0,
|
|
6340
|
-
title: modified ? "Click to reset" : void 0,
|
|
6341
|
-
style: __spreadProps(__spreadValues({}, labelStyle), {
|
|
6342
|
-
color: modified ? accentColor : "#64748b",
|
|
6343
|
-
fontWeight: modified ? 600 : 400,
|
|
6344
|
-
cursor: modified ? "pointer" : "default"
|
|
6345
|
-
}),
|
|
6346
|
-
children: prop.label
|
|
6347
|
-
}
|
|
6348
|
-
),
|
|
6349
|
-
/* @__PURE__ */ jsx7("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: renderInput(prop) })
|
|
6350
|
-
] }, prop.property);
|
|
6351
|
-
}) })
|
|
6352
|
-
] }, section.name);
|
|
6353
|
-
}),
|
|
6354
|
-
/* @__PURE__ */ jsxs6("div", { style: { opacity: hasActiveDropdown ? 0.3 : 1, transition: "opacity 150ms ease" }, children: [
|
|
6355
|
-
/* @__PURE__ */ jsx7("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsx7("span", { children: "Raw CSS" }) }),
|
|
6356
|
-
/* @__PURE__ */ jsxs6("div", { style: { padding: "8px 12px" }, children: [
|
|
6357
|
-
/* @__PURE__ */ jsx7(
|
|
6358
|
-
"textarea",
|
|
6359
|
-
{
|
|
6360
|
-
value: rawCss,
|
|
6361
|
-
onChange: (e) => setRawCss(e.target.value),
|
|
6362
|
-
placeholder: "property: value; ...",
|
|
6363
|
-
style: {
|
|
6364
|
-
width: "100%",
|
|
6365
|
-
height: 60,
|
|
6366
|
-
padding: 8,
|
|
6367
|
-
fontSize: 11,
|
|
6368
|
-
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace',
|
|
6369
|
-
border: "1px solid rgba(0,0,0,0.1)",
|
|
6370
|
-
borderRadius: 2,
|
|
6371
|
-
resize: "vertical",
|
|
6372
|
-
outline: "none"
|
|
6373
|
-
}
|
|
6374
|
-
}
|
|
6375
|
-
),
|
|
6376
|
-
rawCss.trim() && /* @__PURE__ */ jsx7(
|
|
6377
|
-
"button",
|
|
6378
|
-
{
|
|
6379
|
-
type: "button",
|
|
6380
|
-
onClick: handleApplyRawCss,
|
|
6381
|
-
style: {
|
|
6382
|
-
marginTop: 4,
|
|
6383
|
-
padding: "4px 8px",
|
|
6384
|
-
width: "100%",
|
|
6385
|
-
fontSize: 11,
|
|
6386
|
-
border: "none",
|
|
6387
|
-
borderRadius: 2,
|
|
6388
|
-
backgroundColor: accentColor,
|
|
6389
|
-
color: "#fff",
|
|
6390
|
-
cursor: "pointer",
|
|
6391
|
-
opacity: rawCss.trim() ? 1 : 0.5
|
|
6392
|
-
},
|
|
6393
|
-
children: "Apply"
|
|
6394
|
-
}
|
|
6395
|
-
)
|
|
6396
|
-
] })
|
|
6397
|
-
] })
|
|
6398
6847
|
] })
|
|
6399
|
-
] })
|
|
6400
|
-
|
|
6401
|
-
/* @__PURE__ */ jsx7("div", { style: __spreadProps(__spreadValues({}, cornerDotStyle), { top: -1, right: -1 }) }),
|
|
6402
|
-
/* @__PURE__ */ jsx7("div", { style: __spreadProps(__spreadValues({}, cornerDotStyle), { bottom: -1, left: -1 }) }),
|
|
6403
|
-
/* @__PURE__ */ jsx7("div", { style: __spreadProps(__spreadValues({}, cornerDotStyle), { bottom: -1, right: -1 }) })
|
|
6404
|
-
] });
|
|
6848
|
+
] })
|
|
6849
|
+
] }) });
|
|
6405
6850
|
}
|
|
6406
6851
|
|
|
6407
6852
|
// src/components/SwipeHints.tsx
|
|
@@ -6672,7 +7117,7 @@ function TextHandles({ element, fontSize, lineHeight, accentColor, hoveredProper
|
|
|
6672
7117
|
// src/components/AnnotationCanvas.tsx
|
|
6673
7118
|
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
6674
7119
|
var HANDLE_SIZE = 8;
|
|
6675
|
-
var
|
|
7120
|
+
var PADDING_SNAP_STEPS2 = [0, 1, 2, 4, 8, 12, 16, 20, 24, 28, 32];
|
|
6676
7121
|
var BADGE_HEIGHT = 22;
|
|
6677
7122
|
var ACTIVE_TEXT_STORAGE_KEY = "devtools-active-text";
|
|
6678
7123
|
function calculateLinkedPosition(rect, anchor, stackOffset = 0) {
|
|
@@ -6680,7 +7125,7 @@ function calculateLinkedPosition(rect, anchor, stackOffset = 0) {
|
|
|
6680
7125
|
const y = anchor === "top-left" ? rect.top + window.scrollY - BADGE_HEIGHT - stackOffset * BADGE_HEIGHT + PADDING : rect.bottom + window.scrollY + PADDING - 1 + stackOffset * BADGE_HEIGHT;
|
|
6681
7126
|
return { x, y };
|
|
6682
7127
|
}
|
|
6683
|
-
function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds, inFlightStyleSelectors, inFlightSelectorColors, onReply, onViewThread,
|
|
7128
|
+
function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds, inFlightStyleSelectors, inFlightSelectorColors, onAttachImages, onReply, onViewThread, activePlan }) {
|
|
6684
7129
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
6685
7130
|
const { canvasRef, redrawAll, resizeCanvas } = useCanvasDrawing();
|
|
6686
7131
|
const [isDrawing, setIsDrawing] = useState12(false);
|
|
@@ -6706,6 +7151,7 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
6706
7151
|
const handDragRef = useRef5({ isDragging: false, side: null, startX: 0, startY: 0, original: { top: 0, right: 0, bottom: 0, left: 0 }, element: null, elementInfo: null, selector: null, durableSelector: null });
|
|
6707
7152
|
const [handHoveredElement, setHandHoveredElement] = useState12(null);
|
|
6708
7153
|
const [handHoveredSide, setHandHoveredSide] = useState12(null);
|
|
7154
|
+
const [stylePanelHint, setStylePanelHint] = useState12(null);
|
|
6709
7155
|
const [handDragging, setHandDragging] = useState12(null);
|
|
6710
7156
|
const handCursorRef = useRef5({ x: 0, y: 0 });
|
|
6711
7157
|
const [handCursorPos, setHandCursorPos] = useState12({ x: 0, y: 0 });
|
|
@@ -7376,26 +7822,39 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
7376
7822
|
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
7377
7823
|
}, [activeText, findTextAtPoint]);
|
|
7378
7824
|
const commitActiveText = useCallback5(() => {
|
|
7825
|
+
var _a2;
|
|
7379
7826
|
if (!activeText) return;
|
|
7380
|
-
|
|
7827
|
+
const imageCount = ((_a2 = activeText.images) == null ? void 0 : _a2.length) || 0;
|
|
7828
|
+
if (activeText.text.trim() || imageCount > 0) {
|
|
7381
7829
|
if (activeText.isNew) {
|
|
7830
|
+
const annotationId = generateId();
|
|
7382
7831
|
dispatch({
|
|
7383
7832
|
type: "ADD_TEXT",
|
|
7384
|
-
payload: {
|
|
7833
|
+
payload: __spreadValues({
|
|
7385
7834
|
point: activeText.point,
|
|
7386
|
-
text: activeText.text,
|
|
7835
|
+
text: activeText.text || (imageCount > 0 ? `[${imageCount} image${imageCount > 1 ? "s" : ""}]` : ""),
|
|
7387
7836
|
fontSize: activeText.fontSize,
|
|
7837
|
+
id: annotationId,
|
|
7388
7838
|
groupId: activeText.groupId,
|
|
7389
7839
|
linkedSelector: activeText.linkedSelector,
|
|
7390
7840
|
linkedAnchor: activeText.linkedAnchor,
|
|
7391
7841
|
elements: activeText.elements
|
|
7392
|
-
}
|
|
7842
|
+
}, imageCount > 0 ? { imageCount } : {})
|
|
7393
7843
|
});
|
|
7844
|
+
if (imageCount > 0 && activeText.images && onAttachImages) {
|
|
7845
|
+
onAttachImages(annotationId, activeText.images);
|
|
7846
|
+
}
|
|
7394
7847
|
} else {
|
|
7395
7848
|
dispatch({
|
|
7396
7849
|
type: "UPDATE_TEXT",
|
|
7397
|
-
payload: {
|
|
7850
|
+
payload: __spreadValues({
|
|
7851
|
+
id: activeText.id,
|
|
7852
|
+
text: activeText.text || (imageCount > 0 ? `[${imageCount} image${imageCount > 1 ? "s" : ""}]` : "")
|
|
7853
|
+
}, imageCount > 0 ? { imageCount } : {})
|
|
7398
7854
|
});
|
|
7855
|
+
if (imageCount > 0 && activeText.images && onAttachImages) {
|
|
7856
|
+
onAttachImages(activeText.id, activeText.images);
|
|
7857
|
+
}
|
|
7399
7858
|
}
|
|
7400
7859
|
} else if (!activeText.isNew) {
|
|
7401
7860
|
dispatch({
|
|
@@ -7404,11 +7863,11 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
7404
7863
|
});
|
|
7405
7864
|
}
|
|
7406
7865
|
setActiveText(null);
|
|
7407
|
-
}, [activeText, dispatch]);
|
|
7866
|
+
}, [activeText, dispatch, onAttachImages]);
|
|
7408
7867
|
const snapPadding = useCallback5((value) => {
|
|
7409
|
-
for (let i = 0; i <
|
|
7410
|
-
const lo =
|
|
7411
|
-
const hi =
|
|
7868
|
+
for (let i = 0; i < PADDING_SNAP_STEPS2.length - 1; i++) {
|
|
7869
|
+
const lo = PADDING_SNAP_STEPS2[i];
|
|
7870
|
+
const hi = PADDING_SNAP_STEPS2[i + 1];
|
|
7412
7871
|
if (value <= (lo + hi) / 2) return lo;
|
|
7413
7872
|
if (value < hi) return hi;
|
|
7414
7873
|
}
|
|
@@ -7438,6 +7897,12 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
7438
7897
|
(e) => {
|
|
7439
7898
|
var _a2;
|
|
7440
7899
|
if (!state.isAnnotating) return;
|
|
7900
|
+
if (state.inspectedElement && state.activeTool === "hand" && !("button" in e && e.button === 2)) {
|
|
7901
|
+
e.preventDefault();
|
|
7902
|
+
e.stopPropagation();
|
|
7903
|
+
dispatch({ type: "SELECT_ELEMENT", payload: null });
|
|
7904
|
+
return;
|
|
7905
|
+
}
|
|
7441
7906
|
const point = getPoint(e);
|
|
7442
7907
|
const isShiftClick = "shiftKey" in e && e.shiftKey;
|
|
7443
7908
|
if (state.activeTool === "inspector") {
|
|
@@ -7663,7 +8128,7 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
7663
8128
|
setIsDrawing(true);
|
|
7664
8129
|
dispatch({ type: "START_PATH", payload: point });
|
|
7665
8130
|
},
|
|
7666
|
-
[state.isAnnotating, state.activeTool, state.annotations, activeText, selectedAnnotationIds, hoveredElement, handHoveredElement, handHoveredSide, radiusHoveredElement, radiusHoveredCorner, gapHoveredElement, gapHoveredAxis, gapIsAuto, textHoveredElement, textHoveredProperty, getPoint, findAnnotationAtPoint, findHandleAtPoint, dispatch, selectAnnotation, clearSelection, commitActiveText]
|
|
8131
|
+
[state.isAnnotating, state.activeTool, state.inspectedElement, state.annotations, activeText, selectedAnnotationIds, hoveredElement, handHoveredElement, handHoveredSide, radiusHoveredElement, radiusHoveredCorner, gapHoveredElement, gapHoveredAxis, gapIsAuto, textHoveredElement, textHoveredProperty, getPoint, findAnnotationAtPoint, findHandleAtPoint, dispatch, selectAnnotation, clearSelection, commitActiveText]
|
|
7667
8132
|
);
|
|
7668
8133
|
const handlePointerMove = useCallback5(
|
|
7669
8134
|
(e) => {
|
|
@@ -8268,7 +8733,8 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8268
8733
|
if (gapDragRef.current.isDragging) {
|
|
8269
8734
|
const drag = gapDragRef.current;
|
|
8270
8735
|
const el = drag.element;
|
|
8271
|
-
|
|
8736
|
+
const isRightClick = "button" in e && e.button === 2;
|
|
8737
|
+
if (!drag.hasMoved && !isRightClick && el && drag.selector && drag.elementInfo) {
|
|
8272
8738
|
if (el instanceof HTMLElement) {
|
|
8273
8739
|
el.style.removeProperty("transition");
|
|
8274
8740
|
}
|
|
@@ -8488,18 +8954,37 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8488
8954
|
commitActiveText();
|
|
8489
8955
|
}
|
|
8490
8956
|
}, [commitActiveText]);
|
|
8957
|
+
const handleTextPaste = useCallback5((e) => {
|
|
8958
|
+
if (!activeText) return;
|
|
8959
|
+
const items = e.clipboardData.items;
|
|
8960
|
+
const imageBlobs = [];
|
|
8961
|
+
for (let i = 0; i < items.length; i++) {
|
|
8962
|
+
const item = items[i];
|
|
8963
|
+
if (item.type.startsWith("image/")) {
|
|
8964
|
+
const file = item.getAsFile();
|
|
8965
|
+
if (file) imageBlobs.push(file);
|
|
8966
|
+
}
|
|
8967
|
+
}
|
|
8968
|
+
if (imageBlobs.length > 0) {
|
|
8969
|
+
e.preventDefault();
|
|
8970
|
+
setActiveText((prev) => prev ? __spreadProps(__spreadValues({}, prev), {
|
|
8971
|
+
images: [...prev.images || [], ...imageBlobs]
|
|
8972
|
+
}) : null);
|
|
8973
|
+
}
|
|
8974
|
+
}, [activeText]);
|
|
8491
8975
|
const handleContextMenu = useCallback5((e) => {
|
|
8492
|
-
if (state.activeTool !== "
|
|
8976
|
+
if (state.activeTool !== "hand" || !state.isAnnotating) return;
|
|
8493
8977
|
e.preventDefault();
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
const
|
|
8978
|
+
const target = handHoveredElement || gapHoveredElement || radiusHoveredElement || textHoveredElement;
|
|
8979
|
+
if (target && !isElementInFlight(target)) {
|
|
8980
|
+
const info = extractElementInfo(target);
|
|
8981
|
+
const selector = getUniqueSelector(target);
|
|
8497
8982
|
dispatch({
|
|
8498
8983
|
type: "SELECT_ELEMENT",
|
|
8499
|
-
payload: { el:
|
|
8984
|
+
payload: { el: target, info: __spreadProps(__spreadValues({}, info), { selector }) }
|
|
8500
8985
|
});
|
|
8501
8986
|
}
|
|
8502
|
-
}, [state.activeTool, state.isAnnotating,
|
|
8987
|
+
}, [state.activeTool, state.isAnnotating, handHoveredElement, gapHoveredElement, radiusHoveredElement, textHoveredElement, dispatch, isElementInFlight]);
|
|
8503
8988
|
useEffect15(() => {
|
|
8504
8989
|
const linkedAnnotations = state.annotations.filter((a) => a.linkedSelector);
|
|
8505
8990
|
if (linkedAnnotations.length === 0) return;
|
|
@@ -8676,10 +9161,36 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8676
9161
|
value: activeText.text,
|
|
8677
9162
|
onChange: handleTextChange,
|
|
8678
9163
|
onKeyDown: handleTextKeyDown,
|
|
9164
|
+
onPaste: handleTextPaste,
|
|
8679
9165
|
onBlur: commitActiveText,
|
|
8680
9166
|
placeholder: "Type here...",
|
|
8681
9167
|
style: textInputStyle
|
|
8682
9168
|
}
|
|
9169
|
+
),
|
|
9170
|
+
activeText.images && activeText.images.length > 0 && /* @__PURE__ */ jsxs9(
|
|
9171
|
+
"div",
|
|
9172
|
+
{
|
|
9173
|
+
"data-devtools": true,
|
|
9174
|
+
style: {
|
|
9175
|
+
position: "fixed",
|
|
9176
|
+
left: activeText.point.x - PADDING - scroll.x,
|
|
9177
|
+
top: activeText.point.y - PADDING - scroll.y - 20,
|
|
9178
|
+
zIndex: 1e4,
|
|
9179
|
+
fontSize: 11,
|
|
9180
|
+
fontFamily: "system-ui, sans-serif",
|
|
9181
|
+
color: "#fff",
|
|
9182
|
+
backgroundColor: "rgba(0,0,0,0.7)",
|
|
9183
|
+
padding: "2px 6px",
|
|
9184
|
+
borderRadius: 3,
|
|
9185
|
+
whiteSpace: "nowrap"
|
|
9186
|
+
},
|
|
9187
|
+
children: [
|
|
9188
|
+
activeText.images.length,
|
|
9189
|
+
" image",
|
|
9190
|
+
activeText.images.length > 1 ? "s" : "",
|
|
9191
|
+
" attached"
|
|
9192
|
+
]
|
|
9193
|
+
}
|
|
8683
9194
|
)
|
|
8684
9195
|
] }),
|
|
8685
9196
|
state.isAnnotating && state.activeTool !== "hand" && state.styleModifications.length > 0 && /* @__PURE__ */ jsx10(
|
|
@@ -8700,29 +9211,16 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8700
9211
|
accentColor: state.activeColor
|
|
8701
9212
|
}
|
|
8702
9213
|
),
|
|
8703
|
-
state.isAnnotating && inFlightAnnotationIds && inFlightAnnotationIds.size > 0 && /* @__PURE__ */ jsx10(
|
|
8704
|
-
ThinkingSpinners,
|
|
8705
|
-
{
|
|
8706
|
-
annotations: state.annotations,
|
|
8707
|
-
inFlightIds: inFlightAnnotationIds,
|
|
8708
|
-
scrollX: scroll.x,
|
|
8709
|
-
scrollY: scroll.y,
|
|
8710
|
-
annotationGroupMap,
|
|
8711
|
-
onViewThread,
|
|
8712
|
-
onSelectAnnotation: selectAnnotation
|
|
8713
|
-
}
|
|
8714
|
-
),
|
|
8715
9214
|
state.isAnnotating && /* @__PURE__ */ jsx10(
|
|
8716
|
-
|
|
9215
|
+
AnnotationBadges,
|
|
8717
9216
|
{
|
|
8718
9217
|
annotations: state.annotations,
|
|
8719
9218
|
supersededAnnotations,
|
|
9219
|
+
inFlightIds: inFlightAnnotationIds,
|
|
8720
9220
|
scrollX: scroll.x,
|
|
8721
9221
|
scrollY: scroll.y,
|
|
8722
9222
|
annotationGroupMap,
|
|
8723
|
-
onReply,
|
|
8724
9223
|
onViewThread,
|
|
8725
|
-
isThreadPanelOpen,
|
|
8726
9224
|
onSelectAnnotation: selectAnnotation
|
|
8727
9225
|
}
|
|
8728
9226
|
),
|
|
@@ -8811,28 +9309,28 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8811
9309
|
refreshKey: textDragging ? textDragging.fontSize + textDragging.lineHeight * 1e3 : 0
|
|
8812
9310
|
}
|
|
8813
9311
|
),
|
|
8814
|
-
state.activeTool === "inspector" && state.isAnnotating && /* @__PURE__ */
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
9312
|
+
state.activeTool === "inspector" && state.isAnnotating && /* @__PURE__ */ jsx10(Fragment6, { children: hoveredElement && !state.inspectedElement && (() => {
|
|
9313
|
+
const hasLinkedAnnotation = !!pendingLinkedText || !!(activeText == null ? void 0 : activeText.linkedSelector) || state.annotations.some((a) => {
|
|
9314
|
+
if (!a.linkedSelector) return false;
|
|
9315
|
+
try {
|
|
9316
|
+
return hoveredElement.matches(a.linkedSelector);
|
|
9317
|
+
} catch (e) {
|
|
9318
|
+
return false;
|
|
9319
|
+
}
|
|
9320
|
+
});
|
|
9321
|
+
return /* @__PURE__ */ jsx10(
|
|
9322
|
+
ElementHighlight,
|
|
9323
|
+
{
|
|
9324
|
+
element: hoveredElement,
|
|
9325
|
+
isSelected: false,
|
|
9326
|
+
elementInfo: hoveredElementInfo,
|
|
9327
|
+
color: state.activeColor,
|
|
9328
|
+
hideTooltip: hasLinkedAnnotation
|
|
9329
|
+
}
|
|
9330
|
+
);
|
|
9331
|
+
})() }),
|
|
9332
|
+
state.activeTool === "hand" && state.isAnnotating && state.inspectedElement && /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
9333
|
+
stylePanelHint && stylePanelHint !== "padding" && stylePanelHint !== "gap" && (() => {
|
|
8836
9334
|
var _a2;
|
|
8837
9335
|
const annotationGroupCount = new Set(
|
|
8838
9336
|
state.annotations.map((a) => a.groupId || a.id)
|
|
@@ -8855,7 +9353,27 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8855
9353
|
}
|
|
8856
9354
|
);
|
|
8857
9355
|
})(),
|
|
8858
|
-
|
|
9356
|
+
stylePanelHint === "padding" && /* @__PURE__ */ jsx10(
|
|
9357
|
+
PaddingHandles,
|
|
9358
|
+
{
|
|
9359
|
+
element: state.inspectedElement.el,
|
|
9360
|
+
padding: getComputedPadding(state.inspectedElement.el),
|
|
9361
|
+
accentColor: state.activeColor,
|
|
9362
|
+
hoveredSide: null,
|
|
9363
|
+
draggingSide: null
|
|
9364
|
+
}
|
|
9365
|
+
),
|
|
9366
|
+
stylePanelHint === "gap" && /* @__PURE__ */ jsx10(
|
|
9367
|
+
GapHandles,
|
|
9368
|
+
{
|
|
9369
|
+
element: state.inspectedElement.el,
|
|
9370
|
+
gap: getComputedGap(state.inspectedElement.el),
|
|
9371
|
+
accentColor: state.activeColor,
|
|
9372
|
+
hoveredAxis: null,
|
|
9373
|
+
draggingAxis: null
|
|
9374
|
+
}
|
|
9375
|
+
),
|
|
9376
|
+
/* @__PURE__ */ jsx10(
|
|
8859
9377
|
StylePanel,
|
|
8860
9378
|
{
|
|
8861
9379
|
element: state.inspectedElement.el,
|
|
@@ -8864,6 +9382,7 @@ function AnnotationCanvas({ state, dispatch, onScreenshot, inFlightAnnotationIds
|
|
|
8864
9382
|
styleModifications: state.styleModifications,
|
|
8865
9383
|
dispatch,
|
|
8866
9384
|
onClose: () => dispatch({ type: "SELECT_ELEMENT", payload: null }),
|
|
9385
|
+
onHover: setStylePanelHint,
|
|
8867
9386
|
accentColor: state.activeColor
|
|
8868
9387
|
}
|
|
8869
9388
|
)
|
|
@@ -8887,8 +9406,9 @@ var THINKING_WORDS2 = [
|
|
|
8887
9406
|
"riffing"
|
|
8888
9407
|
];
|
|
8889
9408
|
var WORD_INTERVAL2 = 3e3;
|
|
8890
|
-
function
|
|
9409
|
+
function AnnotationBadges({
|
|
8891
9410
|
annotations,
|
|
9411
|
+
supersededAnnotations,
|
|
8892
9412
|
inFlightIds,
|
|
8893
9413
|
scrollX,
|
|
8894
9414
|
scrollY,
|
|
@@ -8896,10 +9416,12 @@ function ThinkingSpinners({
|
|
|
8896
9416
|
onViewThread,
|
|
8897
9417
|
onSelectAnnotation
|
|
8898
9418
|
}) {
|
|
8899
|
-
var _a;
|
|
9419
|
+
var _a, _b;
|
|
8900
9420
|
const [charIndex, setCharIndex] = useState12(0);
|
|
8901
9421
|
const [wordIndex, setWordIndex] = useState12(() => Math.floor(Math.random() * THINKING_WORDS2.length));
|
|
9422
|
+
const hasInFlight = !!(inFlightIds && inFlightIds.size > 0);
|
|
8902
9423
|
useEffect15(() => {
|
|
9424
|
+
if (!hasInFlight) return;
|
|
8903
9425
|
const charTimer = setInterval(() => {
|
|
8904
9426
|
setCharIndex((i) => (i + 1) % SPINNER_FRAME_COUNT2);
|
|
8905
9427
|
}, SPINNER_INTERVAL2);
|
|
@@ -8910,14 +9432,25 @@ function ThinkingSpinners({
|
|
|
8910
9432
|
clearInterval(charTimer);
|
|
8911
9433
|
clearInterval(wordTimer);
|
|
8912
9434
|
};
|
|
8913
|
-
}, []);
|
|
8914
|
-
const
|
|
9435
|
+
}, [hasInFlight]);
|
|
9436
|
+
const badges = [];
|
|
8915
9437
|
for (const annotation of annotations) {
|
|
8916
9438
|
if (annotation.type !== "text" || !annotation.text || !annotation.points[0]) continue;
|
|
8917
|
-
|
|
8918
|
-
|
|
9439
|
+
if (supersededAnnotations.has(annotation)) continue;
|
|
9440
|
+
const groupAnns = annotation.groupId ? annotations.filter((a) => a.groupId === annotation.groupId) : [annotation];
|
|
9441
|
+
const isInFlight = !!(inFlightIds && (inFlightIds.has(annotation.id) || groupAnns.some((a) => inFlightIds.has(a.id))));
|
|
9442
|
+
const status = (_a = annotation.status) != null ? _a : "pending";
|
|
9443
|
+
const groupMateResolved = groupAnns.some(
|
|
9444
|
+
(a) => a.status === "resolved" || a.status === "needs_review"
|
|
8919
9445
|
);
|
|
8920
|
-
|
|
9446
|
+
const hasThread = groupAnns.some((a) => a.threadId);
|
|
9447
|
+
if (!isInFlight && status !== "resolved" && status !== "needs_review" && !groupMateResolved && !hasThread) continue;
|
|
9448
|
+
const threadId = annotation.threadId || ((_b = groupAnns.find((a) => a.threadId)) == null ? void 0 : _b.threadId);
|
|
9449
|
+
const isNeedsReview = status === "needs_review" || groupAnns.some((a) => a.status === "needs_review");
|
|
9450
|
+
const replyCount = groupAnns.reduce((n, a) => {
|
|
9451
|
+
var _a2;
|
|
9452
|
+
return n + ((_a2 = a.replyCount) != null ? _a2 : 0);
|
|
9453
|
+
}, 0) || 1;
|
|
8921
9454
|
const point = annotation.points[0];
|
|
8922
9455
|
const fontSize = annotation.fontSize || 12;
|
|
8923
9456
|
const lineHeightPx = fontSize * LINE_HEIGHT;
|
|
@@ -8930,26 +9463,24 @@ function ThinkingSpinners({
|
|
|
8930
9463
|
ctx.font = `${fontSize}px ${FONT_FAMILY}`;
|
|
8931
9464
|
const maxWidth = Math.min(MAX_DISPLAY_WIDTH, Math.max(...displayLines.map((line) => ctx.measureText(line).width)));
|
|
8932
9465
|
const totalHeight = displayLines.length * lineHeightPx;
|
|
8933
|
-
|
|
8934
|
-
const groupAnns = annotation.groupId ? annotations.filter((a) => a.groupId === annotation.groupId) : [annotation];
|
|
8935
|
-
const threadId = annotation.threadId || ((_a = groupAnns.find((a) => a.threadId)) == null ? void 0 : _a.threadId);
|
|
8936
|
-
spinnerPositions.push({
|
|
9466
|
+
badges.push({
|
|
8937
9467
|
id: annotation.id,
|
|
8938
9468
|
threadId,
|
|
8939
9469
|
x: point.x + maxWidth + PADDING,
|
|
8940
|
-
// right edge of text bg
|
|
8941
9470
|
y: point.y - PADDING,
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
9471
|
+
size: totalHeight + PADDING * 2,
|
|
9472
|
+
color: annotation.color,
|
|
9473
|
+
isInFlight,
|
|
9474
|
+
isNeedsReview,
|
|
9475
|
+
replyCount
|
|
8945
9476
|
});
|
|
8946
9477
|
}
|
|
8947
|
-
if (
|
|
9478
|
+
if (badges.length === 0) return null;
|
|
8948
9479
|
const clickable = !!onViewThread;
|
|
8949
|
-
return /* @__PURE__ */ jsx10(Fragment6, { children:
|
|
9480
|
+
return /* @__PURE__ */ jsx10(Fragment6, { children: badges.map((pos) => /* @__PURE__ */ jsx10(
|
|
8950
9481
|
"div",
|
|
8951
9482
|
{
|
|
8952
|
-
"data-devtools":
|
|
9483
|
+
"data-devtools": "annotation-badge",
|
|
8953
9484
|
onClick: clickable && pos.threadId ? () => {
|
|
8954
9485
|
onSelectAnnotation == null ? void 0 : onSelectAnnotation(pos.id);
|
|
8955
9486
|
onViewThread(pos.threadId);
|
|
@@ -8962,7 +9493,7 @@ function ThinkingSpinners({
|
|
|
8962
9493
|
display: "flex",
|
|
8963
9494
|
alignItems: "center",
|
|
8964
9495
|
pointerEvents: clickable ? "auto" : "none",
|
|
8965
|
-
cursor: clickable ? "pointer" : void 0,
|
|
9496
|
+
cursor: clickable && pos.threadId ? "pointer" : void 0,
|
|
8966
9497
|
zIndex: 9999,
|
|
8967
9498
|
backgroundColor: pos.color,
|
|
8968
9499
|
fontFamily: FONT_FAMILY,
|
|
@@ -8973,7 +9504,7 @@ function ThinkingSpinners({
|
|
|
8973
9504
|
gap: 4,
|
|
8974
9505
|
whiteSpace: "nowrap"
|
|
8975
9506
|
},
|
|
8976
|
-
children: [
|
|
9507
|
+
children: pos.isInFlight ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
8977
9508
|
/* @__PURE__ */ jsx10("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "currentColor", style: { verticalAlign: "middle" }, children: charIndex === 1 ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
8978
9509
|
/* @__PURE__ */ jsx10("circle", { cx: "7", cy: "7", r: "2" }),
|
|
8979
9510
|
/* @__PURE__ */ jsx10("circle", { cx: "17", cy: "7", r: "2" }),
|
|
@@ -8986,287 +9517,23 @@ function ThinkingSpinners({
|
|
|
8986
9517
|
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "18", r: "2" })
|
|
8987
9518
|
] }) }),
|
|
8988
9519
|
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.7 }, children: THINKING_WORDS2[wordIndex] })
|
|
8989
|
-
]
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
}
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
isThreadPanelOpen,
|
|
9003
|
-
onSelectAnnotation
|
|
9004
|
-
}) {
|
|
9005
|
-
var _a;
|
|
9006
|
-
const badgePositions = [];
|
|
9007
|
-
for (const annotation of annotations) {
|
|
9008
|
-
if (annotation.type !== "text" || !annotation.text || !annotation.points[0]) continue;
|
|
9009
|
-
if (supersededAnnotations.has(annotation)) continue;
|
|
9010
|
-
const status = (_a = annotation.status) != null ? _a : "pending";
|
|
9011
|
-
const groupAnns = annotation.groupId ? annotations.filter((a) => a.groupId === annotation.groupId) : [annotation];
|
|
9012
|
-
const groupMateResolved = groupAnns.some(
|
|
9013
|
-
(a) => a.status === "resolved" || a.status === "needs_review"
|
|
9014
|
-
);
|
|
9015
|
-
const hasThread = groupAnns.some((a) => a.threadId);
|
|
9016
|
-
if (status !== "resolved" && status !== "needs_review" && !groupMateResolved && !hasThread) continue;
|
|
9017
|
-
const isNeedsReview = status === "needs_review" || groupAnns.some((a) => a.status === "needs_review");
|
|
9018
|
-
const point = annotation.points[0];
|
|
9019
|
-
const fontSize = annotation.fontSize || 12;
|
|
9020
|
-
const lineHeightPx = fontSize * LINE_HEIGHT;
|
|
9021
|
-
const lines = annotation.text.split("\n");
|
|
9022
|
-
const groupNumber = annotationGroupMap.get(annotation.id);
|
|
9023
|
-
const displayLines = groupNumber !== void 0 ? [groupNumber + ". " + (lines[0] || ""), ...lines.slice(1)] : lines;
|
|
9024
|
-
const canvas = document.createElement("canvas");
|
|
9025
|
-
const ctx = canvas.getContext("2d");
|
|
9026
|
-
if (!ctx) continue;
|
|
9027
|
-
ctx.font = `${fontSize}px ${FONT_FAMILY}`;
|
|
9028
|
-
const maxWidth = Math.min(MAX_DISPLAY_WIDTH, Math.max(...displayLines.map((line) => ctx.measureText(line).width)));
|
|
9029
|
-
const totalHeight = displayLines.length * lineHeightPx;
|
|
9030
|
-
const annotationHeight = totalHeight + PADDING * 2;
|
|
9031
|
-
badgePositions.push({
|
|
9032
|
-
annotation,
|
|
9033
|
-
x: point.x + maxWidth + PADDING,
|
|
9034
|
-
y: point.y - PADDING,
|
|
9035
|
-
size: annotationHeight,
|
|
9036
|
-
isNeedsReview: !!isNeedsReview,
|
|
9037
|
-
groupNumber
|
|
9038
|
-
});
|
|
9039
|
-
}
|
|
9040
|
-
if (badgePositions.length === 0) return null;
|
|
9041
|
-
return /* @__PURE__ */ jsx10(Fragment6, { children: badgePositions.map(({ annotation, x, y, size, isNeedsReview, groupNumber }) => /* @__PURE__ */ jsx10(
|
|
9042
|
-
ResolutionBadge,
|
|
9043
|
-
{
|
|
9044
|
-
annotation,
|
|
9045
|
-
annotations,
|
|
9046
|
-
x: x - scrollX,
|
|
9047
|
-
y: y - scrollY,
|
|
9048
|
-
size,
|
|
9049
|
-
isNeedsReview: !!isNeedsReview,
|
|
9050
|
-
groupNumber,
|
|
9051
|
-
onReply,
|
|
9052
|
-
onViewThread,
|
|
9053
|
-
isThreadPanelOpen,
|
|
9054
|
-
onSelectAnnotation
|
|
9520
|
+
] }) : /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
9521
|
+
pos.isNeedsReview ? /* @__PURE__ */ jsx10("span", { style: { fontWeight: 700 }, children: "?" }) : /* @__PURE__ */ jsxs9("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
|
|
9522
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "3", x2: "12", y2: "9" }),
|
|
9523
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "15", x2: "12", y2: "21" }),
|
|
9524
|
+
/* @__PURE__ */ jsx10("line", { x1: "3", y1: "12", x2: "9", y2: "12" }),
|
|
9525
|
+
/* @__PURE__ */ jsx10("line", { x1: "15", y1: "12", x2: "21", y2: "12" })
|
|
9526
|
+
] }),
|
|
9527
|
+
/* @__PURE__ */ jsxs9("span", { style: { opacity: 0.7 }, children: [
|
|
9528
|
+
pos.replyCount,
|
|
9529
|
+
" ",
|
|
9530
|
+
pos.replyCount === 1 ? "reply" : "replies"
|
|
9531
|
+
] })
|
|
9532
|
+
] })
|
|
9055
9533
|
},
|
|
9056
|
-
|
|
9534
|
+
pos.id
|
|
9057
9535
|
)) });
|
|
9058
9536
|
}
|
|
9059
|
-
function ResolutionBadge({
|
|
9060
|
-
annotation,
|
|
9061
|
-
annotations,
|
|
9062
|
-
x,
|
|
9063
|
-
y,
|
|
9064
|
-
size,
|
|
9065
|
-
isNeedsReview,
|
|
9066
|
-
groupNumber,
|
|
9067
|
-
onReply,
|
|
9068
|
-
onViewThread,
|
|
9069
|
-
isThreadPanelOpen,
|
|
9070
|
-
onSelectAnnotation
|
|
9071
|
-
}) {
|
|
9072
|
-
var _a, _b;
|
|
9073
|
-
const [expanded, setExpanded] = useState12(false);
|
|
9074
|
-
const [replyText, setReplyText] = useState12("");
|
|
9075
|
-
const textareaRef = useRef5(null);
|
|
9076
|
-
const panelRef = useRef5(null);
|
|
9077
|
-
useEffect15(() => {
|
|
9078
|
-
if (expanded && textareaRef.current) {
|
|
9079
|
-
textareaRef.current.focus();
|
|
9080
|
-
}
|
|
9081
|
-
}, [expanded]);
|
|
9082
|
-
useEffect15(() => {
|
|
9083
|
-
if (!expanded) return;
|
|
9084
|
-
const handleClickOutside = (e) => {
|
|
9085
|
-
if (panelRef.current && !panelRef.current.contains(e.target)) {
|
|
9086
|
-
setExpanded(false);
|
|
9087
|
-
}
|
|
9088
|
-
};
|
|
9089
|
-
const handleEscape = (e) => {
|
|
9090
|
-
if (e.key === "Escape") setExpanded(false);
|
|
9091
|
-
};
|
|
9092
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
9093
|
-
document.addEventListener("keydown", handleEscape);
|
|
9094
|
-
return () => {
|
|
9095
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
9096
|
-
document.removeEventListener("keydown", handleEscape);
|
|
9097
|
-
};
|
|
9098
|
-
}, [expanded]);
|
|
9099
|
-
const groupAnnotations = annotation.groupId ? annotations.filter((a) => a.groupId === annotation.groupId) : [annotation];
|
|
9100
|
-
const textAnn = groupAnnotations.find((a) => a.type === "text");
|
|
9101
|
-
const userMessage = (textAnn == null ? void 0 : textAnn.text) || "(no text)";
|
|
9102
|
-
const summary = (_a = groupAnnotations.find((a) => a.resolutionSummary)) == null ? void 0 : _a.resolutionSummary;
|
|
9103
|
-
const threadId = (_b = groupAnnotations.find((a) => a.threadId)) == null ? void 0 : _b.threadId;
|
|
9104
|
-
const handleSubmit = useCallback5(() => {
|
|
9105
|
-
if (!replyText.trim() || !threadId || !onReply) return;
|
|
9106
|
-
onReply(threadId, replyText.trim());
|
|
9107
|
-
setReplyText("");
|
|
9108
|
-
setExpanded(false);
|
|
9109
|
-
}, [replyText, threadId, onReply]);
|
|
9110
|
-
const handleKeyDown = useCallback5((e) => {
|
|
9111
|
-
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
9112
|
-
e.preventDefault();
|
|
9113
|
-
handleSubmit();
|
|
9114
|
-
}
|
|
9115
|
-
}, [handleSubmit]);
|
|
9116
|
-
return /* @__PURE__ */ jsxs9(
|
|
9117
|
-
"div",
|
|
9118
|
-
{
|
|
9119
|
-
ref: panelRef,
|
|
9120
|
-
"data-devtools": "resolution-badge",
|
|
9121
|
-
style: {
|
|
9122
|
-
position: "fixed",
|
|
9123
|
-
left: x,
|
|
9124
|
-
top: y,
|
|
9125
|
-
zIndex: expanded ? 10002 : 9999,
|
|
9126
|
-
pointerEvents: "auto"
|
|
9127
|
-
},
|
|
9128
|
-
children: [
|
|
9129
|
-
!expanded && /* @__PURE__ */ jsxs9(
|
|
9130
|
-
"div",
|
|
9131
|
-
{
|
|
9132
|
-
onClick: () => {
|
|
9133
|
-
onSelectAnnotation == null ? void 0 : onSelectAnnotation(annotation.id);
|
|
9134
|
-
if (threadId && onViewThread) {
|
|
9135
|
-
onViewThread(threadId);
|
|
9136
|
-
}
|
|
9137
|
-
},
|
|
9138
|
-
style: {
|
|
9139
|
-
height: size,
|
|
9140
|
-
display: "flex",
|
|
9141
|
-
alignItems: "center",
|
|
9142
|
-
cursor: "pointer",
|
|
9143
|
-
backgroundColor: annotation.color,
|
|
9144
|
-
fontFamily: FONT_FAMILY,
|
|
9145
|
-
fontSize: 12,
|
|
9146
|
-
color: "#ffffff",
|
|
9147
|
-
userSelect: "none",
|
|
9148
|
-
padding: `0 ${PADDING}px`,
|
|
9149
|
-
gap: 4,
|
|
9150
|
-
whiteSpace: "nowrap"
|
|
9151
|
-
},
|
|
9152
|
-
children: [
|
|
9153
|
-
isNeedsReview ? /* @__PURE__ */ jsx10("span", { style: { fontWeight: 700 }, children: "?" }) : /* @__PURE__ */ jsxs9("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
|
|
9154
|
-
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "3", x2: "12", y2: "9" }),
|
|
9155
|
-
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "15", x2: "12", y2: "21" }),
|
|
9156
|
-
/* @__PURE__ */ jsx10("line", { x1: "3", y1: "12", x2: "9", y2: "12" }),
|
|
9157
|
-
/* @__PURE__ */ jsx10("line", { x1: "15", y1: "12", x2: "21", y2: "12" })
|
|
9158
|
-
] }),
|
|
9159
|
-
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.7 }, children: (() => {
|
|
9160
|
-
const groupAnns = annotation.groupId ? annotations.filter((a) => a.groupId === annotation.groupId) : [annotation];
|
|
9161
|
-
const count = groupAnns.reduce((n, a) => {
|
|
9162
|
-
var _a2;
|
|
9163
|
-
return n + ((_a2 = a.replyCount) != null ? _a2 : 0);
|
|
9164
|
-
}, 0) || 1;
|
|
9165
|
-
return `${count} ${count === 1 ? "reply" : "replies"}`;
|
|
9166
|
-
})() })
|
|
9167
|
-
]
|
|
9168
|
-
}
|
|
9169
|
-
),
|
|
9170
|
-
expanded && /* @__PURE__ */ jsxs9(
|
|
9171
|
-
"div",
|
|
9172
|
-
{
|
|
9173
|
-
style: {
|
|
9174
|
-
minWidth: 280,
|
|
9175
|
-
maxWidth: 400,
|
|
9176
|
-
backgroundColor: "#ffffff",
|
|
9177
|
-
fontFamily: FONT_FAMILY,
|
|
9178
|
-
fontSize: 12,
|
|
9179
|
-
color: "#1f2937",
|
|
9180
|
-
border: "1px solid rgba(0, 0, 0, 0.1)"
|
|
9181
|
-
},
|
|
9182
|
-
children: [
|
|
9183
|
-
/* @__PURE__ */ jsx10("div", { style: {
|
|
9184
|
-
padding: `${PADDING + 2}px ${PADDING + 4}px`,
|
|
9185
|
-
backgroundColor: annotation.color,
|
|
9186
|
-
color: "#ffffff",
|
|
9187
|
-
lineHeight: 1.4
|
|
9188
|
-
}, children: userMessage }),
|
|
9189
|
-
summary && /* @__PURE__ */ jsx10("div", { style: {
|
|
9190
|
-
padding: `${PADDING + 2}px ${PADDING + 4}px`,
|
|
9191
|
-
lineHeight: 1.4,
|
|
9192
|
-
borderBottom: "1px solid rgba(0, 0, 0, 0.06)"
|
|
9193
|
-
}, children: summary }),
|
|
9194
|
-
threadId && /* @__PURE__ */ jsxs9("div", { style: { padding: PADDING }, children: [
|
|
9195
|
-
onReply && /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
9196
|
-
/* @__PURE__ */ jsx10(
|
|
9197
|
-
"textarea",
|
|
9198
|
-
{
|
|
9199
|
-
ref: textareaRef,
|
|
9200
|
-
value: replyText,
|
|
9201
|
-
onChange: (e) => setReplyText(e.target.value),
|
|
9202
|
-
onKeyDown: handleKeyDown,
|
|
9203
|
-
placeholder: "Reply...",
|
|
9204
|
-
style: {
|
|
9205
|
-
width: "100%",
|
|
9206
|
-
minHeight: 40,
|
|
9207
|
-
padding: PADDING,
|
|
9208
|
-
fontSize: 12,
|
|
9209
|
-
fontFamily: FONT_FAMILY,
|
|
9210
|
-
backgroundColor: "rgba(0, 0, 0, 0.04)",
|
|
9211
|
-
color: "#1f2937",
|
|
9212
|
-
border: "1px solid rgba(0, 0, 0, 0.1)",
|
|
9213
|
-
borderRadius: 0,
|
|
9214
|
-
outline: "none",
|
|
9215
|
-
resize: "vertical",
|
|
9216
|
-
lineHeight: 1.4,
|
|
9217
|
-
boxSizing: "border-box"
|
|
9218
|
-
}
|
|
9219
|
-
}
|
|
9220
|
-
),
|
|
9221
|
-
/* @__PURE__ */ jsx10("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 4 }, children: /* @__PURE__ */ jsx10(
|
|
9222
|
-
"button",
|
|
9223
|
-
{
|
|
9224
|
-
onClick: handleSubmit,
|
|
9225
|
-
disabled: !replyText.trim(),
|
|
9226
|
-
style: {
|
|
9227
|
-
padding: "4px 12px",
|
|
9228
|
-
fontSize: 11,
|
|
9229
|
-
fontFamily: FONT_FAMILY,
|
|
9230
|
-
fontWeight: 600,
|
|
9231
|
-
backgroundColor: replyText.trim() ? annotation.color : "rgba(0,0,0,0.1)",
|
|
9232
|
-
color: replyText.trim() ? "#ffffff" : "rgba(0,0,0,0.3)",
|
|
9233
|
-
border: "none",
|
|
9234
|
-
cursor: replyText.trim() ? "pointer" : "default"
|
|
9235
|
-
},
|
|
9236
|
-
children: "Send \u2318\u23CE"
|
|
9237
|
-
}
|
|
9238
|
-
) })
|
|
9239
|
-
] }),
|
|
9240
|
-
onViewThread && /* @__PURE__ */ jsx10(
|
|
9241
|
-
"button",
|
|
9242
|
-
{
|
|
9243
|
-
onClick: () => {
|
|
9244
|
-
onViewThread(threadId);
|
|
9245
|
-
setExpanded(false);
|
|
9246
|
-
},
|
|
9247
|
-
style: {
|
|
9248
|
-
width: "100%",
|
|
9249
|
-
padding: "5px 0",
|
|
9250
|
-
fontSize: 11,
|
|
9251
|
-
fontFamily: FONT_FAMILY,
|
|
9252
|
-
fontWeight: 500,
|
|
9253
|
-
backgroundColor: "transparent",
|
|
9254
|
-
color: "#6b7280",
|
|
9255
|
-
border: "1px solid rgba(0, 0, 0, 0.1)",
|
|
9256
|
-
cursor: "pointer",
|
|
9257
|
-
marginTop: onReply ? 8 : 0
|
|
9258
|
-
},
|
|
9259
|
-
children: "View conversation \u2192"
|
|
9260
|
-
}
|
|
9261
|
-
)
|
|
9262
|
-
] })
|
|
9263
|
-
]
|
|
9264
|
-
}
|
|
9265
|
-
)
|
|
9266
|
-
]
|
|
9267
|
-
}
|
|
9268
|
-
);
|
|
9269
|
-
}
|
|
9270
9537
|
function PlanWaitingBadges({
|
|
9271
9538
|
annotations,
|
|
9272
9539
|
supersededAnnotations,
|
|
@@ -9792,13 +10059,6 @@ function useLocalStorageBatch(isExpanded, state, hasRestoredAnnotations, hasActi
|
|
|
9792
10059
|
]);
|
|
9793
10060
|
}
|
|
9794
10061
|
|
|
9795
|
-
// src/styles/border.ts
|
|
9796
|
-
var POPMELT_BORDER = {
|
|
9797
|
-
borderWidth: 4,
|
|
9798
|
-
borderStyle: "solid",
|
|
9799
|
-
borderImage: "repeating-linear-gradient(-45deg, rgba(0,0,0,1) 0, rgba(0,0,0,1) 1px, rgba(0,0,0,0.1) 1px, rgba(0,0,0,0.1) 4px) 4"
|
|
9800
|
-
};
|
|
9801
|
-
|
|
9802
10062
|
// src/components/ToolButton.tsx
|
|
9803
10063
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
9804
10064
|
var colors = {
|
|
@@ -9919,13 +10179,15 @@ var TOOL_GUIDANCE = {
|
|
|
9919
10179
|
"Corners \u2192 rounding",
|
|
9920
10180
|
"Right of text \u2192 font size",
|
|
9921
10181
|
"Below text \u2192 line height",
|
|
9922
|
-
"Click a spacing handle to cycle distribution"
|
|
10182
|
+
"Click a spacing handle to cycle distribution",
|
|
10183
|
+
"Right-click \u2192 inspect element styles"
|
|
9923
10184
|
],
|
|
9924
10185
|
keys: [
|
|
9925
10186
|
{ key: "H", desc: "Select tool" },
|
|
9926
10187
|
{ key: "Shift", desc: "Snap to scale" },
|
|
9927
10188
|
{ key: "\u2325 + swipe", desc: "Cycle justify / flip direction" },
|
|
9928
10189
|
{ key: "\u21E7 + swipe", desc: "Cycle align-items" },
|
|
10190
|
+
{ key: "Right-click", desc: "Inspect styles" },
|
|
9929
10191
|
{ key: "Esc", desc: "Deselect" },
|
|
9930
10192
|
{ key: "\u2318 Enter", desc: "Hand off to your AI", accent: true }
|
|
9931
10193
|
]
|
|
@@ -10582,7 +10844,9 @@ function AnnotationToolbar({
|
|
|
10582
10844
|
"div",
|
|
10583
10845
|
{
|
|
10584
10846
|
id: "devtools-toolbar",
|
|
10585
|
-
style: __spreadProps(__spreadValues({}, toolbarStyle), { overflow: "visible" }),
|
|
10847
|
+
style: __spreadProps(__spreadValues({}, toolbarStyle), { overflow: "visible", opacity: 0.5, transition: "opacity 150ms ease" }),
|
|
10848
|
+
onMouseEnter: (e) => e.currentTarget.style.opacity = "1",
|
|
10849
|
+
onMouseLeave: (e) => e.currentTarget.style.opacity = "0.5",
|
|
10586
10850
|
children: /* @__PURE__ */ jsx12(
|
|
10587
10851
|
"button",
|
|
10588
10852
|
{
|
|
@@ -10951,7 +11215,7 @@ function AnnotationToolbar({
|
|
|
10951
11215
|
}
|
|
10952
11216
|
|
|
10953
11217
|
// src/components/BridgeStatusPanel.tsx
|
|
10954
|
-
import { useEffect as useEffect18, useRef as useRef8, useState as useState14 } from "react";
|
|
11218
|
+
import { useCallback as useCallback7, useEffect as useEffect18, useRef as useRef8, useState as useState14 } from "react";
|
|
10955
11219
|
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
10956
11220
|
var stackContainerStyle = {
|
|
10957
11221
|
position: "fixed",
|
|
@@ -10960,21 +11224,22 @@ var stackContainerStyle = {
|
|
|
10960
11224
|
zIndex: 9999,
|
|
10961
11225
|
display: "flex",
|
|
10962
11226
|
flexDirection: "column",
|
|
10963
|
-
gap:
|
|
11227
|
+
gap: 10
|
|
10964
11228
|
};
|
|
10965
|
-
var rowStyle = {
|
|
11229
|
+
var rowStyle = __spreadProps(__spreadValues({
|
|
10966
11230
|
display: "flex",
|
|
10967
11231
|
alignItems: "center",
|
|
10968
11232
|
gap: 6,
|
|
10969
11233
|
padding: "4px 10px",
|
|
10970
|
-
backgroundColor: "rgba(255, 255, 255, 0.85)"
|
|
10971
|
-
|
|
11234
|
+
backgroundColor: "rgba(255, 255, 255, 0.85)"
|
|
11235
|
+
}, POPMELT_BORDER), {
|
|
10972
11236
|
backdropFilter: "blur(32px)",
|
|
10973
11237
|
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
10974
11238
|
fontSize: 11,
|
|
10975
11239
|
color: "#1f2937",
|
|
10976
|
-
whiteSpace: "nowrap"
|
|
10977
|
-
|
|
11240
|
+
whiteSpace: "nowrap",
|
|
11241
|
+
transition: "transform 200ms ease, opacity 200ms ease"
|
|
11242
|
+
});
|
|
10978
11243
|
function formatStepText(events) {
|
|
10979
11244
|
var _a;
|
|
10980
11245
|
const toolEvents = events.filter((e) => e.type === "tool_use");
|
|
@@ -11065,6 +11330,60 @@ function ErrorDot() {
|
|
|
11065
11330
|
}
|
|
11066
11331
|
);
|
|
11067
11332
|
}
|
|
11333
|
+
function SwipeDismiss({ onDismiss, children }) {
|
|
11334
|
+
const ref = useRef8(null);
|
|
11335
|
+
const drag = useRef8(null);
|
|
11336
|
+
const [offset, setOffset] = useState14(0);
|
|
11337
|
+
const [dismissed, setDismissed] = useState14(false);
|
|
11338
|
+
const THRESHOLD = 60;
|
|
11339
|
+
const onPointerDown = useCallback7((e) => {
|
|
11340
|
+
var _a;
|
|
11341
|
+
drag.current = { startX: e.clientX, startY: e.clientY, locked: false };
|
|
11342
|
+
(_a = ref.current) == null ? void 0 : _a.setPointerCapture(e.pointerId);
|
|
11343
|
+
}, []);
|
|
11344
|
+
const onPointerMove = useCallback7((e) => {
|
|
11345
|
+
const d = drag.current;
|
|
11346
|
+
if (!d) return;
|
|
11347
|
+
const dx = e.clientX - d.startX;
|
|
11348
|
+
const dy = e.clientY - d.startY;
|
|
11349
|
+
if (!d.locked) {
|
|
11350
|
+
if (Math.abs(dx) < 4 && Math.abs(dy) < 4) return;
|
|
11351
|
+
d.locked = true;
|
|
11352
|
+
if (Math.abs(dy) > Math.abs(dx)) {
|
|
11353
|
+
drag.current = null;
|
|
11354
|
+
return;
|
|
11355
|
+
}
|
|
11356
|
+
}
|
|
11357
|
+
setOffset(Math.max(0, dx));
|
|
11358
|
+
}, []);
|
|
11359
|
+
const onPointerUp = useCallback7(() => {
|
|
11360
|
+
if (!drag.current) return;
|
|
11361
|
+
drag.current = null;
|
|
11362
|
+
if (offset >= THRESHOLD) {
|
|
11363
|
+
setDismissed(true);
|
|
11364
|
+
setTimeout(onDismiss, 200);
|
|
11365
|
+
} else {
|
|
11366
|
+
setOffset(0);
|
|
11367
|
+
}
|
|
11368
|
+
}, [offset, onDismiss]);
|
|
11369
|
+
return /* @__PURE__ */ jsx13(
|
|
11370
|
+
"div",
|
|
11371
|
+
{
|
|
11372
|
+
ref,
|
|
11373
|
+
onPointerDown,
|
|
11374
|
+
onPointerMove,
|
|
11375
|
+
onPointerUp,
|
|
11376
|
+
onPointerCancel: onPointerUp,
|
|
11377
|
+
style: {
|
|
11378
|
+
transform: dismissed ? "translateX(120%)" : `translateX(${offset}px)`,
|
|
11379
|
+
opacity: dismissed ? 0 : 1 - offset / (THRESHOLD * 3),
|
|
11380
|
+
transition: drag.current ? "none" : "transform 200ms ease, opacity 200ms ease",
|
|
11381
|
+
touchAction: "pan-y"
|
|
11382
|
+
},
|
|
11383
|
+
children
|
|
11384
|
+
}
|
|
11385
|
+
);
|
|
11386
|
+
}
|
|
11068
11387
|
function BridgeEventStack({ bridge, inFlightJobs, isVisible: isVisible2, onHover, clearSignal }) {
|
|
11069
11388
|
const [entries, setEntries] = useState14([]);
|
|
11070
11389
|
useEffect18(() => {
|
|
@@ -11118,20 +11437,20 @@ function BridgeEventStack({ bridge, inFlightJobs, isVisible: isVisible2, onHover
|
|
|
11118
11437
|
onMouseLeave: () => onHover(false),
|
|
11119
11438
|
children: entries.map((entry) => {
|
|
11120
11439
|
const label = entry.status === "working" ? formatStepText(bridge.events.filter((e) => e.data.jobId === entry.jobId)) : entry.status === "queued" ? "Queued" : entry.status === "done" ? entry.doneLabel || "Done" : "Error";
|
|
11121
|
-
return /* @__PURE__ */ jsxs11("div", { style: rowStyle, children: [
|
|
11440
|
+
return /* @__PURE__ */ jsx13(SwipeDismiss, { onDismiss: () => setEntries((prev) => prev.filter((e) => e.jobId !== entry.jobId)), children: /* @__PURE__ */ jsxs11("div", { style: rowStyle, children: [
|
|
11122
11441
|
entry.status === "working" && /* @__PURE__ */ jsx13(DotSpinner, { color: entry.color }),
|
|
11123
11442
|
entry.status === "queued" && /* @__PURE__ */ jsx13(ColorSquare, { color: entry.color }),
|
|
11124
11443
|
entry.status === "done" && /* @__PURE__ */ jsx13(Checkmark, { color: entry.color }),
|
|
11125
11444
|
entry.status === "error" && /* @__PURE__ */ jsx13(ErrorDot, {}),
|
|
11126
11445
|
/* @__PURE__ */ jsx13("span", { style: { color: entry.status === "queued" ? "#9ca3af" : "#1f2937" }, children: label })
|
|
11127
|
-
] }, entry.jobId);
|
|
11446
|
+
] }) }, entry.jobId);
|
|
11128
11447
|
})
|
|
11129
11448
|
}
|
|
11130
11449
|
);
|
|
11131
11450
|
}
|
|
11132
11451
|
|
|
11133
11452
|
// src/components/ThreadPanel.tsx
|
|
11134
|
-
import { useCallback as
|
|
11453
|
+
import { useCallback as useCallback8, useEffect as useEffect19, useRef as useRef9, useState as useState15 } from "react";
|
|
11135
11454
|
|
|
11136
11455
|
// src/utils/threadMarkdown.tsx
|
|
11137
11456
|
import { Fragment as Fragment9, jsx as jsx14 } from "react/jsx-runtime";
|
|
@@ -11412,13 +11731,10 @@ function ThinkingBadge({ color }) {
|
|
|
11412
11731
|
/* @__PURE__ */ jsx15("span", { style: { fontSize: 11, color: "#9ca3af", fontStyle: "italic" }, children: THINKING_WORDS3[wordIndex] })
|
|
11413
11732
|
] });
|
|
11414
11733
|
}
|
|
11415
|
-
function
|
|
11734
|
+
function formatToolEvent(event) {
|
|
11416
11735
|
var _a;
|
|
11417
|
-
const
|
|
11418
|
-
|
|
11419
|
-
const last = toolEvents[toolEvents.length - 1];
|
|
11420
|
-
const tool = String(last.data.tool || "");
|
|
11421
|
-
const file = last.data.file ? String(last.data.file) : null;
|
|
11736
|
+
const tool = String(event.data.tool || "");
|
|
11737
|
+
const file = event.data.file ? String(event.data.file) : null;
|
|
11422
11738
|
const basename = file ? (_a = file.split("/").pop()) != null ? _a : file : null;
|
|
11423
11739
|
switch (tool) {
|
|
11424
11740
|
case "Read":
|
|
@@ -11441,6 +11757,34 @@ function formatToolStep(events) {
|
|
|
11441
11757
|
return tool ? `Using ${tool}` : null;
|
|
11442
11758
|
}
|
|
11443
11759
|
}
|
|
11760
|
+
function buildStreamSegments(events) {
|
|
11761
|
+
const segments = [];
|
|
11762
|
+
for (const e of events) {
|
|
11763
|
+
if (e.type === "tool_use") {
|
|
11764
|
+
const label = formatToolEvent(e);
|
|
11765
|
+
if (label) segments.push({ kind: "tool", label });
|
|
11766
|
+
} else if (e.type === "delta") {
|
|
11767
|
+
const text = String(e.data.text || "");
|
|
11768
|
+
if (!text) continue;
|
|
11769
|
+
const last = segments[segments.length - 1];
|
|
11770
|
+
if (last && last.kind === "text") {
|
|
11771
|
+
last.text += text;
|
|
11772
|
+
} else {
|
|
11773
|
+
segments.push({ kind: "text", text });
|
|
11774
|
+
}
|
|
11775
|
+
} else if (e.type === "thinking") {
|
|
11776
|
+
const text = String(e.data.text || "");
|
|
11777
|
+
if (!text) continue;
|
|
11778
|
+
const last = segments[segments.length - 1];
|
|
11779
|
+
if (last && last.kind === "thinking") {
|
|
11780
|
+
last.text += text;
|
|
11781
|
+
} else {
|
|
11782
|
+
segments.push({ kind: "thinking", text });
|
|
11783
|
+
}
|
|
11784
|
+
}
|
|
11785
|
+
}
|
|
11786
|
+
return segments;
|
|
11787
|
+
}
|
|
11444
11788
|
function ThreadPanel({
|
|
11445
11789
|
threadId,
|
|
11446
11790
|
bridgeUrl,
|
|
@@ -11462,10 +11806,11 @@ function ThreadPanel({
|
|
|
11462
11806
|
const [messages, setMessages] = useState15([]);
|
|
11463
11807
|
const [loading, setLoading] = useState15(true);
|
|
11464
11808
|
const [replyText, setReplyText] = useState15("");
|
|
11809
|
+
const [replyImages, setReplyImages] = useState15([]);
|
|
11465
11810
|
const scrollRef = useRef9(null);
|
|
11466
11811
|
const panelRef = useRef9(null);
|
|
11467
11812
|
const prevStreamingRef = useRef9(isStreaming);
|
|
11468
|
-
const fetchThread =
|
|
11813
|
+
const fetchThread = useCallback8(() => {
|
|
11469
11814
|
fetch(`${bridgeUrl}/thread/${threadId}`).then((r) => r.json()).then((data) => {
|
|
11470
11815
|
var _a2;
|
|
11471
11816
|
setMessages((_a2 = data.messages) != null ? _a2 : []);
|
|
@@ -11482,11 +11827,12 @@ function ThreadPanel({
|
|
|
11482
11827
|
}
|
|
11483
11828
|
prevStreamingRef.current = isStreaming;
|
|
11484
11829
|
}, [isStreaming, fetchThread]);
|
|
11830
|
+
const streamSegments = streamingEvents ? buildStreamSegments(streamingEvents) : [];
|
|
11485
11831
|
useEffect19(() => {
|
|
11486
11832
|
if (scrollRef.current) {
|
|
11487
11833
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
11488
11834
|
}
|
|
11489
|
-
}, [messages,
|
|
11835
|
+
}, [messages, streamSegments.length, isStreaming]);
|
|
11490
11836
|
useEffect19(() => {
|
|
11491
11837
|
const handleEscape = (e) => {
|
|
11492
11838
|
if (e.key === "Escape") onClose();
|
|
@@ -11494,27 +11840,41 @@ function ThreadPanel({
|
|
|
11494
11840
|
document.addEventListener("keydown", handleEscape);
|
|
11495
11841
|
return () => document.removeEventListener("keydown", handleEscape);
|
|
11496
11842
|
}, [onClose]);
|
|
11497
|
-
const handleSubmit =
|
|
11843
|
+
const handleSubmit = useCallback8(() => {
|
|
11498
11844
|
if (!replyText.trim() || !onReply) return;
|
|
11499
11845
|
const text = replyText.trim();
|
|
11846
|
+
const images = replyImages.length > 0 ? replyImages : void 0;
|
|
11500
11847
|
setMessages((prev) => [...prev, {
|
|
11501
11848
|
role: "human",
|
|
11502
11849
|
timestamp: Date.now(),
|
|
11503
11850
|
jobId: "pending",
|
|
11504
|
-
replyToQuestion: text
|
|
11851
|
+
replyToQuestion: images ? `${text} [${images.length} image${images.length > 1 ? "s" : ""}]` : text
|
|
11505
11852
|
}]);
|
|
11506
|
-
onReply(threadId, text);
|
|
11853
|
+
onReply(threadId, text, images);
|
|
11507
11854
|
setReplyText("");
|
|
11508
|
-
|
|
11509
|
-
|
|
11855
|
+
setReplyImages([]);
|
|
11856
|
+
}, [replyText, replyImages, threadId, onReply]);
|
|
11857
|
+
const handlePaste = useCallback8((e) => {
|
|
11858
|
+
const items = e.clipboardData.items;
|
|
11859
|
+
const imageBlobs = [];
|
|
11860
|
+
for (let i = 0; i < items.length; i++) {
|
|
11861
|
+
const item = items[i];
|
|
11862
|
+
if (item.type.startsWith("image/")) {
|
|
11863
|
+
const file = item.getAsFile();
|
|
11864
|
+
if (file) imageBlobs.push(file);
|
|
11865
|
+
}
|
|
11866
|
+
}
|
|
11867
|
+
if (imageBlobs.length > 0) {
|
|
11868
|
+
e.preventDefault();
|
|
11869
|
+
setReplyImages((prev) => [...prev, ...imageBlobs]);
|
|
11870
|
+
}
|
|
11871
|
+
}, []);
|
|
11872
|
+
const handleKeyDown = useCallback8((e) => {
|
|
11510
11873
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
11511
11874
|
e.preventDefault();
|
|
11512
11875
|
handleSubmit();
|
|
11513
11876
|
}
|
|
11514
11877
|
}, [handleSubmit]);
|
|
11515
|
-
const toolStep = streamingEvents ? formatToolStep(streamingEvents) : null;
|
|
11516
|
-
const thinkingText = streamingThinking || "";
|
|
11517
|
-
const responseText = streamingResponse ? stripInternalTags(streamingResponse) : "";
|
|
11518
11878
|
return /* @__PURE__ */ jsxs12(Fragment10, { children: [
|
|
11519
11879
|
/* @__PURE__ */ jsx15(
|
|
11520
11880
|
"div",
|
|
@@ -11562,7 +11922,9 @@ function ThreadPanel({
|
|
|
11562
11922
|
const isHuman = msg.role === "human";
|
|
11563
11923
|
const text = isHuman ? msg.replyToQuestion || msg.feedbackSummary || "(annotation)" : stripInternalTags(msg.responseText || "");
|
|
11564
11924
|
const questionText = !isHuman ? msg.question : void 0;
|
|
11565
|
-
|
|
11925
|
+
const hasResolutions = !isHuman && msg.resolutions && msg.resolutions.length > 0;
|
|
11926
|
+
const hasToolsUsed = !isHuman && msg.toolsUsed && msg.toolsUsed.length > 0;
|
|
11927
|
+
if (!text && !questionText && !hasResolutions) return null;
|
|
11566
11928
|
const isLatest = i === messages.length - 1;
|
|
11567
11929
|
return /* @__PURE__ */ jsxs12(
|
|
11568
11930
|
"div",
|
|
@@ -11595,7 +11957,21 @@ function ThreadPanel({
|
|
|
11595
11957
|
marginTop: text ? 4 : 0,
|
|
11596
11958
|
lineHeight: 1.5,
|
|
11597
11959
|
wordBreak: "break-word"
|
|
11598
|
-
}, children: renderMarkdown(questionText) })
|
|
11960
|
+
}, children: renderMarkdown(questionText) }),
|
|
11961
|
+
(hasToolsUsed || hasResolutions) && /* @__PURE__ */ jsxs12("div", { style: {
|
|
11962
|
+
marginTop: text || questionText ? 6 : 0,
|
|
11963
|
+
padding: "4px 8px",
|
|
11964
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)",
|
|
11965
|
+
fontSize: 11,
|
|
11966
|
+
lineHeight: 1.5,
|
|
11967
|
+
color: "#6b7280"
|
|
11968
|
+
}, children: [
|
|
11969
|
+
hasToolsUsed && /* @__PURE__ */ jsx15("div", { style: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 10 }, children: msg.toolsUsed.map((t, j) => /* @__PURE__ */ jsx15("div", { children: t }, j)) }),
|
|
11970
|
+
hasResolutions && msg.resolutions.map((r, j) => /* @__PURE__ */ jsxs12("div", { style: { marginTop: hasToolsUsed ? 4 : 0 }, children: [
|
|
11971
|
+
/* @__PURE__ */ jsx15("span", { style: { color: r.status === "resolved" ? "#10b981" : "#f59e0b" }, children: r.status === "resolved" ? "Done" : "Needs review" }),
|
|
11972
|
+
r.summary ? ` \u2014 ${r.summary}` : ""
|
|
11973
|
+
] }, j))
|
|
11974
|
+
] })
|
|
11599
11975
|
]
|
|
11600
11976
|
},
|
|
11601
11977
|
`${msg.jobId}-${i}`
|
|
@@ -11692,39 +12068,102 @@ function ThreadPanel({
|
|
|
11692
12068
|
/* @__PURE__ */ jsx15("span", { style: { fontWeight: 600, fontSize: 11, color: "#6b7280" }, children: "Claude Code" }),
|
|
11693
12069
|
/* @__PURE__ */ jsx15("span", { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx15(ThinkingBadge, { color: accentColor }) })
|
|
11694
12070
|
] }),
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
12071
|
+
streamSegments.map((seg, i) => {
|
|
12072
|
+
if (seg.kind === "tool") {
|
|
12073
|
+
return /* @__PURE__ */ jsx15(
|
|
12074
|
+
"div",
|
|
12075
|
+
{
|
|
12076
|
+
style: {
|
|
12077
|
+
paddingLeft: 12,
|
|
12078
|
+
fontSize: 11,
|
|
12079
|
+
color: "#9ca3af",
|
|
12080
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
12081
|
+
lineHeight: 1.6
|
|
12082
|
+
},
|
|
12083
|
+
children: seg.label
|
|
12084
|
+
},
|
|
12085
|
+
i
|
|
12086
|
+
);
|
|
12087
|
+
}
|
|
12088
|
+
if (seg.kind === "thinking") {
|
|
12089
|
+
return /* @__PURE__ */ jsx15(
|
|
12090
|
+
"div",
|
|
12091
|
+
{
|
|
12092
|
+
style: {
|
|
12093
|
+
paddingLeft: 12,
|
|
12094
|
+
marginTop: 2,
|
|
12095
|
+
marginBottom: 2,
|
|
12096
|
+
fontSize: 11,
|
|
12097
|
+
color: "#9ca3af",
|
|
12098
|
+
fontStyle: "italic",
|
|
12099
|
+
lineHeight: 1.4,
|
|
12100
|
+
whiteSpace: "pre-wrap",
|
|
12101
|
+
wordBreak: "break-word",
|
|
12102
|
+
maxHeight: 80,
|
|
12103
|
+
overflowY: "auto"
|
|
12104
|
+
},
|
|
12105
|
+
children: seg.text
|
|
12106
|
+
},
|
|
12107
|
+
i
|
|
12108
|
+
);
|
|
12109
|
+
}
|
|
12110
|
+
const stripped = stripInternalTags(seg.text);
|
|
12111
|
+
if (!stripped) return null;
|
|
12112
|
+
return /* @__PURE__ */ jsx15(
|
|
12113
|
+
"div",
|
|
12114
|
+
{
|
|
12115
|
+
style: {
|
|
12116
|
+
paddingLeft: 12,
|
|
12117
|
+
marginTop: 2,
|
|
12118
|
+
marginBottom: 2,
|
|
12119
|
+
lineHeight: 1.5,
|
|
12120
|
+
wordBreak: "break-word"
|
|
12121
|
+
},
|
|
12122
|
+
children: renderMarkdown(stripped)
|
|
12123
|
+
},
|
|
12124
|
+
i
|
|
12125
|
+
);
|
|
12126
|
+
})
|
|
11719
12127
|
] })
|
|
11720
12128
|
] }),
|
|
11721
12129
|
onReply && /* @__PURE__ */ jsxs12("div", { style: replyAreaStyle, children: [
|
|
12130
|
+
replyImages.length > 0 && /* @__PURE__ */ jsxs12("div", { style: {
|
|
12131
|
+
fontSize: 11,
|
|
12132
|
+
color: "#6b7280",
|
|
12133
|
+
marginBottom: 4,
|
|
12134
|
+
display: "flex",
|
|
12135
|
+
alignItems: "center",
|
|
12136
|
+
gap: 4
|
|
12137
|
+
}, children: [
|
|
12138
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
12139
|
+
replyImages.length,
|
|
12140
|
+
" image",
|
|
12141
|
+
replyImages.length > 1 ? "s" : "",
|
|
12142
|
+
" attached"
|
|
12143
|
+
] }),
|
|
12144
|
+
/* @__PURE__ */ jsx15(
|
|
12145
|
+
"button",
|
|
12146
|
+
{
|
|
12147
|
+
onClick: () => setReplyImages([]),
|
|
12148
|
+
style: {
|
|
12149
|
+
background: "none",
|
|
12150
|
+
border: "none",
|
|
12151
|
+
cursor: "pointer",
|
|
12152
|
+
fontSize: 11,
|
|
12153
|
+
color: "#9ca3af",
|
|
12154
|
+
padding: "0 2px"
|
|
12155
|
+
},
|
|
12156
|
+
children: "\xD7"
|
|
12157
|
+
}
|
|
12158
|
+
)
|
|
12159
|
+
] }),
|
|
11722
12160
|
/* @__PURE__ */ jsx15(
|
|
11723
12161
|
"textarea",
|
|
11724
12162
|
{
|
|
11725
12163
|
value: replyText,
|
|
11726
12164
|
onChange: (e) => setReplyText(e.target.value),
|
|
11727
12165
|
onKeyDown: handleKeyDown,
|
|
12166
|
+
onPaste: handlePaste,
|
|
11728
12167
|
placeholder: "Reply... (Cmd+Enter to send)",
|
|
11729
12168
|
style: {
|
|
11730
12169
|
width: "100%",
|
|
@@ -11782,6 +12221,7 @@ var CLAUDE_MODELS = [
|
|
|
11782
12221
|
];
|
|
11783
12222
|
var CODEX_MODELS = [
|
|
11784
12223
|
{ id: "gpt-5.3-codex", label: "Codex 5.3" },
|
|
12224
|
+
{ id: "gpt-5.3-codex-spark", label: "Spark 5.3" },
|
|
11785
12225
|
{ id: "gpt-5.1-codex-mini", label: "Mini 5.1" }
|
|
11786
12226
|
];
|
|
11787
12227
|
function equivalentModelIndex(fromProvider, toProvider, currentIndex) {
|
|
@@ -11797,6 +12237,7 @@ function PopmeltProvider({
|
|
|
11797
12237
|
var _a, _b, _c, _d, _e;
|
|
11798
12238
|
const [state, dispatch] = useAnnotationState();
|
|
11799
12239
|
const bridge = useBridgeConnection(bridgeUrl);
|
|
12240
|
+
const annotationImagesRef = useRef10(/* @__PURE__ */ new Map());
|
|
11800
12241
|
const [provider, setProvider] = useState16(() => {
|
|
11801
12242
|
if (typeof window === "undefined") return "claude";
|
|
11802
12243
|
return localStorage.getItem(PROVIDER_STORAGE_KEY) || "claude";
|
|
@@ -11826,7 +12267,7 @@ function PopmeltProvider({
|
|
|
11826
12267
|
}, [availableProviders, provider]);
|
|
11827
12268
|
const models = provider === "codex" ? CODEX_MODELS : CLAUDE_MODELS;
|
|
11828
12269
|
const currentModel = (_a = models[modelIndex]) != null ? _a : models[0];
|
|
11829
|
-
const handleProviderChange =
|
|
12270
|
+
const handleProviderChange = useCallback9((newProvider) => {
|
|
11830
12271
|
const oldProvider = provider;
|
|
11831
12272
|
setProvider(newProvider);
|
|
11832
12273
|
localStorage.setItem(PROVIDER_STORAGE_KEY, newProvider);
|
|
@@ -11834,7 +12275,7 @@ function PopmeltProvider({
|
|
|
11834
12275
|
setModelIndex(newIndex);
|
|
11835
12276
|
localStorage.setItem(MODEL_STORAGE_KEY, String(newIndex));
|
|
11836
12277
|
}, [provider, modelIndex]);
|
|
11837
|
-
const handleModelChange =
|
|
12278
|
+
const handleModelChange = useCallback9((newIndex) => {
|
|
11838
12279
|
setModelIndex(newIndex);
|
|
11839
12280
|
localStorage.setItem(MODEL_STORAGE_KEY, String(newIndex));
|
|
11840
12281
|
}, []);
|
|
@@ -12026,7 +12467,7 @@ function PopmeltProvider({
|
|
|
12026
12467
|
setInFlightJobs({});
|
|
12027
12468
|
}
|
|
12028
12469
|
}, [bridge.status]);
|
|
12029
|
-
const handleScreenshot =
|
|
12470
|
+
const handleScreenshot = useCallback9(async () => {
|
|
12030
12471
|
const canvas = document.getElementById("devtools-canvas");
|
|
12031
12472
|
if (!canvas) return false;
|
|
12032
12473
|
const blobs = await captureScreenshot(document.body, canvas, state.annotations);
|
|
@@ -12037,7 +12478,7 @@ function PopmeltProvider({
|
|
|
12037
12478
|
}
|
|
12038
12479
|
return success;
|
|
12039
12480
|
}, [state.annotations, state.styleModifications, dispatch]);
|
|
12040
|
-
const handlePlanGoal =
|
|
12481
|
+
const handlePlanGoal = useCallback9(async (goal) => {
|
|
12041
12482
|
var _a2;
|
|
12042
12483
|
try {
|
|
12043
12484
|
const activeAnnotations = state.annotations.filter((a) => {
|
|
@@ -12085,7 +12526,7 @@ function PopmeltProvider({
|
|
|
12085
12526
|
return false;
|
|
12086
12527
|
}
|
|
12087
12528
|
}, [bridgeUrl, provider, currentModel.id, state.annotations, state.styleModifications, state.inspectedElement, dispatch]);
|
|
12088
|
-
const materializePlan =
|
|
12529
|
+
const materializePlan = useCallback9(async (tasks) => {
|
|
12089
12530
|
const planId = activePlan == null ? void 0 : activePlan.planId;
|
|
12090
12531
|
if (!planId) return;
|
|
12091
12532
|
const baseHueMatch = state.activeColor.match(/oklch\([^)]*\s+([\d.]+)\s*\)/);
|
|
@@ -12130,7 +12571,11 @@ function PopmeltProvider({
|
|
|
12130
12571
|
}
|
|
12131
12572
|
}
|
|
12132
12573
|
}, [activePlan == null ? void 0 : activePlan.planId, state.activeColor, dispatch]);
|
|
12133
|
-
const
|
|
12574
|
+
const handleAttachImages = useCallback9((annotationId, images) => {
|
|
12575
|
+
const existing = annotationImagesRef.current.get(annotationId) || [];
|
|
12576
|
+
annotationImagesRef.current.set(annotationId, [...existing, ...images]);
|
|
12577
|
+
}, []);
|
|
12578
|
+
const handleSendToClaude = useCallback9(async () => {
|
|
12134
12579
|
const canvas = document.getElementById("devtools-canvas");
|
|
12135
12580
|
if (!canvas) return false;
|
|
12136
12581
|
const activeAnnotations = state.annotations.filter((a) => {
|
|
@@ -12146,9 +12591,37 @@ function PopmeltProvider({
|
|
|
12146
12591
|
if (!stitchedBlob) return false;
|
|
12147
12592
|
const feedbackData = buildFeedbackData(activeAnnotations, state.styleModifications);
|
|
12148
12593
|
const feedbackJson = JSON.stringify(feedbackData);
|
|
12594
|
+
const pastedImages = /* @__PURE__ */ new Map();
|
|
12595
|
+
for (const ann of activeAnnotations) {
|
|
12596
|
+
const blobs2 = annotationImagesRef.current.get(ann.id);
|
|
12597
|
+
if (blobs2 && blobs2.length > 0) {
|
|
12598
|
+
pastedImages.set(ann.id, blobs2);
|
|
12599
|
+
}
|
|
12600
|
+
if (ann.groupId) {
|
|
12601
|
+
for (const mate of activeAnnotations) {
|
|
12602
|
+
if (mate.groupId === ann.groupId && mate.id !== ann.id) {
|
|
12603
|
+
const mateBlobs = annotationImagesRef.current.get(mate.id);
|
|
12604
|
+
if (mateBlobs && mateBlobs.length > 0) {
|
|
12605
|
+
pastedImages.set(mate.id, mateBlobs);
|
|
12606
|
+
}
|
|
12607
|
+
}
|
|
12608
|
+
}
|
|
12609
|
+
}
|
|
12610
|
+
}
|
|
12149
12611
|
try {
|
|
12150
12612
|
const hexColor = cssColorToHex(state.activeColor);
|
|
12151
|
-
const { jobId, threadId: assignedThreadId } = await sendToBridge(
|
|
12613
|
+
const { jobId, threadId: assignedThreadId } = await sendToBridge(
|
|
12614
|
+
stitchedBlob,
|
|
12615
|
+
feedbackJson,
|
|
12616
|
+
bridgeUrl,
|
|
12617
|
+
hexColor,
|
|
12618
|
+
provider,
|
|
12619
|
+
currentModel.id,
|
|
12620
|
+
pastedImages.size > 0 ? pastedImages : void 0
|
|
12621
|
+
);
|
|
12622
|
+
for (const annId of pastedImages.keys()) {
|
|
12623
|
+
annotationImagesRef.current.delete(annId);
|
|
12624
|
+
}
|
|
12152
12625
|
const sentAnnotationIds = activeAnnotations.map((a) => a.id);
|
|
12153
12626
|
const sentStyleSelectors = state.styleModifications.filter((m) => !m.captured).map((m) => m.selector);
|
|
12154
12627
|
setInFlightJobs((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
@@ -12160,6 +12633,9 @@ function PopmeltProvider({
|
|
|
12160
12633
|
}
|
|
12161
12634
|
}));
|
|
12162
12635
|
dispatch({ type: "MARK_CAPTURED" });
|
|
12636
|
+
if (assignedThreadId && sentAnnotationIds.length > 0) {
|
|
12637
|
+
dispatch({ type: "SET_ANNOTATION_THREAD", payload: { ids: sentAnnotationIds, threadId: assignedThreadId } });
|
|
12638
|
+
}
|
|
12163
12639
|
const hueMatch = state.activeColor.match(/oklch\([^)]*\s+([\d.]+)\s*\)/);
|
|
12164
12640
|
const currentHue = (hueMatch == null ? void 0 : hueMatch[1]) ? parseFloat(hueMatch[1]) : 29;
|
|
12165
12641
|
const nextHue = (currentHue + 60) % 360;
|
|
@@ -12170,10 +12646,10 @@ function PopmeltProvider({
|
|
|
12170
12646
|
return false;
|
|
12171
12647
|
}
|
|
12172
12648
|
}, [state.annotations, state.styleModifications, state.activeColor, dispatch, bridgeUrl, provider, currentModel.id]);
|
|
12173
|
-
const handleReply =
|
|
12649
|
+
const handleReply = useCallback9(async (threadId, reply, images) => {
|
|
12174
12650
|
try {
|
|
12175
12651
|
const hexColor = cssColorToHex(state.activeColor);
|
|
12176
|
-
const { jobId } = await sendReplyToBridge(threadId, reply, bridgeUrl, hexColor, provider, currentModel.id);
|
|
12652
|
+
const { jobId } = await sendReplyToBridge(threadId, reply, bridgeUrl, hexColor, provider, currentModel.id, images);
|
|
12177
12653
|
setInFlightJobs((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
12178
12654
|
[jobId]: {
|
|
12179
12655
|
annotationIds: [],
|
|
@@ -12205,7 +12681,7 @@ function PopmeltProvider({
|
|
|
12205
12681
|
console.error("[Pare] Failed to send reply:", err);
|
|
12206
12682
|
}
|
|
12207
12683
|
}, [state.activeColor, state.annotations, bridgeUrl, bridge.dismissQuestion, dispatch, provider, currentModel.id]);
|
|
12208
|
-
const handleApprovePlan =
|
|
12684
|
+
const handleApprovePlan = useCallback9(async () => {
|
|
12209
12685
|
if (!activePlan || !activePlan.planId) return;
|
|
12210
12686
|
try {
|
|
12211
12687
|
await approvePlan(activePlan.planId, bridgeUrl);
|
|
@@ -12278,7 +12754,7 @@ function PopmeltProvider({
|
|
|
12278
12754
|
console.error("[Pare] Failed to approve plan:", err);
|
|
12279
12755
|
}
|
|
12280
12756
|
}, [activePlan, state.annotations, state.activeColor, bridgeUrl, provider, currentModel.id, dispatch]);
|
|
12281
|
-
const handleDismissPlan =
|
|
12757
|
+
const handleDismissPlan = useCallback9(() => {
|
|
12282
12758
|
setActivePlan(null);
|
|
12283
12759
|
if (activePlan == null ? void 0 : activePlan.planId) {
|
|
12284
12760
|
const planAnnotations = state.annotations.filter((a) => a.planId === activePlan.planId);
|
|
@@ -12376,7 +12852,7 @@ function PopmeltProvider({
|
|
|
12376
12852
|
const values = Object.values(inFlightJobs);
|
|
12377
12853
|
return values.length > 0 ? values[values.length - 1].color : void 0;
|
|
12378
12854
|
}, [bridge.activeJobId, inFlightJobs]);
|
|
12379
|
-
const handleViewThread =
|
|
12855
|
+
const handleViewThread = useCallback9((threadId) => {
|
|
12380
12856
|
setOpenThreadId(threadId);
|
|
12381
12857
|
}, []);
|
|
12382
12858
|
const threadActiveJobId = useMemo4(() => {
|
|
@@ -12389,7 +12865,7 @@ function PopmeltProvider({
|
|
|
12389
12865
|
const [eventStreamVisible, setEventStreamVisible] = useState16(false);
|
|
12390
12866
|
const [clearSignal, setClearSignal] = useState16(0);
|
|
12391
12867
|
const hideTimeoutRef = useRef10(null);
|
|
12392
|
-
const handleEventStreamHover =
|
|
12868
|
+
const handleEventStreamHover = useCallback9((hovering) => {
|
|
12393
12869
|
if (hovering) {
|
|
12394
12870
|
if (hideTimeoutRef.current) {
|
|
12395
12871
|
clearTimeout(hideTimeoutRef.current);
|
|
@@ -12403,7 +12879,7 @@ function PopmeltProvider({
|
|
|
12403
12879
|
}, 150);
|
|
12404
12880
|
}
|
|
12405
12881
|
}, []);
|
|
12406
|
-
const handleClearEventStream =
|
|
12882
|
+
const handleClearEventStream = useCallback9(() => {
|
|
12407
12883
|
setClearSignal((s) => s + 1);
|
|
12408
12884
|
bridge.clearEvents();
|
|
12409
12885
|
}, [bridge.clearEvents]);
|
|
@@ -12430,9 +12906,9 @@ function PopmeltProvider({
|
|
|
12430
12906
|
inFlightAnnotationIds,
|
|
12431
12907
|
inFlightStyleSelectors,
|
|
12432
12908
|
inFlightSelectorColors,
|
|
12909
|
+
onAttachImages: handleAttachImages,
|
|
12433
12910
|
onReply: bridge.isConnected ? handleReply : void 0,
|
|
12434
12911
|
onViewThread: bridge.isConnected ? handleViewThread : void 0,
|
|
12435
|
-
isThreadPanelOpen: openThreadId !== null,
|
|
12436
12912
|
activePlan
|
|
12437
12913
|
}
|
|
12438
12914
|
),
|