alabit-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/foundations/tokens/tokens.css +214 -0
- package/dist/index.cjs +30164 -0
- package/dist/index.d.cts +2384 -0
- package/dist/index.d.ts +2384 -0
- package/dist/index.js +29654 -0
- package/dist/server.cjs +649 -0
- package/dist/server.js +622 -0
- package/package.json +65 -0
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __spreadValues = (a, b) => {
|
|
12
|
+
for (var prop in b || (b = {}))
|
|
13
|
+
if (__hasOwnProp.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
if (__getOwnPropSymbols)
|
|
16
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
+
if (__propIsEnum.call(b, prop))
|
|
18
|
+
__defNormalProp(a, prop, b[prop]);
|
|
19
|
+
}
|
|
20
|
+
return a;
|
|
21
|
+
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
var __export = (target, all) => {
|
|
24
|
+
for (var name in all)
|
|
25
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
|
+
};
|
|
27
|
+
var __copyProps = (to, from, except, desc) => {
|
|
28
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
29
|
+
for (let key of __getOwnPropNames(from))
|
|
30
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
31
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
32
|
+
}
|
|
33
|
+
return to;
|
|
34
|
+
};
|
|
35
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
|
+
|
|
37
|
+
// src/server.ts
|
|
38
|
+
var server_exports = {};
|
|
39
|
+
__export(server_exports, {
|
|
40
|
+
createResponsiveSession: () => createResponsiveSession,
|
|
41
|
+
deleteResponsiveSession: () => deleteResponsiveSession,
|
|
42
|
+
getResponsiveSession: () => getResponsiveSession,
|
|
43
|
+
performResponsiveAction: () => performResponsiveAction
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(server_exports);
|
|
46
|
+
|
|
47
|
+
// src/lib/responsive/server.ts
|
|
48
|
+
var import_node_crypto = require("crypto");
|
|
49
|
+
var import_promises = require("fs/promises");
|
|
50
|
+
var import_node_fs = require("fs");
|
|
51
|
+
var import_playwright_core = require("playwright-core");
|
|
52
|
+
|
|
53
|
+
// src/lib/responsive/shared.ts
|
|
54
|
+
var DEVICE_PRESETS = [
|
|
55
|
+
{
|
|
56
|
+
id: "mobile-sm",
|
|
57
|
+
name: "Mobile S",
|
|
58
|
+
width: 360,
|
|
59
|
+
height: 780,
|
|
60
|
+
kind: "phone",
|
|
61
|
+
category: "phone",
|
|
62
|
+
brand: "generic",
|
|
63
|
+
line: "generic-smartphone",
|
|
64
|
+
tags: ["sm", "360", "small"]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "iphone-12-pro",
|
|
68
|
+
name: "iPhone 12 Pro",
|
|
69
|
+
width: 390,
|
|
70
|
+
height: 844,
|
|
71
|
+
kind: "phone",
|
|
72
|
+
category: "phone",
|
|
73
|
+
brand: "apple",
|
|
74
|
+
line: "iphone",
|
|
75
|
+
tags: ["apple", "ios", "390"]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "mobile-lg",
|
|
79
|
+
name: "Mobile L",
|
|
80
|
+
width: 640,
|
|
81
|
+
height: 960,
|
|
82
|
+
kind: "phone",
|
|
83
|
+
category: "phone",
|
|
84
|
+
brand: "generic",
|
|
85
|
+
line: "generic-smartphone",
|
|
86
|
+
tags: ["lg", "640", "large"]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: "ipad-mini",
|
|
90
|
+
name: "iPad Mini",
|
|
91
|
+
width: 744,
|
|
92
|
+
height: 1133,
|
|
93
|
+
kind: "tablet",
|
|
94
|
+
category: "tablet",
|
|
95
|
+
brand: "apple",
|
|
96
|
+
line: "ipad",
|
|
97
|
+
tags: ["apple", "ipad", "mini"]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "ipad",
|
|
101
|
+
name: "iPad",
|
|
102
|
+
width: 768,
|
|
103
|
+
height: 1024,
|
|
104
|
+
kind: "tablet",
|
|
105
|
+
category: "tablet",
|
|
106
|
+
brand: "apple",
|
|
107
|
+
line: "ipad",
|
|
108
|
+
tags: ["apple", "ipad", "768"]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "ipad-air",
|
|
112
|
+
name: "iPad Air",
|
|
113
|
+
width: 820,
|
|
114
|
+
height: 1180,
|
|
115
|
+
kind: "tablet",
|
|
116
|
+
category: "tablet",
|
|
117
|
+
brand: "apple",
|
|
118
|
+
line: "ipad",
|
|
119
|
+
tags: ["apple", "ipad", "air"]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "ipad-pro-11",
|
|
123
|
+
name: 'iPad Pro 11"',
|
|
124
|
+
width: 834,
|
|
125
|
+
height: 1194,
|
|
126
|
+
kind: "tablet",
|
|
127
|
+
category: "tablet",
|
|
128
|
+
brand: "apple",
|
|
129
|
+
line: "ipad",
|
|
130
|
+
tags: ["apple", "ipad", "pro", "11"]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "ipad-pro-12-9",
|
|
134
|
+
name: 'iPad Pro 12.9"',
|
|
135
|
+
width: 1024,
|
|
136
|
+
height: 1366,
|
|
137
|
+
kind: "tablet",
|
|
138
|
+
category: "tablet",
|
|
139
|
+
brand: "apple",
|
|
140
|
+
line: "ipad",
|
|
141
|
+
tags: ["apple", "ipad", "pro", "12"]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: "galaxy-tab-s9",
|
|
145
|
+
name: "Galaxy Tab S9",
|
|
146
|
+
width: 847,
|
|
147
|
+
height: 1210,
|
|
148
|
+
kind: "tablet",
|
|
149
|
+
category: "tablet",
|
|
150
|
+
brand: "samsung",
|
|
151
|
+
line: "galaxy-tab",
|
|
152
|
+
tags: ["samsung", "android", "galaxy-tab"]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: "tablet-generic",
|
|
156
|
+
name: "Tablet Gen\xE9rica",
|
|
157
|
+
width: 800,
|
|
158
|
+
height: 1280,
|
|
159
|
+
kind: "tablet",
|
|
160
|
+
category: "tablet",
|
|
161
|
+
brand: "generic",
|
|
162
|
+
line: "generic-tablet",
|
|
163
|
+
tags: ["generic", "android"]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "laptop",
|
|
167
|
+
name: "Laptop",
|
|
168
|
+
width: 1024,
|
|
169
|
+
height: 768,
|
|
170
|
+
kind: "desktop",
|
|
171
|
+
category: "laptop",
|
|
172
|
+
brand: "generic",
|
|
173
|
+
line: "generic-laptop",
|
|
174
|
+
tags: ["1024", "lg-screen"]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: "macbook-air-13",
|
|
178
|
+
name: 'MacBook Air 13"',
|
|
179
|
+
width: 1280,
|
|
180
|
+
height: 832,
|
|
181
|
+
kind: "desktop",
|
|
182
|
+
category: "laptop",
|
|
183
|
+
brand: "apple",
|
|
184
|
+
line: "macbook",
|
|
185
|
+
tags: ["apple", "mac", "macbook", "air", "13"]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "macbook-pro-14",
|
|
189
|
+
name: 'MacBook Pro 14"',
|
|
190
|
+
width: 1512,
|
|
191
|
+
height: 982,
|
|
192
|
+
kind: "desktop",
|
|
193
|
+
category: "laptop",
|
|
194
|
+
brand: "apple",
|
|
195
|
+
line: "macbook",
|
|
196
|
+
tags: ["apple", "mac", "macbook", "pro", "14"]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: "macbook-pro-16",
|
|
200
|
+
name: 'MacBook Pro 16"',
|
|
201
|
+
width: 1728,
|
|
202
|
+
height: 1117,
|
|
203
|
+
kind: "desktop",
|
|
204
|
+
category: "laptop",
|
|
205
|
+
brand: "apple",
|
|
206
|
+
line: "macbook",
|
|
207
|
+
tags: ["apple", "mac", "macbook", "pro", "16"]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: "desktop",
|
|
211
|
+
name: "Desktop",
|
|
212
|
+
width: 1280,
|
|
213
|
+
height: 800,
|
|
214
|
+
kind: "desktop",
|
|
215
|
+
category: "desktop",
|
|
216
|
+
brand: "monitor",
|
|
217
|
+
line: "generic-desktop",
|
|
218
|
+
tags: ["1280", "hd", "screen"]
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "imac-24",
|
|
222
|
+
name: 'iMac 24"',
|
|
223
|
+
width: 2240,
|
|
224
|
+
height: 1260,
|
|
225
|
+
kind: "desktop",
|
|
226
|
+
category: "aio",
|
|
227
|
+
brand: "apple",
|
|
228
|
+
line: "imac",
|
|
229
|
+
tags: ["apple", "mac", "imac", "24", "screen"]
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: "desktop-xl",
|
|
233
|
+
name: "Desktop XL",
|
|
234
|
+
width: 1536,
|
|
235
|
+
height: 960,
|
|
236
|
+
kind: "desktop",
|
|
237
|
+
category: "desktop",
|
|
238
|
+
brand: "monitor",
|
|
239
|
+
line: "pro-monitor",
|
|
240
|
+
tags: ["1536", "2xl", "screen"]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: "imac-27",
|
|
244
|
+
name: 'iMac 27"',
|
|
245
|
+
width: 2560,
|
|
246
|
+
height: 1440,
|
|
247
|
+
kind: "desktop",
|
|
248
|
+
category: "aio",
|
|
249
|
+
brand: "apple",
|
|
250
|
+
line: "imac",
|
|
251
|
+
tags: ["apple", "mac", "imac", "27", "5k", "screen"]
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: "full-hd",
|
|
255
|
+
name: "Full HD",
|
|
256
|
+
width: 1920,
|
|
257
|
+
height: 1080,
|
|
258
|
+
kind: "desktop",
|
|
259
|
+
category: "desktop",
|
|
260
|
+
brand: "monitor",
|
|
261
|
+
line: "pro-monitor",
|
|
262
|
+
tags: ["1920", "1080", "fhd", "screen"]
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
id: "wqxga",
|
|
266
|
+
name: "WQXGA 2.5K",
|
|
267
|
+
width: 2560,
|
|
268
|
+
height: 1600,
|
|
269
|
+
kind: "desktop",
|
|
270
|
+
category: "desktop",
|
|
271
|
+
brand: "monitor",
|
|
272
|
+
line: "pro-monitor",
|
|
273
|
+
tags: ["2560", "1600", "2k", "qhd", "screen"]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: "uhd-4k",
|
|
277
|
+
name: "4K UHD",
|
|
278
|
+
width: 3840,
|
|
279
|
+
height: 2160,
|
|
280
|
+
kind: "desktop",
|
|
281
|
+
category: "desktop",
|
|
282
|
+
brand: "monitor",
|
|
283
|
+
line: "pro-monitor",
|
|
284
|
+
tags: ["3840", "2160", "4k", "uhd", "screen"]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: "custom",
|
|
288
|
+
name: "Personalizado",
|
|
289
|
+
width: 480,
|
|
290
|
+
height: 720,
|
|
291
|
+
kind: "phone",
|
|
292
|
+
category: "custom",
|
|
293
|
+
brand: "custom",
|
|
294
|
+
line: "custom",
|
|
295
|
+
tags: ["custom", "user"]
|
|
296
|
+
}
|
|
297
|
+
];
|
|
298
|
+
function getViewportSize(device, orientation) {
|
|
299
|
+
const baseIsLandscape = device.width >= device.height;
|
|
300
|
+
if (orientation === "landscape") {
|
|
301
|
+
return baseIsLandscape ? { width: device.width, height: device.height } : { width: device.height, height: device.width };
|
|
302
|
+
}
|
|
303
|
+
return baseIsLandscape ? { width: device.height, height: device.width } : { width: device.width, height: device.height };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/lib/responsive/server.ts
|
|
307
|
+
var _a;
|
|
308
|
+
var DEFAULT_CHROME_PATH = (_a = process.env.RESPONSIVE_CHROME_PATH) != null ? _a : "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
|
309
|
+
var SESSION_TTL_MS = 1e3 * 60 * 15;
|
|
310
|
+
var ACTION_SETTLE_MS = 350;
|
|
311
|
+
var NAVIGATION_TIMEOUT_MS = 3e4;
|
|
312
|
+
var SCREENSHOT_TIMEOUT_MS = 6e4;
|
|
313
|
+
function getStore() {
|
|
314
|
+
if (!globalThis.__responsiveStore__) {
|
|
315
|
+
globalThis.__responsiveStore__ = {
|
|
316
|
+
browserPromise: null,
|
|
317
|
+
sessions: /* @__PURE__ */ new Map(),
|
|
318
|
+
cleanupTimer: null
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (!globalThis.__responsiveStore__.cleanupTimer) {
|
|
322
|
+
globalThis.__responsiveStore__.cleanupTimer = setInterval(() => {
|
|
323
|
+
void cleanupExpiredSessions();
|
|
324
|
+
}, 6e4);
|
|
325
|
+
}
|
|
326
|
+
return globalThis.__responsiveStore__;
|
|
327
|
+
}
|
|
328
|
+
async function resolveBrowser() {
|
|
329
|
+
const store = getStore();
|
|
330
|
+
if (!store.browserPromise) {
|
|
331
|
+
store.browserPromise = (async () => {
|
|
332
|
+
await (0, import_promises.access)(DEFAULT_CHROME_PATH, import_node_fs.constants.X_OK);
|
|
333
|
+
return import_playwright_core.chromium.launch({
|
|
334
|
+
headless: true,
|
|
335
|
+
executablePath: DEFAULT_CHROME_PATH,
|
|
336
|
+
args: [
|
|
337
|
+
"--disable-dev-shm-usage",
|
|
338
|
+
"--disable-background-timer-throttling",
|
|
339
|
+
"--disable-renderer-backgrounding"
|
|
340
|
+
]
|
|
341
|
+
});
|
|
342
|
+
})().catch((error) => {
|
|
343
|
+
store.browserPromise = null;
|
|
344
|
+
throw error;
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
return store.browserPromise;
|
|
348
|
+
}
|
|
349
|
+
function sanitizeUrl(rawUrl) {
|
|
350
|
+
try {
|
|
351
|
+
const url = new URL(rawUrl);
|
|
352
|
+
if (!["http:", "https:"].includes(url.protocol)) {
|
|
353
|
+
throw new Error("Solo se permiten URLs http/https.");
|
|
354
|
+
}
|
|
355
|
+
return url.toString();
|
|
356
|
+
} catch (e) {
|
|
357
|
+
throw new Error("URL invalida. Usa una ruta local completa o una URL externa valida.");
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function emptySnapshot(device, orientation, targetUrl) {
|
|
361
|
+
const viewport = getViewportSize(device, orientation);
|
|
362
|
+
return {
|
|
363
|
+
deviceId: device.id,
|
|
364
|
+
name: device.name,
|
|
365
|
+
width: viewport.width,
|
|
366
|
+
height: viewport.height,
|
|
367
|
+
screenshotDataUrl: null,
|
|
368
|
+
status: "loading",
|
|
369
|
+
currentUrl: targetUrl,
|
|
370
|
+
title: "",
|
|
371
|
+
error: null
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
async function waitForPageReady(page) {
|
|
375
|
+
await page.waitForLoadState("domcontentloaded", { timeout: NAVIGATION_TIMEOUT_MS });
|
|
376
|
+
try {
|
|
377
|
+
await page.waitForLoadState("networkidle", { timeout: 2e3 });
|
|
378
|
+
} catch (e) {
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function getBrowserNavigationError(page) {
|
|
382
|
+
const currentUrl = page.url();
|
|
383
|
+
if (currentUrl.startsWith("chrome-error://")) {
|
|
384
|
+
return "Chrome no pudo cargar la URL destino.";
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
async function captureFrame(frame) {
|
|
389
|
+
const { page } = frame;
|
|
390
|
+
try {
|
|
391
|
+
const navigationError = getBrowserNavigationError(page);
|
|
392
|
+
if (navigationError) {
|
|
393
|
+
throw new Error(navigationError);
|
|
394
|
+
}
|
|
395
|
+
await page.waitForTimeout(60);
|
|
396
|
+
const buffer = await page.screenshot({
|
|
397
|
+
type: "jpeg",
|
|
398
|
+
quality: 65,
|
|
399
|
+
animations: "disabled",
|
|
400
|
+
caret: "hide",
|
|
401
|
+
timeout: SCREENSHOT_TIMEOUT_MS
|
|
402
|
+
});
|
|
403
|
+
frame.snapshot = __spreadProps(__spreadValues({}, frame.snapshot), {
|
|
404
|
+
screenshotDataUrl: `data:image/jpeg;base64,${buffer.toString("base64")}`,
|
|
405
|
+
status: "ready",
|
|
406
|
+
currentUrl: page.url(),
|
|
407
|
+
title: await page.title(),
|
|
408
|
+
error: null
|
|
409
|
+
});
|
|
410
|
+
} catch (error) {
|
|
411
|
+
frame.snapshot = __spreadProps(__spreadValues({}, frame.snapshot), {
|
|
412
|
+
screenshotDataUrl: null,
|
|
413
|
+
status: "error",
|
|
414
|
+
currentUrl: page.url(),
|
|
415
|
+
title: "",
|
|
416
|
+
error: error instanceof Error ? error.message : "No se pudo capturar el viewport."
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async function refreshSession(session) {
|
|
421
|
+
for (const frame of session.frames.values()) {
|
|
422
|
+
await captureFrame(frame);
|
|
423
|
+
}
|
|
424
|
+
session.updatedAt = Date.now();
|
|
425
|
+
}
|
|
426
|
+
async function closeSessionResources(session) {
|
|
427
|
+
if (session.closed) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
session.closed = true;
|
|
431
|
+
await Promise.all(
|
|
432
|
+
Array.from(session.frames.values()).map(async (frame) => {
|
|
433
|
+
await frame.context.close().catch(() => void 0);
|
|
434
|
+
})
|
|
435
|
+
);
|
|
436
|
+
session.frames.clear();
|
|
437
|
+
}
|
|
438
|
+
async function cleanupExpiredSessions() {
|
|
439
|
+
const store = getStore();
|
|
440
|
+
const now = Date.now();
|
|
441
|
+
const expired = Array.from(store.sessions.values()).filter(
|
|
442
|
+
(session) => now - session.updatedAt > SESSION_TTL_MS
|
|
443
|
+
);
|
|
444
|
+
await Promise.all(
|
|
445
|
+
expired.map(async (session) => {
|
|
446
|
+
store.sessions.delete(session.id);
|
|
447
|
+
await closeSessionResources(session);
|
|
448
|
+
})
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
function requireSession(sessionId) {
|
|
452
|
+
const store = getStore();
|
|
453
|
+
const session = store.sessions.get(sessionId);
|
|
454
|
+
if (!session || session.closed) {
|
|
455
|
+
throw new Error("La sesion ya no existe. Abri la URL de nuevo.");
|
|
456
|
+
}
|
|
457
|
+
session.updatedAt = Date.now();
|
|
458
|
+
return session;
|
|
459
|
+
}
|
|
460
|
+
function toSnapshot(session) {
|
|
461
|
+
return {
|
|
462
|
+
sessionId: session.id,
|
|
463
|
+
targetUrl: session.targetUrl,
|
|
464
|
+
orientation: session.orientation,
|
|
465
|
+
updatedAt: session.updatedAt,
|
|
466
|
+
frames: DEVICE_PRESETS.map((device) => {
|
|
467
|
+
var _a2;
|
|
468
|
+
const frame = session.frames.get(device.id);
|
|
469
|
+
return (_a2 = frame == null ? void 0 : frame.snapshot) != null ? _a2 : emptySnapshot(device, session.orientation, session.targetUrl);
|
|
470
|
+
})
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function createFrame(browser, device, targetUrl, orientation) {
|
|
474
|
+
const viewport = getViewportSize(device, orientation);
|
|
475
|
+
const context = await browser.newContext({
|
|
476
|
+
viewport,
|
|
477
|
+
screen: viewport,
|
|
478
|
+
deviceScaleFactor: 1,
|
|
479
|
+
isMobile: device.kind === "phone",
|
|
480
|
+
hasTouch: device.kind !== "desktop"
|
|
481
|
+
});
|
|
482
|
+
const page = await context.newPage();
|
|
483
|
+
const snapshot = emptySnapshot(device, orientation, targetUrl);
|
|
484
|
+
try {
|
|
485
|
+
await page.goto(targetUrl, {
|
|
486
|
+
waitUntil: "domcontentloaded",
|
|
487
|
+
timeout: NAVIGATION_TIMEOUT_MS
|
|
488
|
+
});
|
|
489
|
+
await waitForPageReady(page);
|
|
490
|
+
const navigationError = getBrowserNavigationError(page);
|
|
491
|
+
if (navigationError) {
|
|
492
|
+
throw new Error(navigationError);
|
|
493
|
+
}
|
|
494
|
+
} catch (error) {
|
|
495
|
+
snapshot.status = "error";
|
|
496
|
+
snapshot.error = error instanceof Error ? error.message : "No se pudo abrir la URL.";
|
|
497
|
+
}
|
|
498
|
+
const frame = {
|
|
499
|
+
device,
|
|
500
|
+
context,
|
|
501
|
+
page,
|
|
502
|
+
snapshot: __spreadProps(__spreadValues({}, snapshot), {
|
|
503
|
+
currentUrl: page.url() || targetUrl
|
|
504
|
+
})
|
|
505
|
+
};
|
|
506
|
+
await captureFrame(frame);
|
|
507
|
+
return frame;
|
|
508
|
+
}
|
|
509
|
+
async function createResponsiveSession(targetUrl, orientation) {
|
|
510
|
+
const sanitizedUrl = sanitizeUrl(targetUrl);
|
|
511
|
+
const browser = await resolveBrowser();
|
|
512
|
+
const frames = [];
|
|
513
|
+
for (const device of DEVICE_PRESETS) {
|
|
514
|
+
frames.push(await createFrame(browser, device, sanitizedUrl, orientation));
|
|
515
|
+
}
|
|
516
|
+
const session = {
|
|
517
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
518
|
+
targetUrl: sanitizedUrl,
|
|
519
|
+
orientation,
|
|
520
|
+
frames: new Map(frames.map((frame) => [frame.device.id, frame])),
|
|
521
|
+
updatedAt: Date.now(),
|
|
522
|
+
closed: false
|
|
523
|
+
};
|
|
524
|
+
getStore().sessions.set(session.id, session);
|
|
525
|
+
return toSnapshot(session);
|
|
526
|
+
}
|
|
527
|
+
async function getResponsiveSession(sessionId) {
|
|
528
|
+
const session = requireSession(sessionId);
|
|
529
|
+
await refreshSession(session);
|
|
530
|
+
return toSnapshot(session);
|
|
531
|
+
}
|
|
532
|
+
async function deleteResponsiveSession(sessionId) {
|
|
533
|
+
const store = getStore();
|
|
534
|
+
const session = store.sessions.get(sessionId);
|
|
535
|
+
if (!session) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
store.sessions.delete(sessionId);
|
|
539
|
+
await closeSessionResources(session);
|
|
540
|
+
}
|
|
541
|
+
function clampRatio(value) {
|
|
542
|
+
return Math.max(0, Math.min(1, value));
|
|
543
|
+
}
|
|
544
|
+
async function settleSession(session) {
|
|
545
|
+
await Promise.all(
|
|
546
|
+
Array.from(session.frames.values()).map(async ({ page }) => {
|
|
547
|
+
try {
|
|
548
|
+
await page.waitForTimeout(ACTION_SETTLE_MS);
|
|
549
|
+
} catch (e) {
|
|
550
|
+
return void 0;
|
|
551
|
+
}
|
|
552
|
+
})
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
async function performResponsiveAction(sessionId, input) {
|
|
556
|
+
var _a2, _b;
|
|
557
|
+
const session = requireSession(sessionId);
|
|
558
|
+
if (input.type === "reload") {
|
|
559
|
+
await Promise.all(
|
|
560
|
+
Array.from(session.frames.values()).map(async ({ page, snapshot }) => {
|
|
561
|
+
snapshot.status = "loading";
|
|
562
|
+
try {
|
|
563
|
+
await page.reload({ waitUntil: "domcontentloaded", timeout: NAVIGATION_TIMEOUT_MS });
|
|
564
|
+
await waitForPageReady(page);
|
|
565
|
+
const navigationError = getBrowserNavigationError(page);
|
|
566
|
+
if (navigationError) {
|
|
567
|
+
throw new Error(navigationError);
|
|
568
|
+
}
|
|
569
|
+
} catch (error) {
|
|
570
|
+
snapshot.status = "error";
|
|
571
|
+
snapshot.error = error instanceof Error ? error.message : "No se pudo recargar.";
|
|
572
|
+
}
|
|
573
|
+
})
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
if (input.type === "set-orientation") {
|
|
577
|
+
session.orientation = input.orientation;
|
|
578
|
+
await Promise.all(
|
|
579
|
+
Array.from(session.frames.values()).map(async (frame) => {
|
|
580
|
+
const viewport = getViewportSize(frame.device, input.orientation);
|
|
581
|
+
frame.snapshot = __spreadProps(__spreadValues({}, frame.snapshot), {
|
|
582
|
+
width: viewport.width,
|
|
583
|
+
height: viewport.height,
|
|
584
|
+
status: "loading",
|
|
585
|
+
error: null
|
|
586
|
+
});
|
|
587
|
+
await frame.page.setViewportSize(viewport);
|
|
588
|
+
})
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
if (input.type === "navigate") {
|
|
592
|
+
const targetUrl = sanitizeUrl(input.targetUrl);
|
|
593
|
+
session.targetUrl = targetUrl;
|
|
594
|
+
await Promise.all(
|
|
595
|
+
Array.from(session.frames.values()).map(async ({ page, snapshot }) => {
|
|
596
|
+
snapshot.status = "loading";
|
|
597
|
+
try {
|
|
598
|
+
await page.goto(targetUrl, {
|
|
599
|
+
waitUntil: "domcontentloaded",
|
|
600
|
+
timeout: NAVIGATION_TIMEOUT_MS
|
|
601
|
+
});
|
|
602
|
+
await waitForPageReady(page);
|
|
603
|
+
const navigationError = getBrowserNavigationError(page);
|
|
604
|
+
if (navigationError) {
|
|
605
|
+
throw new Error(navigationError);
|
|
606
|
+
}
|
|
607
|
+
} catch (error) {
|
|
608
|
+
snapshot.status = "error";
|
|
609
|
+
snapshot.error = error instanceof Error ? error.message : "No se pudo navegar.";
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
if (input.type === "click") {
|
|
615
|
+
await Promise.all(
|
|
616
|
+
Array.from(session.frames.values()).map(async (frame) => {
|
|
617
|
+
const { width, height } = getViewportSize(frame.device, session.orientation);
|
|
618
|
+
await frame.page.mouse.click(
|
|
619
|
+
clampRatio(input.xRatio) * width,
|
|
620
|
+
clampRatio(input.yRatio) * height
|
|
621
|
+
);
|
|
622
|
+
})
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
if (input.type === "scroll") {
|
|
626
|
+
const deltaX = (_a2 = input.deltaX) != null ? _a2 : 0;
|
|
627
|
+
const deltaY = (_b = input.deltaY) != null ? _b : 0;
|
|
628
|
+
await Promise.all(
|
|
629
|
+
Array.from(session.frames.values()).map(
|
|
630
|
+
({ page }) => page.evaluate(
|
|
631
|
+
({ nextX, nextY }) => {
|
|
632
|
+
window.scrollBy(nextX, nextY);
|
|
633
|
+
},
|
|
634
|
+
{ nextX: deltaX, nextY: deltaY }
|
|
635
|
+
)
|
|
636
|
+
)
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
await settleSession(session);
|
|
640
|
+
await refreshSession(session);
|
|
641
|
+
return toSnapshot(session);
|
|
642
|
+
}
|
|
643
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
644
|
+
0 && (module.exports = {
|
|
645
|
+
createResponsiveSession,
|
|
646
|
+
deleteResponsiveSession,
|
|
647
|
+
getResponsiveSession,
|
|
648
|
+
performResponsiveAction
|
|
649
|
+
});
|