lib-e2e-cypress-for-dummys-ts 0.5.0 → 0.6.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 +20 -0
- package/dist/index.cjs +214 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -2
- package/dist/index.d.ts +51 -2
- package/dist/index.js +207 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -361,6 +361,23 @@ Stopping a recording (save **or** discard) ends the session, so a finished recor
|
|
|
361
361
|
|
|
362
362
|
---
|
|
363
363
|
|
|
364
|
+
### Moving the widget (draggable)
|
|
365
|
+
|
|
366
|
+
If the floating widget covers a control you need, **drag the record button (⏺/⏹)**
|
|
367
|
+
to move the whole widget anywhere on screen. Press-and-move to drag; a plain click
|
|
368
|
+
still starts/stops recording (a ~5 px threshold tells the two apart).
|
|
369
|
+
|
|
370
|
+
The radial menu **expands toward the centre of the screen**, so the action buttons
|
|
371
|
+
stay fully visible wherever you drop it, and the position is **remembered** across
|
|
372
|
+
reloads (and app crossings). Reset it to the default corner from **⚙️ Config →
|
|
373
|
+
🧲 Widget position → Reset position**, or programmatically:
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
recorder.resetWidgetPosition();
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
364
381
|
### Keyboard shortcuts
|
|
365
382
|
|
|
366
383
|
| Shortcut | Action |
|
|
@@ -535,6 +552,9 @@ class LibE2eRecorderElement extends HTMLElement {
|
|
|
535
552
|
hasActiveSession(): boolean; // is a recording session persisted/active?
|
|
536
553
|
resumeSession(): void; // rehydrate the persisted session
|
|
537
554
|
discardSession(): void; // drop the persisted session
|
|
555
|
+
|
|
556
|
+
// Draggable widget
|
|
557
|
+
resetWidgetPosition(): void; // move the widget back to its default corner
|
|
538
558
|
}
|
|
539
559
|
```
|
|
540
560
|
|
package/dist/index.cjs
CHANGED
|
@@ -467,6 +467,7 @@ __export(index_exports, {
|
|
|
467
467
|
DB_SCHEMA: () => DB_SCHEMA,
|
|
468
468
|
DB_STORE_NAMES: () => DB_STORE_NAMES,
|
|
469
469
|
DEFAULT_RESUME_TTL_MINUTES: () => DEFAULT_RESUME_TTL_MINUTES,
|
|
470
|
+
DRAG_THRESHOLD: () => DRAG_THRESHOLD,
|
|
470
471
|
FilePreviewElement: () => FilePreviewElement,
|
|
471
472
|
HttpMonitor: () => HttpMonitor,
|
|
472
473
|
INPUT_TYPES: () => INPUT_TYPES,
|
|
@@ -481,12 +482,17 @@ __export(index_exports, {
|
|
|
481
482
|
SaveTestElement: () => SaveTestElement,
|
|
482
483
|
SelectorPickerElement: () => SelectorPickerElement,
|
|
483
484
|
Subject: () => Subject,
|
|
485
|
+
TOGGLE_MARGIN: () => TOGGLE_MARGIN,
|
|
484
486
|
TestEditorElement: () => TestEditorElement,
|
|
485
487
|
TestPrevisualizerElement: () => TestPrevisualizerElement,
|
|
486
488
|
TransformationService: () => TransformationService,
|
|
487
489
|
TranslationService: () => TranslationService,
|
|
488
490
|
VERSION: () => VERSION,
|
|
489
491
|
advancedTestTransformationService: () => advancedTestTransformationService,
|
|
492
|
+
boxOffsetForDirection: () => boxOffsetForDirection,
|
|
493
|
+
boxTopLeftFor: () => boxTopLeftFor,
|
|
494
|
+
clampTogglePosition: () => clampTogglePosition,
|
|
495
|
+
defaultTogglePosition: () => defaultTogglePosition,
|
|
490
496
|
generateAlias: () => generateAlias,
|
|
491
497
|
injectStyles: () => injectStyles,
|
|
492
498
|
isLang: () => isLang,
|
|
@@ -496,6 +502,7 @@ __export(index_exports, {
|
|
|
496
502
|
makeSwalDraggable: () => makeSwalDraggable,
|
|
497
503
|
makeSwalDraggableByContentId: () => makeSwalDraggableByContentId,
|
|
498
504
|
persistenceService: () => persistenceService,
|
|
505
|
+
resolveExpandDirection: () => resolveExpandDirection,
|
|
499
506
|
selectTestsForExport: () => selectTestsForExport,
|
|
500
507
|
setSwal2DataCyAttribute: () => setSwal2DataCyAttribute,
|
|
501
508
|
showToast: () => showToast,
|
|
@@ -703,7 +710,11 @@ var I18N_ES = {
|
|
|
703
710
|
START_HIDDEN_SUB: "El widget arranca invisible. Usa Ctrl+Shift+E para mostrarlo u ocultarlo.",
|
|
704
711
|
RESUME_TTL_SECTION: "\u23F1 Continuidad de grabaci\xF3n",
|
|
705
712
|
RESUME_TTL_LABEL: "Reanudar sin preguntar (minutos)",
|
|
706
|
-
RESUME_TTL_HINT: "Si recargas o cambias de proyecto, una grabaci\xF3n activa se reanuda sin preguntar dentro de este margen. Pasado ese tiempo, te preguntar\xE1 si continuar o descartar."
|
|
713
|
+
RESUME_TTL_HINT: "Si recargas o cambias de proyecto, una grabaci\xF3n activa se reanuda sin preguntar dentro de este margen. Pasado ese tiempo, te preguntar\xE1 si continuar o descartar.",
|
|
714
|
+
WIDGET_POSITION_SECTION: "\u{1F9F2} Posici\xF3n del widget",
|
|
715
|
+
WIDGET_POSITION_HINT: "Arrastra el bot\xF3n de grabar para moverlo donde no estorbe. Se recuerda su posici\xF3n.",
|
|
716
|
+
WIDGET_POSITION_RESET_BTN: "\u21BA Restablecer posici\xF3n",
|
|
717
|
+
WIDGET_POSITION_RESET_DONE: "\u2713 Posici\xF3n restablecida"
|
|
707
718
|
},
|
|
708
719
|
SELECTOR_PICKER: {
|
|
709
720
|
TITLE: "Selecciona un elemento del DOM",
|
|
@@ -899,7 +910,11 @@ var I18N_EN = {
|
|
|
899
910
|
START_HIDDEN_SUB: "The widget starts invisible. Use Ctrl+Shift+E to show or hide it.",
|
|
900
911
|
RESUME_TTL_SECTION: "\u23F1 Recording continuity",
|
|
901
912
|
RESUME_TTL_LABEL: "Resume without asking (minutes)",
|
|
902
|
-
RESUME_TTL_HINT: "If you reload or switch projects, an active recording resumes without asking within this window. After that, you will be asked to continue or discard."
|
|
913
|
+
RESUME_TTL_HINT: "If you reload or switch projects, an active recording resumes without asking within this window. After that, you will be asked to continue or discard.",
|
|
914
|
+
WIDGET_POSITION_SECTION: "\u{1F9F2} Widget position",
|
|
915
|
+
WIDGET_POSITION_HINT: "Drag the record button to move it out of the way. Its position is remembered.",
|
|
916
|
+
WIDGET_POSITION_RESET_BTN: "\u21BA Reset position",
|
|
917
|
+
WIDGET_POSITION_RESET_DONE: "\u2713 Position reset"
|
|
903
918
|
},
|
|
904
919
|
SELECTOR_PICKER: {
|
|
905
920
|
TITLE: "Select a DOM element",
|
|
@@ -1095,7 +1110,11 @@ var I18N_FR = {
|
|
|
1095
1110
|
START_HIDDEN_SUB: "Le widget d\xE9marre invisible. Utilisez Ctrl+Shift+E pour l'afficher ou le masquer.",
|
|
1096
1111
|
RESUME_TTL_SECTION: "\u23F1 Continuit\xE9 d'enregistrement",
|
|
1097
1112
|
RESUME_TTL_LABEL: "Reprendre sans demander (minutes)",
|
|
1098
|
-
RESUME_TTL_HINT: "Si vous rechargez ou changez de projet, un enregistrement actif reprend sans demander dans ce d\xE9lai. Au-del\xE0, il vous demandera de continuer ou d'ignorer."
|
|
1113
|
+
RESUME_TTL_HINT: "Si vous rechargez ou changez de projet, un enregistrement actif reprend sans demander dans ce d\xE9lai. Au-del\xE0, il vous demandera de continuer ou d'ignorer.",
|
|
1114
|
+
WIDGET_POSITION_SECTION: "\u{1F9F2} Position du widget",
|
|
1115
|
+
WIDGET_POSITION_HINT: "Fais glisser le bouton d'enregistrement pour le d\xE9placer. Sa position est m\xE9moris\xE9e.",
|
|
1116
|
+
WIDGET_POSITION_RESET_BTN: "\u21BA R\xE9initialiser la position",
|
|
1117
|
+
WIDGET_POSITION_RESET_DONE: "\u2713 Position r\xE9initialis\xE9e"
|
|
1099
1118
|
},
|
|
1100
1119
|
SELECTOR_PICKER: {
|
|
1101
1120
|
TITLE: "S\xE9lectionnez un \xE9l\xE9ment du DOM",
|
|
@@ -1291,7 +1310,11 @@ var I18N_IT = {
|
|
|
1291
1310
|
START_HIDDEN_SUB: "Il widget si avvia invisibile. Usa Ctrl+Shift+E per mostrarlo o nasconderlo.",
|
|
1292
1311
|
RESUME_TTL_SECTION: "\u23F1 Continuit\xE0 di registrazione",
|
|
1293
1312
|
RESUME_TTL_LABEL: "Riprendi senza chiedere (minuti)",
|
|
1294
|
-
RESUME_TTL_HINT: "Se ricarichi o cambi progetto, una registrazione attiva riprende senza chiedere entro questo intervallo. Trascorso, ti chieder\xE0 se continuare o annullare."
|
|
1313
|
+
RESUME_TTL_HINT: "Se ricarichi o cambi progetto, una registrazione attiva riprende senza chiedere entro questo intervallo. Trascorso, ti chieder\xE0 se continuare o annullare.",
|
|
1314
|
+
WIDGET_POSITION_SECTION: "\u{1F9F2} Posizione del widget",
|
|
1315
|
+
WIDGET_POSITION_HINT: "Trascina il pulsante di registrazione per spostarlo. La posizione viene ricordata.",
|
|
1316
|
+
WIDGET_POSITION_RESET_BTN: "\u21BA Reimposta posizione",
|
|
1317
|
+
WIDGET_POSITION_RESET_DONE: "\u2713 Posizione reimpostata"
|
|
1295
1318
|
},
|
|
1296
1319
|
SELECTOR_PICKER: {
|
|
1297
1320
|
TITLE: "Seleziona un elemento DOM",
|
|
@@ -1487,7 +1510,11 @@ var I18N_DE = {
|
|
|
1487
1510
|
START_HIDDEN_SUB: "Das Widget startet unsichtbar. Verwenden Sie Ctrl+Shift+E zum Ein-/Ausblenden.",
|
|
1488
1511
|
RESUME_TTL_SECTION: "\u23F1 Aufzeichnungskontinuit\xE4t",
|
|
1489
1512
|
RESUME_TTL_LABEL: "Ohne Nachfrage fortsetzen (Minuten)",
|
|
1490
|
-
RESUME_TTL_HINT: "Wenn Sie neu laden oder das Projekt wechseln, wird eine aktive Aufzeichnung innerhalb dieses Zeitfensters ohne Nachfrage fortgesetzt. Danach werden Sie gefragt, ob fortsetzen oder verwerfen."
|
|
1513
|
+
RESUME_TTL_HINT: "Wenn Sie neu laden oder das Projekt wechseln, wird eine aktive Aufzeichnung innerhalb dieses Zeitfensters ohne Nachfrage fortgesetzt. Danach werden Sie gefragt, ob fortsetzen oder verwerfen.",
|
|
1514
|
+
WIDGET_POSITION_SECTION: "\u{1F9F2} Widget-Position",
|
|
1515
|
+
WIDGET_POSITION_HINT: "Ziehe den Aufnahme-Button, um ihn aus dem Weg zu schieben. Die Position wird gespeichert.",
|
|
1516
|
+
WIDGET_POSITION_RESET_BTN: "\u21BA Position zur\xFCcksetzen",
|
|
1517
|
+
WIDGET_POSITION_RESET_DONE: "\u2713 Position zur\xFCckgesetzt"
|
|
1491
1518
|
},
|
|
1492
1519
|
SELECTOR_PICKER: {
|
|
1493
1520
|
TITLE: "DOM-Element ausw\xE4hlen",
|
|
@@ -2758,6 +2785,37 @@ function isLocalHost(hostname) {
|
|
|
2758
2785
|
return h === "localhost" || h.endsWith(".localhost") || h === "127.0.0.1" || h === "::1" || h === "0.0.0.0";
|
|
2759
2786
|
}
|
|
2760
2787
|
|
|
2788
|
+
// src/utils/widget-position.utils.ts
|
|
2789
|
+
var TOGGLE_MARGIN = 30;
|
|
2790
|
+
var DRAG_THRESHOLD = 5;
|
|
2791
|
+
var DEFAULT_EDGE_OFFSET = 46;
|
|
2792
|
+
function boxOffsetForDirection(dir) {
|
|
2793
|
+
return {
|
|
2794
|
+
x: dir.endsWith("left") ? 144 : 46,
|
|
2795
|
+
y: dir.startsWith("up") ? 144 : 46
|
|
2796
|
+
};
|
|
2797
|
+
}
|
|
2798
|
+
function clampTogglePosition(x, y, vw, vh, margin = TOGGLE_MARGIN) {
|
|
2799
|
+
const maxX = Math.max(margin, vw - margin);
|
|
2800
|
+
const maxY = Math.max(margin, vh - margin);
|
|
2801
|
+
return {
|
|
2802
|
+
x: Math.min(Math.max(x, margin), maxX),
|
|
2803
|
+
y: Math.min(Math.max(y, margin), maxY)
|
|
2804
|
+
};
|
|
2805
|
+
}
|
|
2806
|
+
function resolveExpandDirection(x, y, vw, vh) {
|
|
2807
|
+
const vertical = y < vh / 2 ? "down" : "up";
|
|
2808
|
+
const horizontal = x < vw / 2 ? "right" : "left";
|
|
2809
|
+
return `${vertical}-${horizontal}`;
|
|
2810
|
+
}
|
|
2811
|
+
function defaultTogglePosition(vw, vh) {
|
|
2812
|
+
return { x: vw - DEFAULT_EDGE_OFFSET, y: vh - DEFAULT_EDGE_OFFSET };
|
|
2813
|
+
}
|
|
2814
|
+
function boxTopLeftFor(toggleCentre, dir) {
|
|
2815
|
+
const off = boxOffsetForDirection(dir);
|
|
2816
|
+
return { x: toggleCentre.x - off.x, y: toggleCentre.y - off.y };
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2761
2819
|
// src/index.ts
|
|
2762
2820
|
init_selector_picker();
|
|
2763
2821
|
|
|
@@ -3868,6 +3926,15 @@ function renderConfiguration(state, t) {
|
|
|
3868
3926
|
</label>
|
|
3869
3927
|
</div>
|
|
3870
3928
|
|
|
3929
|
+
<!-- Widget position (draggable widget) -->
|
|
3930
|
+
<div class="card">
|
|
3931
|
+
<div class="card-hd">${t("CONFIG.WIDGET_POSITION_SECTION")}</div>
|
|
3932
|
+
<div class="check-sub" style="margin-bottom:10px">${t("CONFIG.WIDGET_POSITION_HINT")}</div>
|
|
3933
|
+
<div class="btn-row">
|
|
3934
|
+
<button id="btn-reset-position">${t("CONFIG.WIDGET_POSITION_RESET_BTN")}</button>
|
|
3935
|
+
</div>
|
|
3936
|
+
</div>
|
|
3937
|
+
|
|
3871
3938
|
<!-- Recording continuity (cross-app resume TTL) -->
|
|
3872
3939
|
<div class="card">
|
|
3873
3940
|
<div class="card-hd">${t("CONFIG.RESUME_TTL_SECTION")}</div>
|
|
@@ -4008,6 +4075,10 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
4008
4075
|
await this.persistence.setConfig({ [RESUME_TTL_CONFIG_KEY]: safe });
|
|
4009
4076
|
this.render();
|
|
4010
4077
|
}
|
|
4078
|
+
onResetWidgetPosition() {
|
|
4079
|
+
this.dispatchEvent(new CustomEvent("resetwidgetposition", { bubbles: true, composed: true }));
|
|
4080
|
+
showToast(this.t("CONFIG.WIDGET_POSITION_RESET_DONE"));
|
|
4081
|
+
}
|
|
4011
4082
|
async onSmartSelectorChange(enabled) {
|
|
4012
4083
|
this.smartSelectorEnabled = enabled;
|
|
4013
4084
|
await this.persistence.setConfig({ smartSelectorEnabled: enabled ? "true" : "false" });
|
|
@@ -4143,6 +4214,7 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
4143
4214
|
"change",
|
|
4144
4215
|
(e) => this.onResumeTtlChange(Number(e.target.value))
|
|
4145
4216
|
);
|
|
4217
|
+
this.shadow.getElementById("btn-reset-position")?.addEventListener("click", () => this.onResetWidgetPosition());
|
|
4146
4218
|
this.shadow.getElementById("selector-strategy").addEventListener(
|
|
4147
4219
|
"change",
|
|
4148
4220
|
(e) => this.onSelectorStrategyChange(e.target.value)
|
|
@@ -5107,15 +5179,37 @@ if (!customElements.get("file-preview")) {
|
|
|
5107
5179
|
var import_sweetalert2 = __toESM(require("sweetalert2"), 1);
|
|
5108
5180
|
|
|
5109
5181
|
// src/components/lib-e2e-recorder/lib-e2e-recorder.styles.ts
|
|
5182
|
+
var DIRECTIONS = ["up-left", "up-right", "down-left", "down-right"];
|
|
5183
|
+
function directionBlocks() {
|
|
5184
|
+
return DIRECTIONS.map((dir) => {
|
|
5185
|
+
const sx = dir.endsWith("left") ? -1 : 1;
|
|
5186
|
+
const sy = dir.startsWith("up") ? -1 : 1;
|
|
5187
|
+
const tv = dir.startsWith("up") ? "bottom" : "top";
|
|
5188
|
+
const th = dir.endsWith("left") ? "right" : "left";
|
|
5189
|
+
const ov = tv === "bottom" ? "top" : "bottom";
|
|
5190
|
+
const oh = th === "right" ? "left" : "right";
|
|
5191
|
+
const sel = `.widget[data-expand="${dir}"]`;
|
|
5192
|
+
const labelGeneral = `${sel} .btn-action::after { ${oh}: calc(100% + 9px); ${th}: auto; top: 50%; bottom: auto; transform: translateY(-50%); }`;
|
|
5193
|
+
const labelEnds = `${sel} .btn-action[data-n="1"]::after, ${sel} .btn-action[data-n="4"]::after { ${ov}: calc(100% + 9px); ${tv}: auto; left: 50%; right: auto; transform: translateX(-50%); }`;
|
|
5194
|
+
return `
|
|
5195
|
+
${sel} { --sx: ${sx}; --sy: ${sy}; }
|
|
5196
|
+
${sel} .btn-toggle { ${tv}: 24px; ${th}: 24px; ${ov}: auto; ${oh}: auto; }
|
|
5197
|
+
${sel} .btn-pause { ${tv}: 78px; ${th}: 24px; ${ov}: auto; ${oh}: auto; }
|
|
5198
|
+
${sel} .btn-action { ${tv}: 28px; ${th}: 28px; ${ov}: auto; ${oh}: auto; }
|
|
5199
|
+
${labelGeneral}
|
|
5200
|
+
${labelEnds}
|
|
5201
|
+
`;
|
|
5202
|
+
}).join("\n");
|
|
5203
|
+
}
|
|
5110
5204
|
function getRecorderStyles(rec, paused) {
|
|
5111
5205
|
return `
|
|
5112
5206
|
:host { all: initial; }
|
|
5113
5207
|
*, *::before, *::after { box-sizing: border-box; }
|
|
5114
5208
|
|
|
5115
5209
|
/*
|
|
5116
|
-
* Invisible 190\xD7190 hit area
|
|
5117
|
-
*
|
|
5118
|
-
*
|
|
5210
|
+
* Invisible 190\xD7190 hit area. Position (left/top) is set from JS so the
|
|
5211
|
+
* widget can be dragged; --sx/--sy + data-expand orient the radial menu so
|
|
5212
|
+
* it always expands toward the viewport interior. Defaults to bottom-right.
|
|
5119
5213
|
*/
|
|
5120
5214
|
.widget {
|
|
5121
5215
|
position: fixed;
|
|
@@ -5124,6 +5218,8 @@ function getRecorderStyles(rec, paused) {
|
|
|
5124
5218
|
width: 190px;
|
|
5125
5219
|
height: 190px;
|
|
5126
5220
|
z-index: 2147483647;
|
|
5221
|
+
--sx: -1;
|
|
5222
|
+
--sy: -1;
|
|
5127
5223
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
5128
5224
|
}
|
|
5129
5225
|
|
|
@@ -5136,7 +5232,8 @@ function getRecorderStyles(rec, paused) {
|
|
|
5136
5232
|
height: 44px;
|
|
5137
5233
|
border-radius: 50%;
|
|
5138
5234
|
border: none;
|
|
5139
|
-
cursor:
|
|
5235
|
+
cursor: grab;
|
|
5236
|
+
touch-action: none;
|
|
5140
5237
|
font-size: 19px;
|
|
5141
5238
|
background: ${rec ? "linear-gradient(135deg,#f85149 0%,#da3633 100%)" : "linear-gradient(135deg,#2f81f7 0%,#1f6feb 100%)"};
|
|
5142
5239
|
color: #fff;
|
|
@@ -5149,7 +5246,7 @@ function getRecorderStyles(rec, paused) {
|
|
|
5149
5246
|
${rec ? "animation: toggle-pulse 2s ease-in-out infinite;" : ""}
|
|
5150
5247
|
}
|
|
5151
5248
|
.btn-toggle:hover { transform: scale(1.1); }
|
|
5152
|
-
.btn-toggle:active { transform: scale(0.93); }
|
|
5249
|
+
.btn-toggle:active { transform: scale(0.93); cursor: grabbing; }
|
|
5153
5250
|
|
|
5154
5251
|
@keyframes toggle-pulse {
|
|
5155
5252
|
0%,100% { box-shadow: 0 4px 20px rgba(248,81,73,.55),0 0 0 4px rgba(248,81,73,.13); }
|
|
@@ -5180,11 +5277,6 @@ function getRecorderStyles(rec, paused) {
|
|
|
5180
5277
|
.btn-pause:active { transform: scale(0.93); }
|
|
5181
5278
|
|
|
5182
5279
|
/* \u2500\u2500 Action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
5183
|
-
/*
|
|
5184
|
-
* All three start centered on the toggle button
|
|
5185
|
-
* (toggle center = bottom:46px right:46px from widget edge;
|
|
5186
|
-
* button half = 18px \u2192 bottom:28px right:28px).
|
|
5187
|
-
*/
|
|
5188
5280
|
.btn-action {
|
|
5189
5281
|
position: absolute;
|
|
5190
5282
|
bottom: 28px;
|
|
@@ -5206,12 +5298,11 @@ function getRecorderStyles(rec, paused) {
|
|
|
5206
5298
|
opacity: 0;
|
|
5207
5299
|
transform: scale(0.35);
|
|
5208
5300
|
pointer-events: none;
|
|
5209
|
-
/* Collapse: fast, no spring */
|
|
5210
5301
|
transition: opacity .15s, transform .18s ease-in,
|
|
5211
5302
|
background .15s, color .12s, box-shadow .15s;
|
|
5212
5303
|
}
|
|
5213
5304
|
|
|
5214
|
-
/* Label
|
|
5305
|
+
/* Label chip */
|
|
5215
5306
|
.btn-action::after {
|
|
5216
5307
|
content: attr(data-label);
|
|
5217
5308
|
position: absolute;
|
|
@@ -5231,14 +5322,6 @@ function getRecorderStyles(rec, paused) {
|
|
|
5231
5322
|
border: 1px solid rgba(48,54,61,.8);
|
|
5232
5323
|
box-shadow: 0 2px 8px rgba(0,0,0,.35);
|
|
5233
5324
|
}
|
|
5234
|
-
/* Button 1 (top) \u2014 label above instead of left to avoid overlap with btn 2 */
|
|
5235
|
-
.btn-action[data-n="1"]::after {
|
|
5236
|
-
right: auto;
|
|
5237
|
-
left: 50%;
|
|
5238
|
-
top: auto;
|
|
5239
|
-
bottom: calc(100% + 9px);
|
|
5240
|
-
transform: translateX(-50%);
|
|
5241
|
-
}
|
|
5242
5325
|
.btn-action:hover::after { opacity: 1; }
|
|
5243
5326
|
.btn-action:hover { background: #21262d; color: #e6edf3; }
|
|
5244
5327
|
.btn-action:active { background: #30363d !important; }
|
|
@@ -5251,31 +5334,26 @@ function getRecorderStyles(rec, paused) {
|
|
|
5251
5334
|
background .15s, color .12s, box-shadow .15s;
|
|
5252
5335
|
}
|
|
5253
5336
|
|
|
5254
|
-
/* Arc positions \u2014
|
|
5255
|
-
.widget:hover .btn-action[data-n="1"] { /*
|
|
5256
|
-
transform: translateY(
|
|
5337
|
+
/* Arc positions \u2014 signs come from --sx/--sy (data-expand) */
|
|
5338
|
+
.widget:hover .btn-action[data-n="1"] { /* vertical extreme */
|
|
5339
|
+
transform: translateY(calc(var(--sy) * 90px)) scale(1);
|
|
5257
5340
|
transition-delay: .03s;
|
|
5258
5341
|
}
|
|
5259
|
-
.widget:hover .btn-action[data-n="2"] { /*
|
|
5260
|
-
transform: translate(
|
|
5342
|
+
.widget:hover .btn-action[data-n="2"] { /* diagonal near-vertical */
|
|
5343
|
+
transform: translate(calc(var(--sx) * 45px), calc(var(--sy) * 78px)) scale(1);
|
|
5261
5344
|
transition-delay: .07s;
|
|
5262
5345
|
}
|
|
5263
|
-
.widget:hover .btn-action[data-n="3"] { /*
|
|
5264
|
-
transform: translate(
|
|
5346
|
+
.widget:hover .btn-action[data-n="3"] { /* diagonal near-horizontal */
|
|
5347
|
+
transform: translate(calc(var(--sx) * 78px), calc(var(--sy) * 45px)) scale(1);
|
|
5265
5348
|
transition-delay: .11s;
|
|
5266
5349
|
}
|
|
5267
|
-
.widget:hover .btn-action[data-n="4"] { /*
|
|
5268
|
-
transform: translateX(
|
|
5350
|
+
.widget:hover .btn-action[data-n="4"] { /* horizontal extreme */
|
|
5351
|
+
transform: translateX(calc(var(--sx) * 90px)) scale(1);
|
|
5269
5352
|
transition-delay: .15s;
|
|
5270
5353
|
}
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
left: 50%;
|
|
5275
|
-
top: auto;
|
|
5276
|
-
bottom: calc(100% + 9px);
|
|
5277
|
-
transform: translateX(-50%);
|
|
5278
|
-
}
|
|
5354
|
+
|
|
5355
|
+
/* Per-direction anchors + label sides */
|
|
5356
|
+
${directionBlocks()}
|
|
5279
5357
|
|
|
5280
5358
|
/* \u2500\u2500 REC / PAUSED badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
5281
5359
|
.rec-badge {
|
|
@@ -5342,6 +5420,14 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
5342
5420
|
sessionUnsub;
|
|
5343
5421
|
sessionSaveTimer;
|
|
5344
5422
|
controlFirstTimeData = true;
|
|
5423
|
+
// ── draggable widget (spec 007) ──
|
|
5424
|
+
togglePos = null;
|
|
5425
|
+
expandDir = "up-left";
|
|
5426
|
+
dragState;
|
|
5427
|
+
suppressNextToggleClick = false;
|
|
5428
|
+
widgetPointerMove;
|
|
5429
|
+
widgetPointerUp;
|
|
5430
|
+
widgetResize;
|
|
5345
5431
|
_previsualizerRef = null;
|
|
5346
5432
|
httpMonitor;
|
|
5347
5433
|
smartSelectorEnabled = true;
|
|
@@ -5385,8 +5471,15 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
5385
5471
|
this.render();
|
|
5386
5472
|
this.initVisibility();
|
|
5387
5473
|
this.initSessionContinuity();
|
|
5474
|
+
this.initWidgetPosition();
|
|
5388
5475
|
this.keydownHandler = (e) => this.handleKeyboardEvent(e);
|
|
5389
5476
|
window.addEventListener("keydown", this.keydownHandler);
|
|
5477
|
+
this.widgetPointerMove = (e) => this.onWidgetPointerMove(e);
|
|
5478
|
+
this.widgetPointerUp = () => this.onWidgetPointerUp();
|
|
5479
|
+
this.widgetResize = () => this.applyWidgetPosition();
|
|
5480
|
+
window.addEventListener("pointermove", this.widgetPointerMove);
|
|
5481
|
+
window.addEventListener("pointerup", this.widgetPointerUp);
|
|
5482
|
+
window.addEventListener("resize", this.widgetResize);
|
|
5390
5483
|
}
|
|
5391
5484
|
disconnectedCallback() {
|
|
5392
5485
|
if (this._isDisabled) return;
|
|
@@ -5399,6 +5492,9 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
5399
5492
|
this.selectorNotFoundUnsub?.();
|
|
5400
5493
|
this.langUnsub?.();
|
|
5401
5494
|
this.sessionUnsub?.();
|
|
5495
|
+
if (this.widgetPointerMove) window.removeEventListener("pointermove", this.widgetPointerMove);
|
|
5496
|
+
if (this.widgetPointerUp) window.removeEventListener("pointerup", this.widgetPointerUp);
|
|
5497
|
+
if (this.widgetResize) window.removeEventListener("resize", this.widgetResize);
|
|
5402
5498
|
this.httpMonitor?.uninstall();
|
|
5403
5499
|
this.recording.destroy();
|
|
5404
5500
|
}
|
|
@@ -5585,6 +5681,63 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
5585
5681
|
discardSession() {
|
|
5586
5682
|
this.clearSessionPersistence();
|
|
5587
5683
|
}
|
|
5684
|
+
// ── draggable widget (spec 007) ────────────────────────────────────────────
|
|
5685
|
+
/** Loads a previously saved widget position and applies it. */
|
|
5686
|
+
async initWidgetPosition() {
|
|
5687
|
+
const config = await this.persistence.getGeneralConfig();
|
|
5688
|
+
const pos = config?.["widgetPosition"];
|
|
5689
|
+
if (pos && typeof pos.x === "number" && typeof pos.y === "number") {
|
|
5690
|
+
this.togglePos = { x: pos.x, y: pos.y };
|
|
5691
|
+
}
|
|
5692
|
+
this.applyWidgetPosition();
|
|
5693
|
+
}
|
|
5694
|
+
/** Positions the `.widget` box from the (clamped) toggle centre and orients the arc. */
|
|
5695
|
+
applyWidgetPosition() {
|
|
5696
|
+
const widget = this.shadow.querySelector(".widget");
|
|
5697
|
+
if (!widget) return;
|
|
5698
|
+
const vw = window.innerWidth;
|
|
5699
|
+
const vh = window.innerHeight;
|
|
5700
|
+
const centre = this.togglePos ?? defaultTogglePosition(vw, vh);
|
|
5701
|
+
const clamped = clampTogglePosition(centre.x, centre.y, vw, vh);
|
|
5702
|
+
this.expandDir = resolveExpandDirection(clamped.x, clamped.y, vw, vh);
|
|
5703
|
+
const topLeft = boxTopLeftFor(clamped, this.expandDir);
|
|
5704
|
+
widget.style.left = `${topLeft.x}px`;
|
|
5705
|
+
widget.style.top = `${topLeft.y}px`;
|
|
5706
|
+
widget.style.right = "auto";
|
|
5707
|
+
widget.style.bottom = "auto";
|
|
5708
|
+
widget.setAttribute("data-expand", this.expandDir);
|
|
5709
|
+
}
|
|
5710
|
+
beginWidgetDrag(e) {
|
|
5711
|
+
const origin = this.togglePos ?? defaultTogglePosition(window.innerWidth, window.innerHeight);
|
|
5712
|
+
this.dragState = { startX: e.clientX, startY: e.clientY, origX: origin.x, origY: origin.y, moved: false };
|
|
5713
|
+
}
|
|
5714
|
+
onWidgetPointerMove(e) {
|
|
5715
|
+
if (!this.dragState) return;
|
|
5716
|
+
const dx = e.clientX - this.dragState.startX;
|
|
5717
|
+
const dy = e.clientY - this.dragState.startY;
|
|
5718
|
+
if (!this.dragState.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
5719
|
+
this.dragState.moved = true;
|
|
5720
|
+
this.togglePos = { x: this.dragState.origX + dx, y: this.dragState.origY + dy };
|
|
5721
|
+
this.applyWidgetPosition();
|
|
5722
|
+
}
|
|
5723
|
+
onWidgetPointerUp() {
|
|
5724
|
+
if (!this.dragState) return;
|
|
5725
|
+
const moved = this.dragState.moved;
|
|
5726
|
+
this.dragState = void 0;
|
|
5727
|
+
if (!moved || !this.togglePos) return;
|
|
5728
|
+
this.suppressNextToggleClick = true;
|
|
5729
|
+
const clamped = clampTogglePosition(this.togglePos.x, this.togglePos.y, window.innerWidth, window.innerHeight);
|
|
5730
|
+
this.togglePos = clamped;
|
|
5731
|
+
this.persistence.setConfig({ widgetPosition: clamped }).catch(() => {
|
|
5732
|
+
});
|
|
5733
|
+
}
|
|
5734
|
+
/** Resets the widget to its default corner and clears the saved position. */
|
|
5735
|
+
resetWidgetPosition() {
|
|
5736
|
+
this.togglePos = null;
|
|
5737
|
+
this.persistence.setConfig({ widgetPosition: null }).catch(() => {
|
|
5738
|
+
});
|
|
5739
|
+
this.applyWidgetPosition();
|
|
5740
|
+
}
|
|
5588
5741
|
toggle() {
|
|
5589
5742
|
this.recording.toggleRecording();
|
|
5590
5743
|
}
|
|
@@ -5901,6 +6054,7 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
5901
6054
|
this.isVisible = !e.detail;
|
|
5902
6055
|
this.style.display = this.isVisible ? "" : "none";
|
|
5903
6056
|
});
|
|
6057
|
+
child.addEventListener("resetwidgetposition", () => this.resetWidgetPosition());
|
|
5904
6058
|
},
|
|
5905
6059
|
willClose: () => {
|
|
5906
6060
|
this.isSettingsDialogOpen = false;
|
|
@@ -6054,12 +6208,21 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
6054
6208
|
const paused = this.isPaused;
|
|
6055
6209
|
this.style.display = this.isVisible ? "" : "none";
|
|
6056
6210
|
this.shadow.innerHTML = `<style>${getRecorderStyles(rec, paused)}</style>${renderRecorderWidget(rec, paused, this.translation.translate.bind(this.translation))}`;
|
|
6057
|
-
this.shadow.querySelector('[data-action="toggle"]')
|
|
6211
|
+
const toggleBtn = this.shadow.querySelector('[data-action="toggle"]');
|
|
6212
|
+
toggleBtn?.addEventListener("click", () => {
|
|
6213
|
+
if (this.suppressNextToggleClick) {
|
|
6214
|
+
this.suppressNextToggleClick = false;
|
|
6215
|
+
return;
|
|
6216
|
+
}
|
|
6217
|
+
this.toggle();
|
|
6218
|
+
});
|
|
6219
|
+
toggleBtn?.addEventListener("pointerdown", (e) => this.beginWidgetDrag(e));
|
|
6058
6220
|
this.shadow.querySelector('[data-action="pause"]')?.addEventListener("click", () => this.togglePause());
|
|
6059
6221
|
this.shadow.querySelector('[data-action="tests"]')?.addEventListener("click", () => this.showSavedTestsDialog());
|
|
6060
6222
|
this.shadow.querySelector('[data-action="commands"]')?.addEventListener("click", () => this.showCommandsDialog());
|
|
6061
6223
|
this.shadow.querySelector('[data-action="config"]')?.addEventListener("click", () => this.showSettingsDialog());
|
|
6062
6224
|
this.shadow.querySelector('[data-action="browse"]')?.addEventListener("click", () => this.showAdvancedEditorDialog());
|
|
6225
|
+
this.applyWidgetPosition();
|
|
6063
6226
|
}
|
|
6064
6227
|
};
|
|
6065
6228
|
if (!customElements.get("lib-e2e-recorder")) {
|
|
@@ -6067,7 +6230,7 @@ if (!customElements.get("lib-e2e-recorder")) {
|
|
|
6067
6230
|
}
|
|
6068
6231
|
|
|
6069
6232
|
// src/index.ts
|
|
6070
|
-
var VERSION = "0.
|
|
6233
|
+
var VERSION = "0.6.0";
|
|
6071
6234
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6072
6235
|
0 && (module.exports = {
|
|
6073
6236
|
ACTIVE_SESSION_BREADCRUMB_KEY,
|
|
@@ -6077,6 +6240,7 @@ var VERSION = "0.5.0";
|
|
|
6077
6240
|
DB_SCHEMA,
|
|
6078
6241
|
DB_STORE_NAMES,
|
|
6079
6242
|
DEFAULT_RESUME_TTL_MINUTES,
|
|
6243
|
+
DRAG_THRESHOLD,
|
|
6080
6244
|
FilePreviewElement,
|
|
6081
6245
|
HttpMonitor,
|
|
6082
6246
|
INPUT_TYPES,
|
|
@@ -6091,12 +6255,17 @@ var VERSION = "0.5.0";
|
|
|
6091
6255
|
SaveTestElement,
|
|
6092
6256
|
SelectorPickerElement,
|
|
6093
6257
|
Subject,
|
|
6258
|
+
TOGGLE_MARGIN,
|
|
6094
6259
|
TestEditorElement,
|
|
6095
6260
|
TestPrevisualizerElement,
|
|
6096
6261
|
TransformationService,
|
|
6097
6262
|
TranslationService,
|
|
6098
6263
|
VERSION,
|
|
6099
6264
|
advancedTestTransformationService,
|
|
6265
|
+
boxOffsetForDirection,
|
|
6266
|
+
boxTopLeftFor,
|
|
6267
|
+
clampTogglePosition,
|
|
6268
|
+
defaultTogglePosition,
|
|
6100
6269
|
generateAlias,
|
|
6101
6270
|
injectStyles,
|
|
6102
6271
|
isLang,
|
|
@@ -6106,6 +6275,7 @@ var VERSION = "0.5.0";
|
|
|
6106
6275
|
makeSwalDraggable,
|
|
6107
6276
|
makeSwalDraggableByContentId,
|
|
6108
6277
|
persistenceService,
|
|
6278
|
+
resolveExpandDirection,
|
|
6109
6279
|
selectTestsForExport,
|
|
6110
6280
|
setSwal2DataCyAttribute,
|
|
6111
6281
|
showToast,
|