browsertrack 0.1.0 → 0.1.1
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/.github/workflows/docs.yml +54 -0
- package/AGENTS.md +133 -0
- package/README.md +1 -1
- package/dist/{chunk-6A7FFDIB.js → chunk-6VA7GBAO.js} +29 -4
- package/dist/chunk-6VA7GBAO.js.map +1 -0
- package/dist/{chunk-ANMR5WBH.js → chunk-G2Y3CXCY.js} +2 -2
- package/dist/{chunk-BSKNG4V7.js → chunk-ILRYKMME.js} +30 -1
- package/dist/chunk-ILRYKMME.js.map +1 -0
- package/dist/{chunk-X7C5CHBO.js → chunk-SKCMT2DE.js} +637 -76
- package/dist/chunk-SKCMT2DE.js.map +1 -0
- package/dist/{chunk-ZLNGOOH2.js → chunk-SPCIROIU.js} +65 -3
- package/dist/chunk-SPCIROIU.js.map +1 -0
- package/dist/cli/index.js +115 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.cjs +637 -75
- package/dist/client/index.d.ts +16 -2
- package/dist/client/index.js +2 -2
- package/dist/client.iife.js +393 -72
- package/dist/core/index.d.ts +12 -4
- package/dist/core/index.js +9 -3
- package/dist/daemon/index.d.ts +1 -1
- package/dist/daemon/index.js +3 -3
- package/dist/{engine-DKloFjvs.d.ts → engine-CeT9URuN.d.ts} +4 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +13 -7
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +2 -2
- package/dist/{server-CN-se8td.d.ts → server-Dd8NX2Mk.d.ts} +1 -1
- package/docboot.config.js +16 -0
- package/docs/cli.md +51 -0
- package/docs/closed-loop-verification.md +57 -0
- package/docs/getting-started.md +122 -0
- package/docs/incidents-diagnostics.md +61 -0
- package/docs/index.md +46 -0
- package/docs/mcp-reference.md +128 -0
- package/docs/security-privacy.md +32 -0
- package/docs/visual-notes.md +67 -0
- package/package.json +6 -2
- package/packages/client/package.json +2 -2
- package/packages/client/src/notes/inspector.ts +689 -79
- package/packages/client/src/transport/websocket.ts +15 -0
- package/packages/core/package.json +3 -0
- package/packages/core/src/redaction.ts +40 -5
- package/packages/daemon/src/server/ws.ts +72 -1
- package/packages/daemon/src/session/manager.ts +21 -0
- package/packages/daemon/src/storage/db.ts +10 -1
- package/test/client/interceptors.test.ts +61 -0
- package/test/core/redaction.test.ts +12 -0
- package/dist/chunk-6A7FFDIB.js.map +0 -1
- package/dist/chunk-BSKNG4V7.js.map +0 -1
- package/dist/chunk-X7C5CHBO.js.map +0 -1
- package/dist/chunk-ZLNGOOH2.js.map +0 -1
- package/packages/core/dist/index.d.ts +0 -317
- package/packages/core/dist/index.js +0 -221
- /package/dist/{chunk-ANMR5WBH.js.map → chunk-G2Y3CXCY.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getSemanticSelector,
|
|
3
3
|
redactUrl,
|
|
4
4
|
truncate
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6VA7GBAO.js";
|
|
6
6
|
|
|
7
7
|
// packages/client/src/breadcrumbs.ts
|
|
8
8
|
var BreadcrumbBuffer = class {
|
|
@@ -880,6 +880,7 @@ var WebSocketTransport = class {
|
|
|
880
880
|
maxReconnectDelay = 1e4;
|
|
881
881
|
reconnectTimer = null;
|
|
882
882
|
commandHandler;
|
|
883
|
+
messageListeners = [];
|
|
883
884
|
isDestroyed = false;
|
|
884
885
|
constructor(options) {
|
|
885
886
|
this.wsUrl = options.url || "ws://127.0.0.1:7331";
|
|
@@ -889,6 +890,12 @@ var WebSocketTransport = class {
|
|
|
889
890
|
setCommandHandler(handler) {
|
|
890
891
|
this.commandHandler = handler;
|
|
891
892
|
}
|
|
893
|
+
onMessage(listener) {
|
|
894
|
+
this.messageListeners.push(listener);
|
|
895
|
+
return () => {
|
|
896
|
+
this.messageListeners = this.messageListeners.filter((l) => l !== listener);
|
|
897
|
+
};
|
|
898
|
+
}
|
|
892
899
|
getSessionId() {
|
|
893
900
|
return this.sessionId;
|
|
894
901
|
}
|
|
@@ -912,6 +919,12 @@ var WebSocketTransport = class {
|
|
|
912
919
|
const raw = typeof event.data === "string" ? event.data : "";
|
|
913
920
|
if (!raw) return;
|
|
914
921
|
const msg = JSON.parse(raw);
|
|
922
|
+
for (const listener of this.messageListeners) {
|
|
923
|
+
try {
|
|
924
|
+
listener(msg);
|
|
925
|
+
} catch {
|
|
926
|
+
}
|
|
927
|
+
}
|
|
915
928
|
if (msg.type === "hello_ack") {
|
|
916
929
|
this.sessionId = msg.sessionId;
|
|
917
930
|
if (this.debug) {
|
|
@@ -1025,8 +1038,11 @@ var NoteInspector = class {
|
|
|
1025
1038
|
highlightOverlay = null;
|
|
1026
1039
|
regionOverlay = null;
|
|
1027
1040
|
regionBox = null;
|
|
1041
|
+
regionBanner = null;
|
|
1042
|
+
markersContainer = null;
|
|
1028
1043
|
toolbarElement = null;
|
|
1029
1044
|
modalOverlay = null;
|
|
1045
|
+
cardOverlay = null;
|
|
1030
1046
|
activeMode = "idle";
|
|
1031
1047
|
hoveredElement = null;
|
|
1032
1048
|
selectedElement = null;
|
|
@@ -1034,6 +1050,8 @@ var NoteInspector = class {
|
|
|
1034
1050
|
isDraggingRegion = false;
|
|
1035
1051
|
dragStartX = 0;
|
|
1036
1052
|
dragStartY = 0;
|
|
1053
|
+
savedNotes = [];
|
|
1054
|
+
showMarkers = true;
|
|
1037
1055
|
cleanups = [];
|
|
1038
1056
|
constructor(transport, screenshotDriver, options = {}) {
|
|
1039
1057
|
this.transport = transport;
|
|
@@ -1054,8 +1072,19 @@ var NoteInspector = class {
|
|
|
1054
1072
|
} else {
|
|
1055
1073
|
this.ensureContainer();
|
|
1056
1074
|
}
|
|
1075
|
+
const unsubscribe = this.transport.onMessage((msg) => {
|
|
1076
|
+
if (msg && msg.type === "notes_sync" && Array.isArray(msg.notes)) {
|
|
1077
|
+
this.syncNotes(msg.notes);
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
this.cleanups.push(unsubscribe);
|
|
1057
1081
|
this.setupListeners();
|
|
1058
1082
|
}
|
|
1083
|
+
syncNotes(notes) {
|
|
1084
|
+
this.savedNotes = notes;
|
|
1085
|
+
this.updateToolbarCount();
|
|
1086
|
+
this.renderMarkers();
|
|
1087
|
+
}
|
|
1059
1088
|
setMode(mode) {
|
|
1060
1089
|
this.activeMode = mode;
|
|
1061
1090
|
this.updateToolbarState();
|
|
@@ -1083,16 +1112,17 @@ var NoteInspector = class {
|
|
|
1083
1112
|
const style = document.createElement("style");
|
|
1084
1113
|
style.textContent = `
|
|
1085
1114
|
:host {
|
|
1086
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
1115
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
1087
1116
|
color-scheme: dark;
|
|
1088
1117
|
-webkit-font-smoothing: antialiased;
|
|
1118
|
+
-moz-osx-font-smoothing: grayscale;
|
|
1089
1119
|
}
|
|
1090
1120
|
|
|
1091
1121
|
/* 1. Element Highlight Overlay */
|
|
1092
1122
|
.bt-highlight {
|
|
1093
1123
|
position: fixed;
|
|
1094
1124
|
border: 2px solid #3b82f6;
|
|
1095
|
-
background: rgba(59, 130, 246, 0.
|
|
1125
|
+
background: rgba(59, 130, 246, 0.16);
|
|
1096
1126
|
border-radius: 4px;
|
|
1097
1127
|
pointer-events: none;
|
|
1098
1128
|
transition: all 0.05s ease-out;
|
|
@@ -1102,18 +1132,19 @@ var NoteInspector = class {
|
|
|
1102
1132
|
|
|
1103
1133
|
.bt-badge {
|
|
1104
1134
|
position: absolute;
|
|
1105
|
-
top: -
|
|
1135
|
+
top: -26px;
|
|
1106
1136
|
left: 0;
|
|
1107
|
-
background: #
|
|
1137
|
+
background: #0f172a;
|
|
1108
1138
|
color: #38bdf8;
|
|
1109
1139
|
border: 1px solid #3b82f6;
|
|
1110
1140
|
font-size: 11px;
|
|
1111
1141
|
font-weight: 600;
|
|
1112
|
-
|
|
1113
|
-
|
|
1142
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1143
|
+
padding: 2px 7px;
|
|
1144
|
+
border-radius: 4px;
|
|
1114
1145
|
white-space: nowrap;
|
|
1115
1146
|
pointer-events: none;
|
|
1116
|
-
box-shadow: 0
|
|
1147
|
+
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.5);
|
|
1117
1148
|
}
|
|
1118
1149
|
|
|
1119
1150
|
/* 2. Region Selection Overlay */
|
|
@@ -1125,7 +1156,8 @@ var NoteInspector = class {
|
|
|
1125
1156
|
cursor: crosshair;
|
|
1126
1157
|
z-index: 2147483642;
|
|
1127
1158
|
pointer-events: auto;
|
|
1128
|
-
background: rgba(15, 23, 42, 0.
|
|
1159
|
+
background: rgba(15, 23, 42, 0.25);
|
|
1160
|
+
user-select: none;
|
|
1129
1161
|
}
|
|
1130
1162
|
|
|
1131
1163
|
.bt-region-box {
|
|
@@ -1139,32 +1171,171 @@ var NoteInspector = class {
|
|
|
1139
1171
|
|
|
1140
1172
|
.bt-region-badge {
|
|
1141
1173
|
position: absolute;
|
|
1142
|
-
top: -
|
|
1174
|
+
top: -26px;
|
|
1143
1175
|
left: 0;
|
|
1144
1176
|
background: #0f172a;
|
|
1145
1177
|
color: #38bdf8;
|
|
1146
1178
|
border: 1px solid #0284c7;
|
|
1147
1179
|
font-size: 11px;
|
|
1148
1180
|
font-weight: 600;
|
|
1149
|
-
|
|
1150
|
-
|
|
1181
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1182
|
+
padding: 2px 7px;
|
|
1183
|
+
border-radius: 4px;
|
|
1151
1184
|
white-space: nowrap;
|
|
1152
1185
|
pointer-events: none;
|
|
1186
|
+
box-shadow: 0 4px 6px -1px rgba(0,0,0,0.5);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
.bt-region-banner {
|
|
1190
|
+
position: fixed;
|
|
1191
|
+
top: 20px;
|
|
1192
|
+
left: 50%;
|
|
1193
|
+
transform: translateX(-50%);
|
|
1194
|
+
background: #0f172a;
|
|
1195
|
+
color: #f8fafc;
|
|
1196
|
+
border: 1px solid #0284c7;
|
|
1197
|
+
border-radius: 30px;
|
|
1198
|
+
padding: 8px 16px;
|
|
1199
|
+
display: flex;
|
|
1200
|
+
align-items: center;
|
|
1201
|
+
gap: 12px;
|
|
1202
|
+
box-shadow: 0 10px 25px -5px rgba(0,0,0,0.6);
|
|
1203
|
+
font-size: 12.5px;
|
|
1204
|
+
font-weight: 500;
|
|
1205
|
+
pointer-events: auto;
|
|
1206
|
+
z-index: 2147483645;
|
|
1207
|
+
user-select: none;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.bt-region-cancel-btn {
|
|
1211
|
+
background: rgba(239, 68, 68, 0.15);
|
|
1212
|
+
color: #fca5a5;
|
|
1213
|
+
border: 1px solid rgba(239, 68, 68, 0.4);
|
|
1214
|
+
padding: 3px 10px;
|
|
1215
|
+
border-radius: 20px;
|
|
1216
|
+
font-size: 11px;
|
|
1217
|
+
font-weight: 600;
|
|
1218
|
+
cursor: pointer;
|
|
1219
|
+
transition: all 0.15s ease;
|
|
1220
|
+
display: inline-flex;
|
|
1221
|
+
align-items: center;
|
|
1222
|
+
gap: 4px;
|
|
1223
|
+
font-family: inherit;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
.bt-region-cancel-btn:hover {
|
|
1227
|
+
background: rgba(239, 68, 68, 0.3);
|
|
1228
|
+
color: #ffffff;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/* 3. Note Markers on Page */
|
|
1232
|
+
.bt-markers-layer {
|
|
1233
|
+
position: fixed;
|
|
1234
|
+
top: 0;
|
|
1235
|
+
left: 0;
|
|
1236
|
+
width: 0;
|
|
1237
|
+
height: 0;
|
|
1238
|
+
pointer-events: none;
|
|
1239
|
+
z-index: 2147483638;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.bt-note-marker {
|
|
1243
|
+
position: fixed;
|
|
1244
|
+
pointer-events: auto;
|
|
1245
|
+
background: linear-gradient(135deg, #2563eb, #1d4ed8);
|
|
1246
|
+
color: #ffffff;
|
|
1247
|
+
border: 2px solid #ffffff;
|
|
1248
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.5), 0 0 0 1px rgba(37,99,235,0.4);
|
|
1249
|
+
border-radius: 999px;
|
|
1250
|
+
height: 26px;
|
|
1251
|
+
min-width: 26px;
|
|
1252
|
+
padding: 0 7px;
|
|
1253
|
+
display: inline-flex;
|
|
1254
|
+
align-items: center;
|
|
1255
|
+
justify-content: center;
|
|
1256
|
+
gap: 4px;
|
|
1257
|
+
cursor: pointer;
|
|
1258
|
+
font-size: 11px;
|
|
1259
|
+
font-weight: 700;
|
|
1260
|
+
user-select: none;
|
|
1261
|
+
transition: transform 0.15s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.15s ease;
|
|
1262
|
+
animation: bt-pop-in 0.2s ease-out;
|
|
1263
|
+
box-sizing: border-box;
|
|
1264
|
+
z-index: 2147483641;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
@keyframes bt-pop-in {
|
|
1268
|
+
0% { transform: scale(0.6); opacity: 0; }
|
|
1269
|
+
100% { transform: scale(1); opacity: 1; }
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
.bt-note-marker:hover {
|
|
1273
|
+
transform: scale(1.15) translateY(-2px);
|
|
1274
|
+
box-shadow: 0 8px 20px rgba(37,99,235,0.6), 0 0 0 2px #60a5fa;
|
|
1153
1275
|
}
|
|
1154
1276
|
|
|
1155
|
-
|
|
1277
|
+
.bt-marker-resolved {
|
|
1278
|
+
background: linear-gradient(135deg, #475569, #334155);
|
|
1279
|
+
border-color: #94a3b8;
|
|
1280
|
+
opacity: 0.75;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
.bt-region-marker-box {
|
|
1284
|
+
position: fixed;
|
|
1285
|
+
border: 2px dashed #0284c7;
|
|
1286
|
+
background: rgba(14, 165, 233, 0.08);
|
|
1287
|
+
pointer-events: none;
|
|
1288
|
+
box-sizing: border-box;
|
|
1289
|
+
border-radius: 6px;
|
|
1290
|
+
z-index: 2147483639;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
.bt-page-notes-dock {
|
|
1294
|
+
position: fixed;
|
|
1295
|
+
top: 16px;
|
|
1296
|
+
right: 16px;
|
|
1297
|
+
display: flex;
|
|
1298
|
+
flex-direction: column;
|
|
1299
|
+
gap: 6px;
|
|
1300
|
+
pointer-events: none;
|
|
1301
|
+
z-index: 2147483641;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.bt-page-note-pill {
|
|
1305
|
+
background: #0f172a;
|
|
1306
|
+
color: #c084fc;
|
|
1307
|
+
border: 1px solid #7e22ce;
|
|
1308
|
+
border-radius: 20px;
|
|
1309
|
+
padding: 5px 12px;
|
|
1310
|
+
font-size: 11.5px;
|
|
1311
|
+
font-weight: 600;
|
|
1312
|
+
display: inline-flex;
|
|
1313
|
+
align-items: center;
|
|
1314
|
+
gap: 6px;
|
|
1315
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.5);
|
|
1316
|
+
cursor: pointer;
|
|
1317
|
+
pointer-events: auto;
|
|
1318
|
+
transition: all 0.15s ease;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
.bt-page-note-pill:hover {
|
|
1322
|
+
background: #1e1b4b;
|
|
1323
|
+
transform: translateY(-1px);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
/* 4. Floating Quick Toolbar */
|
|
1156
1327
|
.bt-toolbar {
|
|
1157
1328
|
position: fixed;
|
|
1158
1329
|
bottom: 20px;
|
|
1159
1330
|
right: 20px;
|
|
1160
|
-
background: #
|
|
1331
|
+
background: #0f172a;
|
|
1161
1332
|
border: 1px solid #334155;
|
|
1162
1333
|
border-radius: 30px;
|
|
1163
1334
|
padding: 4px 6px;
|
|
1164
1335
|
display: flex;
|
|
1165
1336
|
align-items: center;
|
|
1166
1337
|
gap: 4px;
|
|
1167
|
-
box-shadow: 0 10px
|
|
1338
|
+
box-shadow: 0 10px 25px -3px rgba(0,0,0,0.6), 0 4px 6px -4px rgba(0,0,0,0.4);
|
|
1168
1339
|
pointer-events: auto;
|
|
1169
1340
|
z-index: 2147483646;
|
|
1170
1341
|
user-select: none;
|
|
@@ -1177,17 +1348,18 @@ var NoteInspector = class {
|
|
|
1177
1348
|
color: #94a3b8;
|
|
1178
1349
|
font-size: 12px;
|
|
1179
1350
|
font-weight: 500;
|
|
1180
|
-
padding: 6px
|
|
1351
|
+
padding: 6px 12px;
|
|
1181
1352
|
border-radius: 20px;
|
|
1182
1353
|
cursor: pointer;
|
|
1183
1354
|
display: flex;
|
|
1184
1355
|
align-items: center;
|
|
1185
|
-
gap:
|
|
1356
|
+
gap: 6px;
|
|
1186
1357
|
transition: all 0.15s ease;
|
|
1358
|
+
font-family: inherit;
|
|
1187
1359
|
}
|
|
1188
1360
|
|
|
1189
1361
|
.bt-toolbar-btn:hover {
|
|
1190
|
-
background: #
|
|
1362
|
+
background: #1e293b;
|
|
1191
1363
|
color: #f8fafc;
|
|
1192
1364
|
}
|
|
1193
1365
|
|
|
@@ -1195,15 +1367,27 @@ var NoteInspector = class {
|
|
|
1195
1367
|
background: #2563eb;
|
|
1196
1368
|
color: #ffffff;
|
|
1197
1369
|
font-weight: 600;
|
|
1370
|
+
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.35);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
.bt-count-pill {
|
|
1374
|
+
background: rgba(255, 255, 255, 0.2);
|
|
1375
|
+
color: #ffffff;
|
|
1376
|
+
font-size: 10px;
|
|
1377
|
+
font-weight: 700;
|
|
1378
|
+
padding: 1px 6px;
|
|
1379
|
+
border-radius: 10px;
|
|
1380
|
+
line-height: 1.2;
|
|
1198
1381
|
}
|
|
1199
1382
|
|
|
1200
1383
|
.bt-toolbar-divider {
|
|
1201
1384
|
width: 1px;
|
|
1202
1385
|
height: 16px;
|
|
1203
1386
|
background: #334155;
|
|
1387
|
+
margin: 0 2px;
|
|
1204
1388
|
}
|
|
1205
1389
|
|
|
1206
|
-
/*
|
|
1390
|
+
/* 5. Modals & Popover Card */
|
|
1207
1391
|
.bt-modal-backdrop {
|
|
1208
1392
|
position: fixed;
|
|
1209
1393
|
top: 0;
|
|
@@ -1211,7 +1395,7 @@ var NoteInspector = class {
|
|
|
1211
1395
|
width: 100vw;
|
|
1212
1396
|
height: 100vh;
|
|
1213
1397
|
background: rgba(15, 23, 42, 0.75);
|
|
1214
|
-
backdrop-filter: blur(
|
|
1398
|
+
backdrop-filter: blur(6px);
|
|
1215
1399
|
display: flex;
|
|
1216
1400
|
align-items: center;
|
|
1217
1401
|
justify-content: center;
|
|
@@ -1219,20 +1403,26 @@ var NoteInspector = class {
|
|
|
1219
1403
|
z-index: 2147483647;
|
|
1220
1404
|
opacity: 1;
|
|
1221
1405
|
box-sizing: border-box;
|
|
1406
|
+
animation: bt-fade-in 0.15s ease-out;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
@keyframes bt-fade-in {
|
|
1410
|
+
from { opacity: 0; transform: scale(0.98); }
|
|
1411
|
+
to { opacity: 1; transform: scale(1); }
|
|
1222
1412
|
}
|
|
1223
1413
|
|
|
1224
1414
|
.bt-modal {
|
|
1225
|
-
background: #
|
|
1415
|
+
background: #0f172a;
|
|
1226
1416
|
color: #f8fafc;
|
|
1227
1417
|
border: 1px solid #334155;
|
|
1228
|
-
border-radius:
|
|
1229
|
-
padding:
|
|
1230
|
-
width:
|
|
1231
|
-
max-width:
|
|
1232
|
-
box-shadow: 0
|
|
1418
|
+
border-radius: 14px;
|
|
1419
|
+
padding: 20px;
|
|
1420
|
+
width: 450px;
|
|
1421
|
+
max-width: 92vw;
|
|
1422
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255, 255, 255, 0.05);
|
|
1233
1423
|
display: flex;
|
|
1234
1424
|
flex-direction: column;
|
|
1235
|
-
gap:
|
|
1425
|
+
gap: 14px;
|
|
1236
1426
|
box-sizing: border-box;
|
|
1237
1427
|
}
|
|
1238
1428
|
|
|
@@ -1243,87 +1433,181 @@ var NoteInspector = class {
|
|
|
1243
1433
|
}
|
|
1244
1434
|
|
|
1245
1435
|
.bt-modal-title {
|
|
1246
|
-
font-size:
|
|
1436
|
+
font-size: 14.5px;
|
|
1247
1437
|
font-weight: 600;
|
|
1438
|
+
letter-spacing: -0.01em;
|
|
1248
1439
|
display: flex;
|
|
1249
1440
|
align-items: center;
|
|
1250
|
-
gap:
|
|
1441
|
+
gap: 8px;
|
|
1251
1442
|
color: #f8fafc;
|
|
1252
1443
|
}
|
|
1253
1444
|
|
|
1254
1445
|
.bt-mode-badge {
|
|
1255
1446
|
font-size: 10px;
|
|
1256
1447
|
font-weight: 700;
|
|
1448
|
+
letter-spacing: 0.05em;
|
|
1257
1449
|
text-transform: uppercase;
|
|
1258
|
-
|
|
1450
|
+
padding: 2px 7px;
|
|
1451
|
+
border-radius: 6px;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
.bt-badge-element {
|
|
1455
|
+
background: rgba(59, 130, 246, 0.15);
|
|
1259
1456
|
color: #60a5fa;
|
|
1260
|
-
border: 1px solid
|
|
1261
|
-
|
|
1262
|
-
|
|
1457
|
+
border: 1px solid rgba(59, 130, 246, 0.4);
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
.bt-badge-region {
|
|
1461
|
+
background: rgba(14, 165, 233, 0.15);
|
|
1462
|
+
color: #38bdf8;
|
|
1463
|
+
border: 1px solid rgba(14, 165, 233, 0.4);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
.bt-badge-page {
|
|
1467
|
+
background: rgba(168, 85, 247, 0.15);
|
|
1468
|
+
color: #c084fc;
|
|
1469
|
+
border: 1px solid rgba(168, 85, 247, 0.4);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
.bt-badge-status-open {
|
|
1473
|
+
background: rgba(16, 185, 129, 0.15);
|
|
1474
|
+
color: #34d399;
|
|
1475
|
+
border: 1px solid rgba(16, 185, 129, 0.4);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
.bt-badge-status-resolved {
|
|
1479
|
+
background: rgba(100, 116, 139, 0.2);
|
|
1480
|
+
color: #94a3b8;
|
|
1481
|
+
border: 1px solid rgba(100, 116, 139, 0.4);
|
|
1263
1482
|
}
|
|
1264
1483
|
|
|
1265
1484
|
.bt-close-btn {
|
|
1266
1485
|
background: transparent;
|
|
1267
1486
|
border: none;
|
|
1268
1487
|
color: #94a3b8;
|
|
1269
|
-
font-size:
|
|
1488
|
+
font-size: 15px;
|
|
1270
1489
|
cursor: pointer;
|
|
1271
|
-
padding:
|
|
1272
|
-
border-radius:
|
|
1490
|
+
padding: 3px 7px;
|
|
1491
|
+
border-radius: 6px;
|
|
1492
|
+
transition: all 0.12s ease;
|
|
1493
|
+
display: flex;
|
|
1494
|
+
align-items: center;
|
|
1495
|
+
justify-content: center;
|
|
1273
1496
|
}
|
|
1274
1497
|
.bt-close-btn:hover {
|
|
1275
|
-
background: #
|
|
1498
|
+
background: #1e293b;
|
|
1276
1499
|
color: #ffffff;
|
|
1277
1500
|
}
|
|
1278
1501
|
|
|
1279
1502
|
.bt-target-pill {
|
|
1280
|
-
background: #
|
|
1503
|
+
background: #090d16;
|
|
1281
1504
|
color: #94a3b8;
|
|
1282
|
-
border: 1px solid #
|
|
1283
|
-
border-radius:
|
|
1284
|
-
padding:
|
|
1505
|
+
border: 1px solid #1e293b;
|
|
1506
|
+
border-radius: 8px;
|
|
1507
|
+
padding: 8px 12px;
|
|
1285
1508
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1286
|
-
font-size:
|
|
1509
|
+
font-size: 11.5px;
|
|
1510
|
+
display: flex;
|
|
1511
|
+
align-items: center;
|
|
1512
|
+
gap: 8px;
|
|
1513
|
+
overflow: hidden;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.bt-pill-content {
|
|
1287
1517
|
overflow: hidden;
|
|
1288
1518
|
text-overflow: ellipsis;
|
|
1289
1519
|
white-space: nowrap;
|
|
1520
|
+
color: #cbd5e1;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
.bt-note-message-box {
|
|
1524
|
+
background: #090d16;
|
|
1525
|
+
border: 1px solid #1e293b;
|
|
1526
|
+
border-radius: 8px;
|
|
1527
|
+
padding: 12px 14px;
|
|
1528
|
+
font-size: 13.5px;
|
|
1529
|
+
line-height: 1.5;
|
|
1530
|
+
color: #f1f5f9;
|
|
1531
|
+
white-space: pre-wrap;
|
|
1532
|
+
word-break: break-word;
|
|
1533
|
+
max-height: 180px;
|
|
1534
|
+
overflow-y: auto;
|
|
1290
1535
|
}
|
|
1291
1536
|
|
|
1292
1537
|
.bt-textarea {
|
|
1293
|
-
background: #
|
|
1538
|
+
background: #090d16;
|
|
1294
1539
|
color: #f8fafc;
|
|
1295
1540
|
border: 1px solid #334155;
|
|
1296
|
-
border-radius:
|
|
1297
|
-
padding:
|
|
1298
|
-
font-size:
|
|
1541
|
+
border-radius: 8px;
|
|
1542
|
+
padding: 12px;
|
|
1543
|
+
font-size: 13.5px;
|
|
1544
|
+
line-height: 1.5;
|
|
1299
1545
|
resize: vertical;
|
|
1300
|
-
min-height:
|
|
1546
|
+
min-height: 95px;
|
|
1301
1547
|
outline: none;
|
|
1302
1548
|
box-sizing: border-box;
|
|
1303
1549
|
width: 100%;
|
|
1304
1550
|
font-family: inherit;
|
|
1551
|
+
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.bt-textarea::placeholder {
|
|
1555
|
+
color: #64748b;
|
|
1305
1556
|
}
|
|
1306
1557
|
|
|
1307
1558
|
.bt-textarea:focus {
|
|
1308
1559
|
border-color: #3b82f6;
|
|
1309
|
-
box-shadow: 0 0 0
|
|
1560
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.bt-modal-footer {
|
|
1564
|
+
display: flex;
|
|
1565
|
+
justify-content: space-between;
|
|
1566
|
+
align-items: center;
|
|
1567
|
+
gap: 12px;
|
|
1568
|
+
margin-top: 2px;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
.bt-kbd-hint {
|
|
1572
|
+
font-size: 11px;
|
|
1573
|
+
color: #64748b;
|
|
1574
|
+
display: flex;
|
|
1575
|
+
align-items: center;
|
|
1576
|
+
gap: 4px;
|
|
1577
|
+
user-select: none;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
.bt-kbd-hint kbd {
|
|
1581
|
+
background: #1e293b;
|
|
1582
|
+
color: #94a3b8;
|
|
1583
|
+
border: 1px solid #334155;
|
|
1584
|
+
border-radius: 4px;
|
|
1585
|
+
padding: 1px 5px;
|
|
1586
|
+
font-family: inherit;
|
|
1587
|
+
font-size: 10px;
|
|
1588
|
+
font-weight: 600;
|
|
1310
1589
|
}
|
|
1311
1590
|
|
|
1312
1591
|
.bt-modal-actions {
|
|
1313
1592
|
display: flex;
|
|
1314
1593
|
justify-content: flex-end;
|
|
1594
|
+
align-items: center;
|
|
1315
1595
|
gap: 8px;
|
|
1316
1596
|
}
|
|
1317
1597
|
|
|
1318
1598
|
.bt-btn {
|
|
1319
|
-
padding: 8px
|
|
1320
|
-
border-radius:
|
|
1321
|
-
font-size:
|
|
1599
|
+
padding: 8px 16px;
|
|
1600
|
+
border-radius: 7px;
|
|
1601
|
+
font-size: 12.5px;
|
|
1322
1602
|
font-weight: 600;
|
|
1323
1603
|
cursor: pointer;
|
|
1324
1604
|
border: 1px solid transparent;
|
|
1325
|
-
transition: all 0.
|
|
1605
|
+
transition: all 0.15s ease;
|
|
1326
1606
|
font-family: inherit;
|
|
1607
|
+
display: inline-flex;
|
|
1608
|
+
align-items: center;
|
|
1609
|
+
justify-content: center;
|
|
1610
|
+
gap: 6px;
|
|
1327
1611
|
}
|
|
1328
1612
|
|
|
1329
1613
|
.bt-btn-cancel {
|
|
@@ -1331,20 +1615,38 @@ var NoteInspector = class {
|
|
|
1331
1615
|
color: #94a3b8;
|
|
1332
1616
|
}
|
|
1333
1617
|
.bt-btn-cancel:hover {
|
|
1334
|
-
background: #
|
|
1618
|
+
background: #1e293b;
|
|
1335
1619
|
color: #f8fafc;
|
|
1336
1620
|
}
|
|
1337
1621
|
|
|
1338
1622
|
.bt-btn-save {
|
|
1339
1623
|
background: #2563eb;
|
|
1340
1624
|
color: #ffffff;
|
|
1625
|
+
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.35);
|
|
1341
1626
|
}
|
|
1342
1627
|
.bt-btn-save:hover {
|
|
1343
1628
|
background: #1d4ed8;
|
|
1629
|
+
box-shadow: 0 4px 10px rgba(37, 99, 235, 0.45);
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
.bt-btn-resolve {
|
|
1633
|
+
background: rgba(16, 185, 129, 0.15);
|
|
1634
|
+
color: #6ee7b7;
|
|
1635
|
+
border: 1px solid rgba(16, 185, 129, 0.35);
|
|
1636
|
+
}
|
|
1637
|
+
.bt-btn-resolve:hover {
|
|
1638
|
+
background: rgba(16, 185, 129, 0.3);
|
|
1639
|
+
color: #ffffff;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
.bt-btn-delete {
|
|
1643
|
+
background: rgba(239, 68, 68, 0.15);
|
|
1644
|
+
color: #fca5a5;
|
|
1645
|
+
border: 1px solid rgba(239, 68, 68, 0.35);
|
|
1344
1646
|
}
|
|
1345
|
-
.bt-btn-
|
|
1346
|
-
|
|
1347
|
-
|
|
1647
|
+
.bt-btn-delete:hover {
|
|
1648
|
+
background: rgba(239, 68, 68, 0.3);
|
|
1649
|
+
color: #ffffff;
|
|
1348
1650
|
}
|
|
1349
1651
|
`;
|
|
1350
1652
|
this.shadowRoot.appendChild(style);
|
|
@@ -1352,6 +1654,9 @@ var NoteInspector = class {
|
|
|
1352
1654
|
this.highlightOverlay.className = "bt-highlight";
|
|
1353
1655
|
this.highlightOverlay.style.display = "none";
|
|
1354
1656
|
this.shadowRoot.appendChild(this.highlightOverlay);
|
|
1657
|
+
this.markersContainer = document.createElement("div");
|
|
1658
|
+
this.markersContainer.className = "bt-markers-layer";
|
|
1659
|
+
this.shadowRoot.appendChild(this.markersContainer);
|
|
1355
1660
|
if (this.options.showToolbar) {
|
|
1356
1661
|
this.createToolbar();
|
|
1357
1662
|
}
|
|
@@ -1378,19 +1683,33 @@ var NoteInspector = class {
|
|
|
1378
1683
|
<button class="bt-toolbar-btn" id="bt-mode-page" title="Leave full-page note">
|
|
1379
1684
|
<span>\u{1F4C4}</span> Page
|
|
1380
1685
|
</button>
|
|
1686
|
+
<div class="bt-toolbar-divider"></div>
|
|
1687
|
+
<button class="bt-toolbar-btn active" id="bt-toggle-notes" title="Toggle visible note markers on screen">
|
|
1688
|
+
<span>\u{1F4CC}</span> Notes <span class="bt-count-pill" id="bt-notes-count">0</span>
|
|
1689
|
+
</button>
|
|
1381
1690
|
`;
|
|
1382
1691
|
const btnElement = this.toolbarElement.querySelector("#bt-mode-element");
|
|
1383
1692
|
const btnRegion = this.toolbarElement.querySelector("#bt-mode-region");
|
|
1384
1693
|
const btnPage = this.toolbarElement.querySelector("#bt-mode-page");
|
|
1385
|
-
|
|
1694
|
+
const btnToggleNotes = this.toolbarElement.querySelector("#bt-toggle-notes");
|
|
1695
|
+
btnElement.onclick = (e) => {
|
|
1696
|
+
e.stopPropagation();
|
|
1386
1697
|
this.setMode(this.activeMode === "element" ? "idle" : "element");
|
|
1387
1698
|
};
|
|
1388
|
-
btnRegion.onclick = () => {
|
|
1699
|
+
btnRegion.onclick = (e) => {
|
|
1700
|
+
e.stopPropagation();
|
|
1389
1701
|
this.setMode(this.activeMode === "region" ? "idle" : "region");
|
|
1390
1702
|
};
|
|
1391
|
-
btnPage.onclick = () => {
|
|
1703
|
+
btnPage.onclick = (e) => {
|
|
1704
|
+
e.stopPropagation();
|
|
1392
1705
|
this.setMode("page");
|
|
1393
1706
|
};
|
|
1707
|
+
btnToggleNotes.onclick = (e) => {
|
|
1708
|
+
e.stopPropagation();
|
|
1709
|
+
this.showMarkers = !this.showMarkers;
|
|
1710
|
+
btnToggleNotes.classList.toggle("active", this.showMarkers);
|
|
1711
|
+
this.renderMarkers();
|
|
1712
|
+
};
|
|
1394
1713
|
this.shadowRoot.appendChild(this.toolbarElement);
|
|
1395
1714
|
}
|
|
1396
1715
|
updateToolbarState() {
|
|
@@ -1402,9 +1721,186 @@ var NoteInspector = class {
|
|
|
1402
1721
|
btnRegion?.classList.toggle("active", this.activeMode === "region");
|
|
1403
1722
|
btnPage?.classList.toggle("active", this.activeMode === "page");
|
|
1404
1723
|
}
|
|
1724
|
+
updateToolbarCount() {
|
|
1725
|
+
if (!this.toolbarElement) return;
|
|
1726
|
+
const countEl = this.toolbarElement.querySelector("#bt-notes-count");
|
|
1727
|
+
if (countEl) {
|
|
1728
|
+
const openCount = this.savedNotes.filter((n) => n.status === "OPEN").length;
|
|
1729
|
+
countEl.textContent = String(openCount);
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
renderMarkers() {
|
|
1733
|
+
const root = this.ensureContainer();
|
|
1734
|
+
if (!root || !this.markersContainer) return;
|
|
1735
|
+
this.markersContainer.innerHTML = "";
|
|
1736
|
+
if (!this.showMarkers) return;
|
|
1737
|
+
const currentPath = window.location.pathname;
|
|
1738
|
+
const activeNotes = this.savedNotes.filter(
|
|
1739
|
+
(n) => n.status === "OPEN" && (n.route === currentPath || !n.route || n.route === "/" || window.location.href.includes(n.route))
|
|
1740
|
+
);
|
|
1741
|
+
const pageNotes = [];
|
|
1742
|
+
activeNotes.forEach((note, index) => {
|
|
1743
|
+
if (note.type === "page") {
|
|
1744
|
+
pageNotes.push(note);
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
if (note.type === "region" && note.region) {
|
|
1748
|
+
const regBox = document.createElement("div");
|
|
1749
|
+
regBox.className = "bt-region-marker-box";
|
|
1750
|
+
regBox.style.left = `${note.region.x}px`;
|
|
1751
|
+
regBox.style.top = `${note.region.y}px`;
|
|
1752
|
+
regBox.style.width = `${note.region.width}px`;
|
|
1753
|
+
regBox.style.height = `${note.region.height}px`;
|
|
1754
|
+
this.markersContainer.appendChild(regBox);
|
|
1755
|
+
const pin = document.createElement("div");
|
|
1756
|
+
pin.className = "bt-note-marker";
|
|
1757
|
+
pin.style.left = `${Math.max(4, note.region.x - 12)}px`;
|
|
1758
|
+
pin.style.top = `${Math.max(4, note.region.y - 12)}px`;
|
|
1759
|
+
pin.title = note.message;
|
|
1760
|
+
pin.innerHTML = `<span>\u{1F4D0}</span> <span>#${index + 1}</span>`;
|
|
1761
|
+
pin.onclick = (e) => {
|
|
1762
|
+
e.stopPropagation();
|
|
1763
|
+
this.openNoteCard(note);
|
|
1764
|
+
};
|
|
1765
|
+
this.markersContainer.appendChild(pin);
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
let targetEl = null;
|
|
1769
|
+
if (note.target?.selector) {
|
|
1770
|
+
try {
|
|
1771
|
+
targetEl = document.querySelector(note.target.selector);
|
|
1772
|
+
} catch {
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
const rect = targetEl ? targetEl.getBoundingClientRect() : note.target?.boundingRect;
|
|
1776
|
+
if (rect) {
|
|
1777
|
+
const pin = document.createElement("div");
|
|
1778
|
+
pin.className = "bt-note-marker";
|
|
1779
|
+
pin.setAttribute("data-note-id", note.id);
|
|
1780
|
+
pin.title = note.message;
|
|
1781
|
+
pin.style.left = `${Math.max(4, rect.left - 10)}px`;
|
|
1782
|
+
pin.style.top = `${Math.max(4, rect.top - 12)}px`;
|
|
1783
|
+
pin.innerHTML = `<span>\u{1F4DD}</span> <span>#${index + 1}</span>`;
|
|
1784
|
+
pin.onclick = (e) => {
|
|
1785
|
+
e.stopPropagation();
|
|
1786
|
+
this.openNoteCard(note);
|
|
1787
|
+
};
|
|
1788
|
+
if (targetEl) {
|
|
1789
|
+
pin.onmouseenter = () => this.updateHighlight(targetEl);
|
|
1790
|
+
pin.onmouseleave = () => this.hideHighlight();
|
|
1791
|
+
}
|
|
1792
|
+
this.markersContainer.appendChild(pin);
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
if (pageNotes.length > 0) {
|
|
1796
|
+
const pageDock = document.createElement("div");
|
|
1797
|
+
pageDock.className = "bt-page-notes-dock";
|
|
1798
|
+
pageNotes.forEach((pNote, idx) => {
|
|
1799
|
+
const pill = document.createElement("div");
|
|
1800
|
+
pill.className = "bt-page-note-pill";
|
|
1801
|
+
pill.innerHTML = `<span>\u{1F4C4}</span> <span>Page Note (${truncate(pNote.message, 25)})</span>`;
|
|
1802
|
+
pill.onclick = (e) => {
|
|
1803
|
+
e.stopPropagation();
|
|
1804
|
+
this.openNoteCard(pNote);
|
|
1805
|
+
};
|
|
1806
|
+
pageDock.appendChild(pill);
|
|
1807
|
+
});
|
|
1808
|
+
this.markersContainer.appendChild(pageDock);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
updateMarkerPositions() {
|
|
1812
|
+
if (!this.showMarkers || !this.markersContainer) return;
|
|
1813
|
+
this.renderMarkers();
|
|
1814
|
+
}
|
|
1815
|
+
openNoteCard(note) {
|
|
1816
|
+
const root = this.ensureContainer();
|
|
1817
|
+
if (!root) return;
|
|
1818
|
+
if (this.cardOverlay && this.cardOverlay.parentElement) {
|
|
1819
|
+
this.cardOverlay.parentElement.removeChild(this.cardOverlay);
|
|
1820
|
+
this.cardOverlay = null;
|
|
1821
|
+
}
|
|
1822
|
+
const backdrop = document.createElement("div");
|
|
1823
|
+
backdrop.className = "bt-modal-backdrop";
|
|
1824
|
+
this.cardOverlay = backdrop;
|
|
1825
|
+
const badgeClass = `bt-badge-${note.type.toLowerCase()}`;
|
|
1826
|
+
const statusClass = note.status === "OPEN" ? "bt-badge-status-open" : "bt-badge-status-resolved";
|
|
1827
|
+
const icon = note.type === "region" ? "\u{1F4D0}" : note.type === "page" ? "\u{1F4C4}" : "\u{1F3AF}";
|
|
1828
|
+
const contextText = note.type === "region" && note.region ? `Region: ${note.region.width} \xD7 ${note.region.height} px \xB7 Route: ${note.route}` : note.type === "page" ? `Page Note \xB7 Route: ${note.route}` : `${note.target?.selector || "Element"} (${note.target?.boundingRect?.width || 0}\xD7${note.target?.boundingRect?.height || 0}px) \xB7 ${note.route}`;
|
|
1829
|
+
const formattedDate = new Date(note.createdAt).toLocaleString();
|
|
1830
|
+
backdrop.innerHTML = `
|
|
1831
|
+
<div class="bt-modal">
|
|
1832
|
+
<div class="bt-modal-header">
|
|
1833
|
+
<div class="bt-modal-title">
|
|
1834
|
+
<span>${icon} Visual Note Details</span>
|
|
1835
|
+
<span class="bt-mode-badge ${badgeClass}">${note.type.toUpperCase()}</span>
|
|
1836
|
+
<span class="bt-mode-badge ${statusClass}">${note.status}</span>
|
|
1837
|
+
</div>
|
|
1838
|
+
<button class="bt-close-btn" id="btn-card-close" title="Close (Esc)">\u2715</button>
|
|
1839
|
+
</div>
|
|
1840
|
+
|
|
1841
|
+
<div class="bt-target-pill" title="${contextText}">
|
|
1842
|
+
<span>\u{1F3F7}\uFE0F</span>
|
|
1843
|
+
<span class="bt-pill-content">${contextText}</span>
|
|
1844
|
+
</div>
|
|
1845
|
+
|
|
1846
|
+
<div class="bt-note-message-box">${note.message}</div>
|
|
1847
|
+
|
|
1848
|
+
<div style="font-size: 11px; color: #64748b; display: flex; justify-content: space-between; padding: 0 2px;">
|
|
1849
|
+
<span>Created: ${formattedDate}</span>
|
|
1850
|
+
<span>ID: <code style="font-family: monospace; color: #94a3b8;">${note.id}</code></span>
|
|
1851
|
+
</div>
|
|
1852
|
+
|
|
1853
|
+
<div class="bt-modal-footer">
|
|
1854
|
+
<button class="bt-btn bt-btn-delete" id="btn-card-delete" title="Delete this note">
|
|
1855
|
+
<span>\u{1F5D1}\uFE0F</span> Delete
|
|
1856
|
+
</button>
|
|
1857
|
+
<div class="bt-modal-actions">
|
|
1858
|
+
<button class="bt-btn bt-btn-cancel" id="btn-card-dismiss">Close</button>
|
|
1859
|
+
<button class="bt-btn ${note.status === "OPEN" ? "bt-btn-resolve" : "bt-btn-save"}" id="btn-card-resolve">
|
|
1860
|
+
${note.status === "OPEN" ? "<span>\u2705</span> Resolve Note" : "<span>\u21BA</span> Reopen"}
|
|
1861
|
+
</button>
|
|
1862
|
+
</div>
|
|
1863
|
+
</div>
|
|
1864
|
+
</div>
|
|
1865
|
+
`;
|
|
1866
|
+
const btnClose = backdrop.querySelector("#btn-card-close");
|
|
1867
|
+
const btnDismiss = backdrop.querySelector("#btn-card-dismiss");
|
|
1868
|
+
const btnResolve = backdrop.querySelector("#btn-card-resolve");
|
|
1869
|
+
const btnDelete = backdrop.querySelector("#btn-card-delete");
|
|
1870
|
+
const closeCard = () => {
|
|
1871
|
+
if (this.cardOverlay) {
|
|
1872
|
+
root.removeChild(this.cardOverlay);
|
|
1873
|
+
this.cardOverlay = null;
|
|
1874
|
+
this.hideHighlight();
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
btnClose.onclick = closeCard;
|
|
1878
|
+
btnDismiss.onclick = closeCard;
|
|
1879
|
+
backdrop.onclick = (e) => {
|
|
1880
|
+
if (e.target === backdrop) closeCard();
|
|
1881
|
+
};
|
|
1882
|
+
btnResolve.onclick = () => {
|
|
1883
|
+
if (note.status === "OPEN") {
|
|
1884
|
+
this.transport.send({ type: "resolve_note", noteId: note.id });
|
|
1885
|
+
} else {
|
|
1886
|
+
this.transport.send({ type: "reopen_note", noteId: note.id });
|
|
1887
|
+
}
|
|
1888
|
+
closeCard();
|
|
1889
|
+
};
|
|
1890
|
+
btnDelete.onclick = () => {
|
|
1891
|
+
this.transport.send({ type: "delete_note", noteId: note.id });
|
|
1892
|
+
closeCard();
|
|
1893
|
+
};
|
|
1894
|
+
root.appendChild(backdrop);
|
|
1895
|
+
}
|
|
1405
1896
|
setupListeners() {
|
|
1406
1897
|
const onMouseMove = (e) => {
|
|
1407
|
-
if (this.modalOverlay || this.isDraggingRegion || this.activeMode === "region") return;
|
|
1898
|
+
if (this.modalOverlay || this.cardOverlay || this.isDraggingRegion || this.activeMode === "region") return;
|
|
1899
|
+
const path = e.composedPath ? e.composedPath() : [];
|
|
1900
|
+
if (this.container && path.includes(this.container)) {
|
|
1901
|
+
this.hideHighlight();
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1408
1904
|
if (e.altKey || this.activeMode === "element") {
|
|
1409
1905
|
const target = document.elementFromPoint(e.clientX, e.clientY);
|
|
1410
1906
|
if (target && target !== this.container && !this.container?.contains(target)) {
|
|
@@ -1418,7 +1914,12 @@ var NoteInspector = class {
|
|
|
1418
1914
|
}
|
|
1419
1915
|
};
|
|
1420
1916
|
const onClick = (e) => {
|
|
1421
|
-
if (this.modalOverlay || this.
|
|
1917
|
+
if (this.modalOverlay || this.cardOverlay) return;
|
|
1918
|
+
const path = e.composedPath ? e.composedPath() : [];
|
|
1919
|
+
if (this.container && path.includes(this.container)) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
if (this.activeMode === "region") return;
|
|
1422
1923
|
if (e.altKey || this.activeMode === "element") {
|
|
1423
1924
|
e.preventDefault();
|
|
1424
1925
|
e.stopPropagation();
|
|
@@ -1432,18 +1933,39 @@ var NoteInspector = class {
|
|
|
1432
1933
|
}
|
|
1433
1934
|
}
|
|
1434
1935
|
};
|
|
1936
|
+
const onKeyDown = (e) => {
|
|
1937
|
+
if (e.key === "Escape") {
|
|
1938
|
+
if (this.cardOverlay && this.cardOverlay.parentElement && this.shadowRoot) {
|
|
1939
|
+
this.shadowRoot.removeChild(this.cardOverlay);
|
|
1940
|
+
this.cardOverlay = null;
|
|
1941
|
+
} else if (this.activeMode === "region" || this.activeMode === "element") {
|
|
1942
|
+
this.setMode("idle");
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1435
1946
|
const onKeyUp = (e) => {
|
|
1436
|
-
if (e.key === "Alt" && !this.modalOverlay && this.activeMode !== "element") {
|
|
1947
|
+
if (e.key === "Alt" && !this.modalOverlay && !this.cardOverlay && this.activeMode !== "element") {
|
|
1437
1948
|
this.hideHighlight();
|
|
1438
1949
|
}
|
|
1439
1950
|
};
|
|
1951
|
+
const onScrollOrResize = () => {
|
|
1952
|
+
requestAnimationFrame(() => {
|
|
1953
|
+
this.updateMarkerPositions();
|
|
1954
|
+
});
|
|
1955
|
+
};
|
|
1440
1956
|
window.addEventListener("mousemove", onMouseMove, { capture: true, passive: true });
|
|
1441
1957
|
window.addEventListener("click", onClick, { capture: true });
|
|
1958
|
+
window.addEventListener("keydown", onKeyDown, { capture: true });
|
|
1442
1959
|
window.addEventListener("keyup", onKeyUp, { capture: true });
|
|
1960
|
+
window.addEventListener("scroll", onScrollOrResize, { capture: true, passive: true });
|
|
1961
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
1443
1962
|
this.cleanups.push(() => {
|
|
1444
1963
|
window.removeEventListener("mousemove", onMouseMove, { capture: true });
|
|
1445
1964
|
window.removeEventListener("click", onClick, { capture: true });
|
|
1965
|
+
window.removeEventListener("keydown", onKeyDown, { capture: true });
|
|
1446
1966
|
window.removeEventListener("keyup", onKeyUp, { capture: true });
|
|
1967
|
+
window.removeEventListener("scroll", onScrollOrResize, { capture: true });
|
|
1968
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
1447
1969
|
});
|
|
1448
1970
|
}
|
|
1449
1971
|
showRegionOverlay() {
|
|
@@ -1456,7 +1978,26 @@ var NoteInspector = class {
|
|
|
1456
1978
|
this.regionBox.className = "bt-region-box";
|
|
1457
1979
|
this.regionBox.style.display = "none";
|
|
1458
1980
|
this.regionOverlay.appendChild(this.regionBox);
|
|
1981
|
+
this.regionBanner = document.createElement("div");
|
|
1982
|
+
this.regionBanner.className = "bt-region-banner";
|
|
1983
|
+
this.regionBanner.innerHTML = `
|
|
1984
|
+
<span>\u{1F4D0} Drag rectangle on screen to select region</span>
|
|
1985
|
+
<button class="bt-region-cancel-btn" id="bt-region-cancel">\u2715 Cancel (Esc)</button>
|
|
1986
|
+
`;
|
|
1987
|
+
const btnCancel = this.regionBanner.querySelector("#bt-region-cancel");
|
|
1988
|
+
btnCancel.onclick = (e) => {
|
|
1989
|
+
e.stopPropagation();
|
|
1990
|
+
this.setMode("idle");
|
|
1991
|
+
};
|
|
1992
|
+
this.regionOverlay.appendChild(this.regionBanner);
|
|
1993
|
+
this.regionOverlay.oncontextmenu = (e) => {
|
|
1994
|
+
e.preventDefault();
|
|
1995
|
+
this.setMode("idle");
|
|
1996
|
+
};
|
|
1459
1997
|
this.regionOverlay.onmousedown = (e) => {
|
|
1998
|
+
const path = e.composedPath ? e.composedPath() : [];
|
|
1999
|
+
if (this.regionBanner && path.includes(this.regionBanner)) return;
|
|
2000
|
+
if (this.toolbarElement && path.includes(this.toolbarElement)) return;
|
|
1460
2001
|
this.isDraggingRegion = true;
|
|
1461
2002
|
this.dragStartX = e.clientX;
|
|
1462
2003
|
this.dragStartY = e.clientY;
|
|
@@ -1497,7 +2038,7 @@ var NoteInspector = class {
|
|
|
1497
2038
|
const top = Math.min(this.dragStartY, currentY);
|
|
1498
2039
|
const width = Math.abs(currentX - this.dragStartX);
|
|
1499
2040
|
const height = Math.abs(currentY - this.dragStartY);
|
|
1500
|
-
if (width >
|
|
2041
|
+
if (width > 15 && height > 15) {
|
|
1501
2042
|
this.selectedRegion = {
|
|
1502
2043
|
x: Math.round(left),
|
|
1503
2044
|
y: Math.round(top),
|
|
@@ -1513,11 +2054,16 @@ var NoteInspector = class {
|
|
|
1513
2054
|
}
|
|
1514
2055
|
};
|
|
1515
2056
|
}
|
|
1516
|
-
|
|
2057
|
+
if (this.toolbarElement && this.toolbarElement.parentNode === root) {
|
|
2058
|
+
root.insertBefore(this.regionOverlay, this.toolbarElement);
|
|
2059
|
+
} else {
|
|
2060
|
+
root.appendChild(this.regionOverlay);
|
|
2061
|
+
}
|
|
1517
2062
|
}
|
|
1518
2063
|
hideRegionOverlay() {
|
|
1519
|
-
|
|
1520
|
-
|
|
2064
|
+
this.isDraggingRegion = false;
|
|
2065
|
+
if (this.regionOverlay && this.regionOverlay.parentNode) {
|
|
2066
|
+
this.regionOverlay.parentNode.removeChild(this.regionOverlay);
|
|
1521
2067
|
}
|
|
1522
2068
|
if (this.regionBox) {
|
|
1523
2069
|
this.regionBox.style.display = "none";
|
|
@@ -1556,7 +2102,7 @@ var NoteInspector = class {
|
|
|
1556
2102
|
this.updateHighlight(targetEl);
|
|
1557
2103
|
}
|
|
1558
2104
|
this.renderNoteModal({
|
|
1559
|
-
title: "
|
|
2105
|
+
title: "Add Visual Note",
|
|
1560
2106
|
modeBadge: noteType.toUpperCase(),
|
|
1561
2107
|
pillText: noteType === "page" ? `Page Viewport: ${window.innerWidth} \xD7 ${window.innerHeight} px` : `${getSemanticSelector(targetEl)} (${Math.round(targetEl.getBoundingClientRect().width)}\xD7${Math.round(targetEl.getBoundingClientRect().height)}) \xB7 Viewport: ${window.innerWidth}\xD7${window.innerHeight}`,
|
|
1562
2108
|
onSave: async (message) => {
|
|
@@ -1566,7 +2112,7 @@ var NoteInspector = class {
|
|
|
1566
2112
|
}
|
|
1567
2113
|
openRegionNoteEditor(region) {
|
|
1568
2114
|
this.renderNoteModal({
|
|
1569
|
-
title: "
|
|
2115
|
+
title: "Add Region Note",
|
|
1570
2116
|
modeBadge: "REGION",
|
|
1571
2117
|
pillText: `Selected Area: x:${region.x}, y:${region.y} (${region.width} \xD7 ${region.height} px)`,
|
|
1572
2118
|
onSave: async (message) => {
|
|
@@ -1584,22 +2130,31 @@ var NoteInspector = class {
|
|
|
1584
2130
|
const backdrop = document.createElement("div");
|
|
1585
2131
|
backdrop.className = "bt-modal-backdrop";
|
|
1586
2132
|
this.modalOverlay = backdrop;
|
|
2133
|
+
const badgeClass = `bt-badge-${options.modeBadge.toLowerCase()}`;
|
|
2134
|
+
const icon = options.modeBadge === "REGION" ? "\u{1F4D0}" : options.modeBadge === "PAGE" ? "\u{1F4C4}" : "\u{1F3AF}";
|
|
2135
|
+
const isMac = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
1587
2136
|
backdrop.innerHTML = `
|
|
1588
2137
|
<div class="bt-modal">
|
|
1589
2138
|
<div class="bt-modal-header">
|
|
1590
2139
|
<div class="bt-modal-title">
|
|
1591
|
-
<span
|
|
1592
|
-
<span class="bt-mode-badge">${options.modeBadge}</span>
|
|
2140
|
+
<span>\u{1F4DD} ${options.title}</span>
|
|
2141
|
+
<span class="bt-mode-badge ${badgeClass}">${options.modeBadge}</span>
|
|
1593
2142
|
</div>
|
|
1594
|
-
<button class="bt-close-btn" id="btn-close" title="Close">\u2715</button>
|
|
2143
|
+
<button class="bt-close-btn" id="btn-close" title="Close (Esc)">\u2715</button>
|
|
1595
2144
|
</div>
|
|
1596
2145
|
<div class="bt-target-pill" title="${options.pillText}">
|
|
1597
|
-
|
|
2146
|
+
<span>${icon}</span>
|
|
2147
|
+
<span class="bt-pill-content">${options.pillText}</span>
|
|
1598
2148
|
</div>
|
|
1599
2149
|
<textarea class="bt-textarea" placeholder="Describe the layout issue, styling bug, or note for AI agent..." autofocus></textarea>
|
|
1600
|
-
<div class="bt-modal-
|
|
1601
|
-
<
|
|
1602
|
-
|
|
2150
|
+
<div class="bt-modal-footer">
|
|
2151
|
+
<div class="bt-kbd-hint">
|
|
2152
|
+
<kbd>${isMac ? "\u2318" : "Ctrl"}+Enter</kbd> save \xB7 <kbd>Esc</kbd> cancel
|
|
2153
|
+
</div>
|
|
2154
|
+
<div class="bt-modal-actions">
|
|
2155
|
+
<button class="bt-btn bt-btn-cancel" id="btn-cancel">Cancel</button>
|
|
2156
|
+
<button class="bt-btn bt-btn-save" id="btn-save">Save Note</button>
|
|
2157
|
+
</div>
|
|
1603
2158
|
</div>
|
|
1604
2159
|
</div>
|
|
1605
2160
|
`;
|
|
@@ -1819,6 +2374,12 @@ var NoteInspector = class {
|
|
|
1819
2374
|
this.container = null;
|
|
1820
2375
|
this.shadowRoot = null;
|
|
1821
2376
|
this.toolbarElement = null;
|
|
2377
|
+
this.regionOverlay = null;
|
|
2378
|
+
this.regionBox = null;
|
|
2379
|
+
this.regionBanner = null;
|
|
2380
|
+
this.markersContainer = null;
|
|
2381
|
+
this.modalOverlay = null;
|
|
2382
|
+
this.cardOverlay = null;
|
|
1822
2383
|
}
|
|
1823
2384
|
};
|
|
1824
2385
|
|
|
@@ -2077,4 +2638,4 @@ export {
|
|
|
2077
2638
|
init,
|
|
2078
2639
|
getClient
|
|
2079
2640
|
};
|
|
2080
|
-
//# sourceMappingURL=chunk-
|
|
2641
|
+
//# sourceMappingURL=chunk-SKCMT2DE.js.map
|