@dataemergencia/emergency 0.1.0 → 0.2.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 +48 -29
- package/dist/iife/emergency.iife.global.js +6 -6
- package/dist/index.cjs +246 -178
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +246 -178
- package/dist/styles.css +108 -159
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -436,19 +436,16 @@ const copy = {
|
|
|
436
436
|
simulateSuccessDetails: "Mensajes enviados",
|
|
437
437
|
simulateSuccessCompleted: "Proceso completado",
|
|
438
438
|
feedbackDismiss: "Entendido",
|
|
439
|
-
errorTitle: "
|
|
439
|
+
errorTitle: "Ha ocurrido un error",
|
|
440
440
|
errorText: "Ha ocurrido un error inesperado.",
|
|
441
441
|
errorDetailInfo: "Revisa la información requerida",
|
|
442
442
|
errorDetailRetry: "Intenta nuevamente",
|
|
443
443
|
retry: "Reintentar",
|
|
444
444
|
geolocationTitle: "No pudimos obtener tu ubicación",
|
|
445
|
-
geolocationDenied: "Permiso de ubicación denegado.
|
|
446
|
-
geolocationUnavailable: "Tu ubicación no está disponible en este momento.
|
|
447
|
-
geolocationTimeout: "La ubicación tardó demasiado.
|
|
448
|
-
geolocationUnsupported: "Este dispositivo no permite compartir la ubicación.
|
|
449
|
-
fallbackTitle: "Llama directamente",
|
|
450
|
-
fallbackDescription: "Si no puedes completar la emergencia desde aquí, llama a este número.",
|
|
451
|
-
fallbackCall: "Llamar",
|
|
445
|
+
geolocationDenied: "Permiso de ubicación denegado. Habilita el acceso a la ubicación en tu navegador e inténtalo de nuevo.",
|
|
446
|
+
geolocationUnavailable: "Tu ubicación no está disponible en este momento. Verifica que el GPS esté activado e inténtalo de nuevo.",
|
|
447
|
+
geolocationTimeout: "La ubicación tardó demasiado. Muévete a un lugar con mejor señal e inténtalo de nuevo.",
|
|
448
|
+
geolocationUnsupported: "Este dispositivo no permite compartir la ubicación. Inténtalo desde otro navegador o dispositivo.",
|
|
452
449
|
resumeTitle: "Emergencia Activa Detectada",
|
|
453
450
|
resumeDescription: "Se ha detectado una emergencia activa en el sistema. Por favor, revisa el estado de la emergencia inmediatamente.",
|
|
454
451
|
resumeAction: "Abrir Panel de Emergencia",
|
|
@@ -990,7 +987,6 @@ function createEmergencyController(deps) {
|
|
|
990
987
|
geolocationError: normalized
|
|
991
988
|
});
|
|
992
989
|
transition({ kind: "ready" });
|
|
993
|
-
pushMessage("error", normalized.message);
|
|
994
990
|
events.emit("emergency:failed", {
|
|
995
991
|
error: normalized,
|
|
996
992
|
operation: "geolocation"
|
|
@@ -1294,16 +1290,87 @@ function createEmergencyController(deps) {
|
|
|
1294
1290
|
if (!get().snapshot?.active) patch({ simulationConfirmation: true });
|
|
1295
1291
|
},
|
|
1296
1292
|
cancelSimulationConfirmation: () => patch({ simulationConfirmation: false }),
|
|
1297
|
-
dismissFeedback: () =>
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1293
|
+
dismissFeedback: () => {
|
|
1294
|
+
const state = get();
|
|
1295
|
+
patch({
|
|
1296
|
+
abortResult: null,
|
|
1297
|
+
simulationResult: null,
|
|
1298
|
+
geolocationError: null,
|
|
1299
|
+
...state.geolocationError !== null || state.abortResult?.ok === false || state.simulationResult?.ok === false || state.phase.kind === "ready" && state.lastError !== null ? { lastError: null } : {}
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1301
1302
|
},
|
|
1302
1303
|
store,
|
|
1303
1304
|
events
|
|
1304
1305
|
};
|
|
1305
1306
|
}
|
|
1306
1307
|
|
|
1308
|
+
// src/core/fonts.ts
|
|
1309
|
+
/**
|
|
1310
|
+
* The exact Google Fonts query segment for each family. Family order matters:
|
|
1311
|
+
* with every family enabled the generated href is the documented stylesheet
|
|
1312
|
+
* URL, byte for byte.
|
|
1313
|
+
*/
|
|
1314
|
+
const FONT_FAMILY_PARAMS = {
|
|
1315
|
+
googleSans: "family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700",
|
|
1316
|
+
montserrat: "family=Montserrat:ital,wght@0,100..900;1,100..900",
|
|
1317
|
+
poppins: "family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900"
|
|
1318
|
+
};
|
|
1319
|
+
const FONT_FAMILY_ORDER = [
|
|
1320
|
+
"googleSans",
|
|
1321
|
+
"montserrat",
|
|
1322
|
+
"poppins"
|
|
1323
|
+
];
|
|
1324
|
+
const FONT_STYLESHEET_BASE = "https://fonts.googleapis.com/css2";
|
|
1325
|
+
const FONT_ORIGIN = "https://fonts.googleapis.com";
|
|
1326
|
+
const FONT_STATIC_ORIGIN = "https://fonts.gstatic.com";
|
|
1327
|
+
/** Marks every link the client injects so repeated mounts stay idempotent. */
|
|
1328
|
+
const FONT_LINK_ATTRIBUTE = "data-de-emergency-fonts";
|
|
1329
|
+
function normalizeFontLoading(input) {
|
|
1330
|
+
const flags = input?.fonts ?? {};
|
|
1331
|
+
return {
|
|
1332
|
+
load: input?.load ?? true,
|
|
1333
|
+
fonts: {
|
|
1334
|
+
googleSans: flags.googleSans ?? true,
|
|
1335
|
+
montserrat: flags.montserrat ?? true,
|
|
1336
|
+
poppins: flags.poppins ?? true
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Builds the stylesheet URL for the enabled families, or `null` when the
|
|
1342
|
+
* master switch is off or no family is enabled. A disabled family is left out
|
|
1343
|
+
* of the request entirely.
|
|
1344
|
+
*/
|
|
1345
|
+
function buildFontStylesheetHref(input) {
|
|
1346
|
+
const { load, fonts } = normalizeFontLoading(input);
|
|
1347
|
+
if (!load) return null;
|
|
1348
|
+
const params = FONT_FAMILY_ORDER.filter((family) => fonts[family]).map((family) => FONT_FAMILY_PARAMS[family]);
|
|
1349
|
+
if (params.length === 0) return null;
|
|
1350
|
+
return `${FONT_STYLESHEET_BASE}?${params.join("&")}&display=swap`;
|
|
1351
|
+
}
|
|
1352
|
+
function createFontLink(rel, href, crossorigin = false) {
|
|
1353
|
+
const link = document.createElement("link");
|
|
1354
|
+
link.rel = rel;
|
|
1355
|
+
link.href = href;
|
|
1356
|
+
if (crossorigin) link.crossOrigin = "anonymous";
|
|
1357
|
+
link.setAttribute(FONT_LINK_ATTRIBUTE, "");
|
|
1358
|
+
return link;
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Injects the preconnect and stylesheet links the panel needs, once per page.
|
|
1362
|
+
* The first successful mount wins: later mounts, including mounts from a
|
|
1363
|
+
* duplicated copy of the library, reuse the links already present. The links
|
|
1364
|
+
* are page-level assets and are intentionally not removed on `destroy()`.
|
|
1365
|
+
*/
|
|
1366
|
+
function installEmergencyFonts(input) {
|
|
1367
|
+
if (typeof document === "undefined") return;
|
|
1368
|
+
const href = buildFontStylesheetHref(input);
|
|
1369
|
+
if (href === null) return;
|
|
1370
|
+
if (document.querySelector(`link[${"data-de-emergency-fonts"}]`)) return;
|
|
1371
|
+
(document.head ?? document.documentElement).append(createFontLink("preconnect", FONT_ORIGIN), createFontLink("preconnect", FONT_STATIC_ORIGIN, true), createFontLink("stylesheet", href));
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1307
1374
|
// src/core/config.ts
|
|
1308
1375
|
const EMERGENCY_CODE_PATTERN = /^[A-Za-z][A-Za-z0-9]{5}$/;
|
|
1309
1376
|
const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
@@ -1375,44 +1442,85 @@ function validateConfig(config) {
|
|
|
1375
1442
|
code,
|
|
1376
1443
|
locale: config.locale ?? "es",
|
|
1377
1444
|
geolocationTimeoutMs: config.geolocationTimeoutMs ?? 8e3,
|
|
1378
|
-
requestTimeoutMs: config.requestTimeoutMs ?? 15e3
|
|
1445
|
+
requestTimeoutMs: config.requestTimeoutMs ?? 15e3,
|
|
1446
|
+
fontLoading: normalizeFontLoading(config.fontLoading)
|
|
1379
1447
|
}
|
|
1380
1448
|
};
|
|
1381
1449
|
}
|
|
1382
1450
|
|
|
1383
|
-
// src/
|
|
1451
|
+
// src/react/components/icons/paramedical-mark.tsx
|
|
1384
1452
|
/**
|
|
1385
1453
|
* Neutral inline illustration used by the idle panel.
|
|
1386
1454
|
*/
|
|
1387
1455
|
function ParamedicalMark({ className, title }) {
|
|
1388
1456
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
1457
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1458
|
+
version: "1.0",
|
|
1459
|
+
viewBox: "0 0 192 192",
|
|
1460
|
+
width: "192",
|
|
1461
|
+
height: "192",
|
|
1462
|
+
id: "Star of life",
|
|
1389
1463
|
className,
|
|
1390
|
-
viewBox: "0 0 96 96",
|
|
1391
|
-
role: "img",
|
|
1392
1464
|
"aria-label": title,
|
|
1393
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
1394
1465
|
children: [
|
|
1395
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1466
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { id: "defs2886" }),
|
|
1467
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
1468
|
+
id: "cross",
|
|
1469
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1470
|
+
d: "m 74,133 0,52 44,0 0,-52 44,26 22,-38 L 140,96 184,70 162,32 117,58 117,7 74,7 74,58 30,32 8,70 52,96 8,121 30,159 z",
|
|
1471
|
+
id: "outline",
|
|
1472
|
+
style: {
|
|
1473
|
+
fill: "none",
|
|
1474
|
+
stroke: "#3333bb",
|
|
1475
|
+
strokeWidth: 6
|
|
1476
|
+
}
|
|
1477
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1478
|
+
d: "m 74,133 0,52 44,0 0,-52 44,26 22,-38 L 140,96 184,70 162,32 117,58 117,7 74,7 74,58 30,32 8,70 52,96 8,121 30,159 z",
|
|
1479
|
+
id: "inner",
|
|
1480
|
+
style: {
|
|
1481
|
+
fill: "#0000bb",
|
|
1482
|
+
fillRule: "evenodd",
|
|
1483
|
+
stroke: "#ffffff",
|
|
1484
|
+
strokeWidth: 2
|
|
1485
|
+
}
|
|
1486
|
+
})]
|
|
1406
1487
|
}),
|
|
1407
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1408
|
-
|
|
1409
|
-
|
|
1488
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
1489
|
+
id: "symbols",
|
|
1490
|
+
style: {
|
|
1491
|
+
fill: "#ffffff",
|
|
1492
|
+
fillRule: "evenodd",
|
|
1493
|
+
stroke: "#3333bb",
|
|
1494
|
+
strokeWidth: 2
|
|
1495
|
+
},
|
|
1496
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1497
|
+
d: "m 93,166 c 0,7 6,7 6,0 l 3,-138 c 0,-8 -12,-8 -12,0 l 3,135 0,3 z",
|
|
1498
|
+
id: "rod"
|
|
1499
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
1500
|
+
id: "snake",
|
|
1501
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1502
|
+
d: "m 100,153 c 7,4 3,15 -3,15 2,-5 3,-9 3,-15 z m 1,-40 c 10,9 4,22 -3,26 -6,3 -6,7 -6,15 -9,-10 -4,-19 4,-24 5,-4 5,-10 5,-17 z m 1,-30 c 0,11 -17,14 -17,22 0,3 1,9 6,12 0,-11 9,-12 15,-18 7,-7 7,-19 -4,-28 0,4 0,8 0,12 z M 90,77 C 80,69 76,55 80,46 c 3,-10 20,-11 20,-3 0,8 -20,3 -13,16 l 3,5 0,13 z",
|
|
1503
|
+
id: "body"
|
|
1504
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1505
|
+
d: "m 95,43 c 7,-3 -7,-3 0,0 z",
|
|
1506
|
+
id: "eye",
|
|
1507
|
+
style: {
|
|
1508
|
+
fill: "#3333bb",
|
|
1509
|
+
fillRule: "evenodd",
|
|
1510
|
+
stroke: "none"
|
|
1511
|
+
}
|
|
1512
|
+
})]
|
|
1513
|
+
})]
|
|
1410
1514
|
})
|
|
1411
1515
|
]
|
|
1412
1516
|
});
|
|
1413
1517
|
}
|
|
1414
1518
|
|
|
1415
1519
|
// src/react/components/Icon/index.tsx
|
|
1520
|
+
/** Icons whose artwork does not fit the default 24x24 grid need their own canvas. */
|
|
1521
|
+
const viewBoxes = { emergency: "0 0 640 640" };
|
|
1522
|
+
/** Icons rendered as a solid shape instead of a stroked outline. */
|
|
1523
|
+
const filledIcons = /* @__PURE__ */ new Set(["emergency"]);
|
|
1416
1524
|
const paths = {
|
|
1417
1525
|
close: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M6 6l12 12M18 6L6 18" }),
|
|
1418
1526
|
"alert-triangle": /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
@@ -1464,21 +1572,18 @@ const paths = {
|
|
|
1464
1572
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 7h.01" })
|
|
1465
1573
|
] }),
|
|
1466
1574
|
"arrow-left": /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M19 12H5" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m12 19-7-7 7-7" })] }),
|
|
1467
|
-
emergency: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1468
|
-
cx: "12",
|
|
1469
|
-
cy: "12",
|
|
1470
|
-
r: "3"
|
|
1471
|
-
})] })
|
|
1575
|
+
emergency: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M272.5 96C272.5 78.3 286.8 64 304.5 64L336.5 64C354.2 64 368.5 78.3 368.5 96L368.5 236.9L490.5 166.5C505.8 157.7 525.4 162.9 534.2 178.2L550.2 205.9C559 221.2 553.8 240.8 538.5 249.6L416.5 320L538.5 390.4C553.8 399.2 559.1 418.8 550.2 434.1L534.2 461.8C525.4 477.1 505.8 482.4 490.5 473.5L368.5 403.1L368.5 544C368.5 561.7 354.2 576 336.5 576L304.5 576C286.8 576 272.5 561.7 272.5 544L272.5 403.1L150.5 473.5C135.2 482.3 115.6 477.1 106.8 461.8L90.8 434.1C82 418.8 87.2 399.2 102.5 390.4L224.5 320L102.5 249.6C87.2 240.8 82 221.2 90.8 205.9L106.8 178.2C115.6 162.9 135.2 157.7 150.5 166.5L272.5 236.9L272.5 96z" }) })
|
|
1472
1576
|
};
|
|
1473
1577
|
function Icon({ name, className, title }) {
|
|
1578
|
+
const stroked = !filledIcons.has(name);
|
|
1474
1579
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
1475
1580
|
className,
|
|
1476
|
-
viewBox: "0 0 24 24",
|
|
1477
|
-
width: "
|
|
1478
|
-
height: "
|
|
1479
|
-
fill: "none",
|
|
1480
|
-
stroke: "currentColor",
|
|
1481
|
-
strokeWidth:
|
|
1581
|
+
viewBox: viewBoxes[name] ?? "0 0 24 24",
|
|
1582
|
+
width: "1rem",
|
|
1583
|
+
height: "1rem",
|
|
1584
|
+
fill: stroked ? "none" : "currentColor",
|
|
1585
|
+
stroke: stroked ? "currentColor" : "none",
|
|
1586
|
+
strokeWidth: stroked ? 2 : void 0,
|
|
1482
1587
|
strokeLinecap: "round",
|
|
1483
1588
|
strokeLinejoin: "round",
|
|
1484
1589
|
"aria-hidden": title ? void 0 : "true",
|
|
@@ -1497,14 +1602,16 @@ var panel_module_default = {
|
|
|
1497
1602
|
"de-emergency-slide-up": "de-emergency-de-emergency-slide-up-kMlO0G",
|
|
1498
1603
|
"de-emergency-spin": "de-emergency-de-emergency-spin-kMlO0G",
|
|
1499
1604
|
"emergency-confirmation": "de-emergency-emergency-confirmation-kMlO0G",
|
|
1500
|
-
"emergency-
|
|
1605
|
+
"emergency-confirmation__body": "de-emergency-emergency-confirmation__body-kMlO0G",
|
|
1501
1606
|
"emergency-confirmation__button": "de-emergency-emergency-confirmation__button-kMlO0G",
|
|
1502
1607
|
"emergency-confirmation__button--cancel": "de-emergency-emergency-confirmation__button--cancel-kMlO0G",
|
|
1503
1608
|
"emergency-confirmation__button--confirm": "de-emergency-emergency-confirmation__button--confirm-kMlO0G",
|
|
1504
1609
|
"emergency-confirmation__button--danger": "de-emergency-emergency-confirmation__button--danger-kMlO0G",
|
|
1505
1610
|
"emergency-confirmation__card": "de-emergency-emergency-confirmation__card-kMlO0G",
|
|
1506
|
-
"emergency-
|
|
1611
|
+
"emergency-confirmation__footer": "de-emergency-emergency-confirmation__footer-kMlO0G",
|
|
1507
1612
|
"emergency-confirmation__icon": "de-emergency-emergency-confirmation__icon-kMlO0G",
|
|
1613
|
+
"emergency-confirmation__icon--danger": "de-emergency-emergency-confirmation__icon--danger-kMlO0G",
|
|
1614
|
+
"emergency-confirmation__icon--information": "de-emergency-emergency-confirmation__icon--information-kMlO0G",
|
|
1508
1615
|
"emergency-confirmation__text": "de-emergency-emergency-confirmation__text-kMlO0G",
|
|
1509
1616
|
"emergency-confirmation__title": "de-emergency-emergency-confirmation__title-kMlO0G",
|
|
1510
1617
|
"emergency-error-message": "de-emergency-emergency-error-message-kMlO0G",
|
|
@@ -1515,10 +1622,6 @@ var panel_module_default = {
|
|
|
1515
1622
|
"emergency-error-message__icon": "de-emergency-emergency-error-message__icon-kMlO0G",
|
|
1516
1623
|
"emergency-error-message__text": "de-emergency-emergency-error-message__text-kMlO0G",
|
|
1517
1624
|
"emergency-error-message__title": "de-emergency-emergency-error-message__title-kMlO0G",
|
|
1518
|
-
"emergency-fallback": "de-emergency-emergency-fallback-kMlO0G",
|
|
1519
|
-
"emergency-fallback__phone": "de-emergency-emergency-fallback__phone-kMlO0G",
|
|
1520
|
-
"emergency-fallback__text": "de-emergency-emergency-fallback__text-kMlO0G",
|
|
1521
|
-
"emergency-fallback__title": "de-emergency-emergency-fallback__title-kMlO0G",
|
|
1522
1625
|
"emergency-feedback": "de-emergency-emergency-feedback-kMlO0G",
|
|
1523
1626
|
"emergency-feedback__dismiss": "de-emergency-emergency-feedback__dismiss-kMlO0G",
|
|
1524
1627
|
"emergency-panel": "de-emergency-emergency-panel-kMlO0G",
|
|
@@ -1550,15 +1653,6 @@ var panel_module_default = {
|
|
|
1550
1653
|
"emergency-status__header": "de-emergency-emergency-status__header-kMlO0G",
|
|
1551
1654
|
"emergency-status__loading": "de-emergency-emergency-status__loading-kMlO0G",
|
|
1552
1655
|
"emergency-status__loading-text": "de-emergency-emergency-status__loading-text-kMlO0G",
|
|
1553
|
-
"emergency-status__message-icon": "de-emergency-emergency-status__message-icon-kMlO0G",
|
|
1554
|
-
"emergency-status__message-icon--failed": "de-emergency-emergency-status__message-icon--failed-kMlO0G",
|
|
1555
|
-
"emergency-status__message-icon--success": "de-emergency-emergency-status__message-icon--success-kMlO0G",
|
|
1556
|
-
"emergency-status__message-row": "de-emergency-emergency-status__message-row-kMlO0G",
|
|
1557
|
-
"emergency-status__message-row--failed": "de-emergency-emergency-status__message-row--failed-kMlO0G",
|
|
1558
|
-
"emergency-status__message-row--success": "de-emergency-emergency-status__message-row--success-kMlO0G",
|
|
1559
|
-
"emergency-status__message-sent-at": "de-emergency-emergency-status__message-sent-at-kMlO0G",
|
|
1560
|
-
"emergency-status__message-text": "de-emergency-emergency-status__message-text-kMlO0G",
|
|
1561
|
-
"emergency-status__message-text-container": "de-emergency-emergency-status__message-text-container-kMlO0G",
|
|
1562
1656
|
"emergency-status__panel": "de-emergency-emergency-status__panel-kMlO0G",
|
|
1563
1657
|
"emergency-status__row": "de-emergency-emergency-status__row-kMlO0G",
|
|
1564
1658
|
"emergency-status__row-container": "de-emergency-emergency-status__row-container-kMlO0G",
|
|
@@ -1569,7 +1663,6 @@ var panel_module_default = {
|
|
|
1569
1663
|
"emergency-status-panel__refresh-icon": "de-emergency-emergency-status-panel__refresh-icon-kMlO0G",
|
|
1570
1664
|
"emergency-status-panel__title": "de-emergency-emergency-status-panel__title-kMlO0G",
|
|
1571
1665
|
"responder-name": "de-emergency-responder-name-kMlO0G",
|
|
1572
|
-
"sent-at--verified": "de-emergency-sent-at--verified-kMlO0G",
|
|
1573
1666
|
"simulacrum-success-message": "de-emergency-simulacrum-success-message-kMlO0G",
|
|
1574
1667
|
"simulacrum-success-message__container": "de-emergency-simulacrum-success-message__container-kMlO0G",
|
|
1575
1668
|
"simulacrum-success-message__content": "de-emergency-simulacrum-success-message__content-kMlO0G",
|
|
@@ -1608,7 +1701,10 @@ function MessageSurface(props) {
|
|
|
1608
1701
|
className: cls(`${prefix}__container`),
|
|
1609
1702
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1610
1703
|
className: cls(`${prefix}__icon`),
|
|
1611
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
1704
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
1705
|
+
name: icon,
|
|
1706
|
+
className: "status-icon"
|
|
1707
|
+
})
|
|
1612
1708
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1613
1709
|
className: cls(`${prefix}__content`),
|
|
1614
1710
|
children: [
|
|
@@ -1656,8 +1752,12 @@ function EmergencyError({ error, onRetry }) {
|
|
|
1656
1752
|
});
|
|
1657
1753
|
}
|
|
1658
1754
|
|
|
1659
|
-
// src/react/components/
|
|
1660
|
-
|
|
1755
|
+
// src/react/components/EmergencyFeedback/index.tsx
|
|
1756
|
+
/** Time the feedback stays on screen before dismissing itself. */
|
|
1757
|
+
const FEEDBACK_AUTO_DISMISS_MS = 3e3;
|
|
1758
|
+
/** Time the geolocation feedback stays on screen before dismissing itself. */
|
|
1759
|
+
const GEOLOCATION_FEEDBACK_AUTO_DISMISS_MS = 5e3;
|
|
1760
|
+
function geolocationText(error) {
|
|
1661
1761
|
switch (error.code) {
|
|
1662
1762
|
case "geolocation_denied": return copy.geolocationDenied;
|
|
1663
1763
|
case "geolocation_timeout": return copy.geolocationTimeout;
|
|
@@ -1665,34 +1765,35 @@ function errorCopy(error) {
|
|
|
1665
1765
|
default: return copy.geolocationUnavailable;
|
|
1666
1766
|
}
|
|
1667
1767
|
}
|
|
1668
|
-
function
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
}),
|
|
1680
|
-
fallback ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
1681
|
-
className: cls("emergency-fallback__phone"),
|
|
1682
|
-
href: `tel:${fallback.phone.replace(/[^\d+]/g, "")}`,
|
|
1683
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "message" }), fallback.label]
|
|
1684
|
-
}) : null
|
|
1685
|
-
]
|
|
1768
|
+
function EmergencyFeedback({ abortResult, simulationResult, geolocationError, activationError, onDismiss }) {
|
|
1769
|
+
const result = abortResult ?? simulationResult;
|
|
1770
|
+
const feedbackActivationError = result ? null : activationError ?? null;
|
|
1771
|
+
const feedbackGeolocationError = result || feedbackActivationError ? null : geolocationError;
|
|
1772
|
+
if (!result && !feedbackActivationError && !feedbackGeolocationError) return null;
|
|
1773
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackSurface, {
|
|
1774
|
+
result,
|
|
1775
|
+
aborting: abortResult !== null,
|
|
1776
|
+
geolocationError: feedbackGeolocationError,
|
|
1777
|
+
activationError: feedbackActivationError,
|
|
1778
|
+
onDismiss
|
|
1686
1779
|
});
|
|
1687
1780
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1781
|
+
function FeedbackSurface({ result, aborting, geolocationError, activationError, onDismiss }) {
|
|
1782
|
+
const dismissRef = (0, react.useRef)(onDismiss);
|
|
1783
|
+
(0, react.useEffect)(() => {
|
|
1784
|
+
dismissRef.current = onDismiss;
|
|
1785
|
+
}, [onDismiss]);
|
|
1786
|
+
(0, react.useEffect)(() => {
|
|
1787
|
+
const timeout = setTimeout(() => dismissRef.current(), geolocationError || activationError ? GEOLOCATION_FEEDBACK_AUTO_DISMISS_MS : FEEDBACK_AUTO_DISMISS_MS);
|
|
1788
|
+
return () => clearTimeout(timeout);
|
|
1789
|
+
}, [
|
|
1790
|
+
result?.at,
|
|
1791
|
+
geolocationError,
|
|
1792
|
+
activationError
|
|
1793
|
+
]);
|
|
1794
|
+
const success = result?.ok === true;
|
|
1695
1795
|
const title = success ? aborting ? copy.abortSuccessTitle : copy.simulateSuccessTitle : copy.errorTitle;
|
|
1796
|
+
const text = success ? result?.message ?? "" : geolocationError ? geolocationText(geolocationError) : activationError ? activationError.message || copy.errorText : result?.message ?? copy.errorText;
|
|
1696
1797
|
const details = success ? aborting ? [{
|
|
1697
1798
|
icon: "message",
|
|
1698
1799
|
text: copy.abortSuccessDetails
|
|
@@ -1713,7 +1814,7 @@ function EmergencyFeedback({ abortResult, simulationResult, onDismiss }) {
|
|
|
1713
1814
|
variant: success ? "success" : "error",
|
|
1714
1815
|
icon: success ? "check-circle" : "alert-triangle",
|
|
1715
1816
|
title,
|
|
1716
|
-
text
|
|
1817
|
+
text,
|
|
1717
1818
|
details,
|
|
1718
1819
|
className: cls("emergency-feedback"),
|
|
1719
1820
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -1767,43 +1868,6 @@ function normalizePeriod(dayPeriod) {
|
|
|
1767
1868
|
return /^a/i.test(dayPeriod) ? "am" : "";
|
|
1768
1869
|
}
|
|
1769
1870
|
|
|
1770
|
-
// src/react/components/EmergencyMessageRow/index.tsx
|
|
1771
|
-
/**
|
|
1772
|
-
* Renders one message row per responder.
|
|
1773
|
-
*/
|
|
1774
|
-
function EmergencyMessageRow({ responder, locale }) {
|
|
1775
|
-
const message = responder.lastMessage;
|
|
1776
|
-
const hasContent = Boolean(message?.content);
|
|
1777
|
-
const modifier = hasContent ? "emergency-status__message-row--success" : "emergency-status__message-row--failed";
|
|
1778
|
-
const iconModifier = hasContent ? "emergency-status__message-icon--success" : "emergency-status__message-icon--failed";
|
|
1779
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1780
|
-
className: cls("emergency-status__message-row", modifier),
|
|
1781
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1782
|
-
className: cls("emergency-status__message-text-container"),
|
|
1783
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
1784
|
-
name: "flag",
|
|
1785
|
-
className: cls("emergency-status__message-icon", iconModifier)
|
|
1786
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1787
|
-
className: cls("emergency-status__message-text"),
|
|
1788
|
-
children: [
|
|
1789
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: copy.statusPrefix }),
|
|
1790
|
-
" ",
|
|
1791
|
-
message?.content ?? ""
|
|
1792
|
-
]
|
|
1793
|
-
})]
|
|
1794
|
-
}), message ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1795
|
-
className: cls("emergency-status__message-text-container", "sent-at--verified"),
|
|
1796
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
1797
|
-
name: "double-check",
|
|
1798
|
-
className: cls("emergency-status__message-icon")
|
|
1799
|
-
}), message.sentAt ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1800
|
-
className: cls("emergency-status__message-sent-at"),
|
|
1801
|
-
children: formatShortTime(message.sentAt, locale)
|
|
1802
|
-
}) : null]
|
|
1803
|
-
}) : null]
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
1871
|
// src/react/components/StatusIcon/index.tsx
|
|
1808
1872
|
/**
|
|
1809
1873
|
* Explicit responder state model:
|
|
@@ -1839,10 +1903,10 @@ function StatusCell({ confirmed, timestamp, failed = false, isFailedIcon = false
|
|
|
1839
1903
|
|
|
1840
1904
|
// src/react/components/ResponderRow/index.tsx
|
|
1841
1905
|
function ResponderRow({ responder, locale }) {
|
|
1842
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1906
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1843
1907
|
className: cls("emergency-status__row-container"),
|
|
1844
1908
|
"data-responder-id": responder.phone,
|
|
1845
|
-
children:
|
|
1909
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1846
1910
|
className: cls("emergency-status__row"),
|
|
1847
1911
|
children: [
|
|
1848
1912
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1872,10 +1936,7 @@ function ResponderRow({ responder, locale }) {
|
|
|
1872
1936
|
locale
|
|
1873
1937
|
})
|
|
1874
1938
|
]
|
|
1875
|
-
})
|
|
1876
|
-
responder,
|
|
1877
|
-
locale
|
|
1878
|
-
})]
|
|
1939
|
+
})
|
|
1879
1940
|
});
|
|
1880
1941
|
}
|
|
1881
1942
|
|
|
@@ -1953,34 +2014,31 @@ function EmergencyStatusPanel({ responders, refreshing, locale, onRefresh }) {
|
|
|
1953
2014
|
|
|
1954
2015
|
// src/react/components/EmergencyBody/index.tsx
|
|
1955
2016
|
function EmergencyBody(props) {
|
|
1956
|
-
const { active, responders, refreshing, loading, locale, geolocationError,
|
|
2017
|
+
const { active, responders, refreshing, loading, locale, geolocationError, activationError, error, abortResult, simulationResult, onRefresh, onRetry, onDismissFeedback } = props;
|
|
2018
|
+
const showingFeedback = geolocationError !== null || Boolean(activationError) || abortResult !== null || simulationResult !== null;
|
|
1957
2019
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1958
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2020
|
+
!loading && !showingFeedback ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1959
2021
|
className: cls("sos-img__container"),
|
|
1960
2022
|
id: "sos-img__container",
|
|
1961
2023
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ParamedicalMark, {
|
|
1962
2024
|
className: cls("sos-img"),
|
|
1963
2025
|
title: copy.illustrationAlt
|
|
1964
2026
|
})
|
|
1965
|
-
}),
|
|
1966
|
-
active ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2027
|
+
}) : null,
|
|
2028
|
+
active || loading || showingFeedback ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1967
2029
|
className: cls("emergency-panel__body-title-container"),
|
|
1968
2030
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1969
2031
|
className: cls("emergency-panel__body-title"),
|
|
1970
2032
|
children: copy.question
|
|
1971
2033
|
})
|
|
1972
2034
|
}),
|
|
1973
|
-
active ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyStatusPanel, {
|
|
2035
|
+
active && !showingFeedback ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyStatusPanel, {
|
|
1974
2036
|
responders,
|
|
1975
2037
|
refreshing,
|
|
1976
2038
|
locale,
|
|
1977
2039
|
onRefresh
|
|
1978
2040
|
}) : null,
|
|
1979
2041
|
loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyLoading, {}) : null,
|
|
1980
|
-
geolocationError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyFallback, {
|
|
1981
|
-
fallback,
|
|
1982
|
-
error: geolocationError
|
|
1983
|
-
}) : null,
|
|
1984
2042
|
error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyError, {
|
|
1985
2043
|
error,
|
|
1986
2044
|
onRetry
|
|
@@ -1988,6 +2046,8 @@ function EmergencyBody(props) {
|
|
|
1988
2046
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyFeedback, {
|
|
1989
2047
|
abortResult,
|
|
1990
2048
|
simulationResult,
|
|
2049
|
+
geolocationError,
|
|
2050
|
+
activationError,
|
|
1991
2051
|
onDismiss: onDismissFeedback
|
|
1992
2052
|
})
|
|
1993
2053
|
] });
|
|
@@ -2006,6 +2066,7 @@ function EmergencyConfirmation(props) {
|
|
|
2006
2066
|
if (!open) return null;
|
|
2007
2067
|
const title = danger ? copy.abortConfirmTitle : copy.simulateConfirmTitle;
|
|
2008
2068
|
const text = danger ? copy.abortConfirmText : copy.simulateConfirmText;
|
|
2069
|
+
const tone = danger ? "danger" : "information";
|
|
2009
2070
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2010
2071
|
className: cls("emergency-confirmation"),
|
|
2011
2072
|
role: "dialog",
|
|
@@ -2013,50 +2074,52 @@ function EmergencyConfirmation(props) {
|
|
|
2013
2074
|
"aria-labelledby": titleId,
|
|
2014
2075
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2015
2076
|
ref: cardRef,
|
|
2016
|
-
className: cls("emergency-confirmation__card"
|
|
2017
|
-
children: [
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2077
|
+
className: cls("emergency-confirmation__card"),
|
|
2078
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2079
|
+
className: cls("emergency-confirmation__body"),
|
|
2080
|
+
children: [
|
|
2081
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2082
|
+
className: cls("emergency-confirmation__icon", `emergency-confirmation__icon--${tone}`),
|
|
2083
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: danger ? "alert-triangle" : "info" })
|
|
2084
|
+
}),
|
|
2085
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h5", {
|
|
2086
|
+
className: cls("emergency-confirmation__title"),
|
|
2087
|
+
id: titleId,
|
|
2088
|
+
children: title
|
|
2089
|
+
}),
|
|
2090
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2091
|
+
className: cls("emergency-confirmation__text"),
|
|
2092
|
+
children: text
|
|
2093
|
+
})
|
|
2094
|
+
]
|
|
2095
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2096
|
+
className: cls("emergency-confirmation__footer"),
|
|
2097
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2098
|
+
type: "button",
|
|
2099
|
+
className: cls("emergency-confirmation__button", "emergency-confirmation__button--cancel"),
|
|
2100
|
+
onClick: danger ? onCancelAbort : onCancelSimulation,
|
|
2101
|
+
children: danger ? copy.abortCancel : copy.simulateCancel
|
|
2102
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2103
|
+
type: "button",
|
|
2104
|
+
className: cls("emergency-confirmation__button", danger ? "emergency-confirmation__button--danger" : "emergency-confirmation__button--confirm"),
|
|
2105
|
+
onClick: danger ? onConfirmAbort : onConfirmSimulation,
|
|
2106
|
+
children: danger ? copy.abortConfirm : copy.simulateConfirm
|
|
2107
|
+
})]
|
|
2108
|
+
})]
|
|
2046
2109
|
})
|
|
2047
2110
|
});
|
|
2048
2111
|
}
|
|
2049
2112
|
|
|
2050
2113
|
// src/react/components/EmergencyFooter/index.tsx
|
|
2051
2114
|
function EmergencyFooter(props) {
|
|
2052
|
-
const { active, busy, aborting, onActivate, onRequestAbort, onRequestSimulation } = props;
|
|
2115
|
+
const { active, busy, aborting, feedbackVisible, onActivate, onRequestAbort, onRequestSimulation } = props;
|
|
2053
2116
|
if (active) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
|
|
2054
2117
|
className: cls("emergency-panel__footer"),
|
|
2055
2118
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2056
2119
|
type: "button",
|
|
2057
2120
|
className: cls("emergency-status__abort-btn"),
|
|
2058
2121
|
"aria-label": copy.abort,
|
|
2059
|
-
disabled: aborting,
|
|
2122
|
+
disabled: aborting || feedbackVisible,
|
|
2060
2123
|
onClick: onRequestAbort,
|
|
2061
2124
|
children: [copy.abort, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "alert-triangle" })]
|
|
2062
2125
|
})
|
|
@@ -2067,14 +2130,14 @@ function EmergencyFooter(props) {
|
|
|
2067
2130
|
type: "button",
|
|
2068
2131
|
className: cls("emergency-panel__button", "emergency-panel__button--emergency"),
|
|
2069
2132
|
"aria-label": copy.emergencyAria,
|
|
2070
|
-
disabled: busy,
|
|
2133
|
+
disabled: busy || feedbackVisible,
|
|
2071
2134
|
onClick: onActivate,
|
|
2072
2135
|
children: [copy.emergency, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "emergency" })]
|
|
2073
2136
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2074
2137
|
type: "button",
|
|
2075
2138
|
className: cls("emergency-panel__button", "emergency-panel__button--simulation"),
|
|
2076
2139
|
"aria-label": copy.testAria,
|
|
2077
|
-
disabled: busy,
|
|
2140
|
+
disabled: busy || feedbackVisible,
|
|
2078
2141
|
onClick: onRequestSimulation,
|
|
2079
2142
|
children: [copy.test, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "list-check" })]
|
|
2080
2143
|
})]
|
|
@@ -2171,9 +2234,10 @@ function useFocusTrap(ref, active) {
|
|
|
2171
2234
|
|
|
2172
2235
|
// src/react/components/EmergencyPanel/index.tsx
|
|
2173
2236
|
function EmergencyPanel(props) {
|
|
2174
|
-
const { open, theme, active, busy, aborting, loading, locale, responders, refreshing, geolocationError,
|
|
2237
|
+
const { open, theme, active, busy, aborting, loading, locale, responders, refreshing, geolocationError, activationError, error, abortResult, simulationResult, abortConfirmation, simulationConfirmation, onClose, onActivate, onRefresh, onRetry, onDismissFeedback, onRequestAbort, onRequestSimulation, onCancelAbort, onCancelSimulation, onConfirmAbort, onConfirmSimulation } = props;
|
|
2175
2238
|
const titleId = (0, react.useId)();
|
|
2176
2239
|
const dialogRef = (0, react.useRef)(null);
|
|
2240
|
+
const feedbackVisible = geolocationError !== null || Boolean(activationError) || abortResult !== null || simulationResult !== null;
|
|
2177
2241
|
const closeOnEscape = (0, react.useCallback)(() => {
|
|
2178
2242
|
onClose("escape");
|
|
2179
2243
|
}, [onClose]);
|
|
@@ -2204,8 +2268,8 @@ function EmergencyPanel(props) {
|
|
|
2204
2268
|
loading,
|
|
2205
2269
|
locale,
|
|
2206
2270
|
geolocationError,
|
|
2271
|
+
activationError,
|
|
2207
2272
|
error,
|
|
2208
|
-
fallback,
|
|
2209
2273
|
abortResult,
|
|
2210
2274
|
simulationResult,
|
|
2211
2275
|
onRefresh,
|
|
@@ -2217,6 +2281,7 @@ function EmergencyPanel(props) {
|
|
|
2217
2281
|
active,
|
|
2218
2282
|
busy,
|
|
2219
2283
|
aborting,
|
|
2284
|
+
feedbackVisible,
|
|
2220
2285
|
onActivate,
|
|
2221
2286
|
onRequestAbort,
|
|
2222
2287
|
onRequestSimulation
|
|
@@ -2320,7 +2385,9 @@ function EmergencyRoot() {
|
|
|
2320
2385
|
const simulationConfirmation = useEmergencyStore((state) => state.simulationConfirmation);
|
|
2321
2386
|
const active = snapshot?.active === true;
|
|
2322
2387
|
const busy = BUSY_PHASES.includes(phase.kind);
|
|
2323
|
-
const
|
|
2388
|
+
const feedbackActive = geolocationError !== null || abortResult !== null || simulationResult !== null;
|
|
2389
|
+
const activationError = phase.kind === "ready" && !feedbackActive ? lastError : null;
|
|
2390
|
+
const showError = phase.kind === "error" || lastError !== null && !feedbackActive && activationError === null;
|
|
2324
2391
|
const error = phase.kind === "error" ? phase.error : lastError;
|
|
2325
2392
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyResumeNotification, {
|
|
2326
2393
|
resumeAvailable,
|
|
@@ -2336,8 +2403,8 @@ function EmergencyRoot() {
|
|
|
2336
2403
|
responders,
|
|
2337
2404
|
refreshing: phase.kind === "refreshing",
|
|
2338
2405
|
geolocationError,
|
|
2406
|
+
activationError,
|
|
2339
2407
|
error: showError ? error : null,
|
|
2340
|
-
fallback: config.fallback ?? null,
|
|
2341
2408
|
abortResult,
|
|
2342
2409
|
simulationResult,
|
|
2343
2410
|
abortConfirmation,
|
|
@@ -2462,6 +2529,7 @@ function mount(options) {
|
|
|
2462
2529
|
const validation = validateConfig(options);
|
|
2463
2530
|
if (!validation.ok || !validation.config) return reportConfigurationError(validation.error ?? createEmergencyError("configuration", "Invalid emergency configuration."), options);
|
|
2464
2531
|
const config = validation.config;
|
|
2532
|
+
installEmergencyFonts(config.fontLoading);
|
|
2465
2533
|
const controller = createEmergencyController({ config });
|
|
2466
2534
|
const container = document.createElement("div");
|
|
2467
2535
|
container.setAttribute("data-de-emergency-container", "");
|