@dataemergencia/emergency 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -83,7 +83,7 @@ function isCurrentResponse(value) {
83
83
  return value["emergency"] === null || isRecord(value["emergency"]) && !Array.isArray(value["emergency"]);
84
84
  }
85
85
  function isRefreshResponse(value) {
86
- return isRecord(value) && isRecord(value["emergency"]) && isArrayOf(value["responders"], isResponderPayload);
86
+ return isRecord(value) && isRecord(value["emergency"]);
87
87
  }
88
88
  function isAbortResponse(value) {
89
89
  return isEmergencyResultPayload(value) && isRecord(value) && isBoolean(value["deleted"]);
@@ -407,19 +407,16 @@ const copy = {
407
407
  simulateSuccessDetails: "Mensajes enviados",
408
408
  simulateSuccessCompleted: "Proceso completado",
409
409
  feedbackDismiss: "Entendido",
410
- errorTitle: "Error",
410
+ errorTitle: "Ha ocurrido un error",
411
411
  errorText: "Ha ocurrido un error inesperado.",
412
412
  errorDetailInfo: "Revisa la información requerida",
413
413
  errorDetailRetry: "Intenta nuevamente",
414
414
  retry: "Reintentar",
415
415
  geolocationTitle: "No pudimos obtener tu ubicación",
416
- geolocationDenied: "Permiso de ubicación denegado. Activa el permiso o llama directamente.",
417
- geolocationUnavailable: "Tu ubicación no está disponible en este momento. Llama directamente.",
418
- geolocationTimeout: "La ubicación tardó demasiado. Inténtalo de nuevo o llama directamente.",
419
- geolocationUnsupported: "Este dispositivo no permite compartir la ubicación. Llama directamente.",
420
- fallbackTitle: "Llama directamente",
421
- fallbackDescription: "Si no puedes completar la emergencia desde aquí, llama a este número.",
422
- fallbackCall: "Llamar",
416
+ geolocationDenied: "Permiso de ubicación denegado. Habilita el acceso a la ubicación en tu navegador e inténtalo de nuevo.",
417
+ geolocationUnavailable: "Tu ubicación no está disponible en este momento. Verifica que el GPS esté activado e inténtalo de nuevo.",
418
+ geolocationTimeout: "La ubicación tardó demasiado. Muévete a un lugar con mejor señal e inténtalo de nuevo.",
419
+ geolocationUnsupported: "Este dispositivo no permite compartir la ubicación. Inténtalo desde otro navegador o dispositivo.",
423
420
  resumeTitle: "Emergencia Activa Detectada",
424
421
  resumeDescription: "Se ha detectado una emergencia activa en el sistema. Por favor, revisa el estado de la emergencia inmediatamente.",
425
422
  resumeAction: "Abrir Panel de Emergencia",
@@ -961,7 +958,6 @@ function createEmergencyController(deps) {
961
958
  geolocationError: normalized
962
959
  });
963
960
  transition({ kind: "ready" });
964
- pushMessage("error", normalized.message);
965
961
  events.emit("emergency:failed", {
966
962
  error: normalized,
967
963
  operation: "geolocation"
@@ -1069,7 +1065,7 @@ function createEmergencyController(deps) {
1069
1065
  code: config.code,
1070
1066
  simulated: snapshot.simulated
1071
1067
  });
1072
- const responders = result.responders.length > 0 ? result.responders.map(toResponder) : next.responders.length > 0 ? next.responders : get().responders;
1068
+ const responders = next.responders.length > 0 ? next.responders : get().responders;
1073
1069
  const updated = {
1074
1070
  ...next,
1075
1071
  responders
@@ -1265,16 +1261,87 @@ function createEmergencyController(deps) {
1265
1261
  if (!get().snapshot?.active) patch({ simulationConfirmation: true });
1266
1262
  },
1267
1263
  cancelSimulationConfirmation: () => patch({ simulationConfirmation: false }),
1268
- dismissFeedback: () => patch({
1269
- abortResult: null,
1270
- simulationResult: null
1271
- })
1264
+ dismissFeedback: () => {
1265
+ const state = get();
1266
+ patch({
1267
+ abortResult: null,
1268
+ simulationResult: null,
1269
+ geolocationError: null,
1270
+ ...state.geolocationError !== null || state.abortResult?.ok === false || state.simulationResult?.ok === false || state.phase.kind === "ready" && state.lastError !== null ? { lastError: null } : {}
1271
+ });
1272
+ }
1272
1273
  },
1273
1274
  store,
1274
1275
  events
1275
1276
  };
1276
1277
  }
1277
1278
 
1279
+ // src/core/fonts.ts
1280
+ /**
1281
+ * The exact Google Fonts query segment for each family. Family order matters:
1282
+ * with every family enabled the generated href is the documented stylesheet
1283
+ * URL, byte for byte.
1284
+ */
1285
+ const FONT_FAMILY_PARAMS = {
1286
+ googleSans: "family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700",
1287
+ montserrat: "family=Montserrat:ital,wght@0,100..900;1,100..900",
1288
+ 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"
1289
+ };
1290
+ const FONT_FAMILY_ORDER = [
1291
+ "googleSans",
1292
+ "montserrat",
1293
+ "poppins"
1294
+ ];
1295
+ const FONT_STYLESHEET_BASE = "https://fonts.googleapis.com/css2";
1296
+ const FONT_ORIGIN = "https://fonts.googleapis.com";
1297
+ const FONT_STATIC_ORIGIN = "https://fonts.gstatic.com";
1298
+ /** Marks every link the client injects so repeated mounts stay idempotent. */
1299
+ const FONT_LINK_ATTRIBUTE = "data-de-emergency-fonts";
1300
+ function normalizeFontLoading(input) {
1301
+ const flags = input?.fonts ?? {};
1302
+ return {
1303
+ load: input?.load ?? true,
1304
+ fonts: {
1305
+ googleSans: flags.googleSans ?? true,
1306
+ montserrat: flags.montserrat ?? true,
1307
+ poppins: flags.poppins ?? true
1308
+ }
1309
+ };
1310
+ }
1311
+ /**
1312
+ * Builds the stylesheet URL for the enabled families, or `null` when the
1313
+ * master switch is off or no family is enabled. A disabled family is left out
1314
+ * of the request entirely.
1315
+ */
1316
+ function buildFontStylesheetHref(input) {
1317
+ const { load, fonts } = normalizeFontLoading(input);
1318
+ if (!load) return null;
1319
+ const params = FONT_FAMILY_ORDER.filter((family) => fonts[family]).map((family) => FONT_FAMILY_PARAMS[family]);
1320
+ if (params.length === 0) return null;
1321
+ return `${FONT_STYLESHEET_BASE}?${params.join("&")}&display=swap`;
1322
+ }
1323
+ function createFontLink(rel, href, crossorigin = false) {
1324
+ const link = document.createElement("link");
1325
+ link.rel = rel;
1326
+ link.href = href;
1327
+ if (crossorigin) link.crossOrigin = "anonymous";
1328
+ link.setAttribute(FONT_LINK_ATTRIBUTE, "");
1329
+ return link;
1330
+ }
1331
+ /**
1332
+ * Injects the preconnect and stylesheet links the panel needs, once per page.
1333
+ * The first successful mount wins: later mounts, including mounts from a
1334
+ * duplicated copy of the library, reuse the links already present. The links
1335
+ * are page-level assets and are intentionally not removed on `destroy()`.
1336
+ */
1337
+ function installEmergencyFonts(input) {
1338
+ if (typeof document === "undefined") return;
1339
+ const href = buildFontStylesheetHref(input);
1340
+ if (href === null) return;
1341
+ if (document.querySelector(`link[${"data-de-emergency-fonts"}]`)) return;
1342
+ (document.head ?? document.documentElement).append(createFontLink("preconnect", FONT_ORIGIN), createFontLink("preconnect", FONT_STATIC_ORIGIN, true), createFontLink("stylesheet", href));
1343
+ }
1344
+
1278
1345
  // src/core/config.ts
1279
1346
  const EMERGENCY_CODE_PATTERN = /^[A-Za-z][A-Za-z0-9]{5}$/;
1280
1347
  const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
@@ -1346,44 +1413,85 @@ function validateConfig(config) {
1346
1413
  code,
1347
1414
  locale: config.locale ?? "es",
1348
1415
  geolocationTimeoutMs: config.geolocationTimeoutMs ?? 8e3,
1349
- requestTimeoutMs: config.requestTimeoutMs ?? 15e3
1416
+ requestTimeoutMs: config.requestTimeoutMs ?? 15e3,
1417
+ fontLoading: normalizeFontLoading(config.fontLoading)
1350
1418
  }
1351
1419
  };
1352
1420
  }
1353
1421
 
1354
- // src/styles/assets/paramedical-mark.tsx
1422
+ // src/react/components/icons/paramedical-mark.tsx
1355
1423
  /**
1356
1424
  * Neutral inline illustration used by the idle panel.
1357
1425
  */
1358
1426
  function ParamedicalMark({ className, title }) {
1359
1427
  return /* @__PURE__ */ jsxs("svg", {
1428
+ xmlns: "http://www.w3.org/2000/svg",
1429
+ version: "1.0",
1430
+ viewBox: "0 0 192 192",
1431
+ width: "192",
1432
+ height: "192",
1433
+ id: "Star of life",
1360
1434
  className,
1361
- viewBox: "0 0 96 96",
1362
- role: "img",
1363
1435
  "aria-label": title,
1364
- xmlns: "http://www.w3.org/2000/svg",
1365
1436
  children: [
1366
- /* @__PURE__ */ jsx("circle", {
1367
- cx: "48",
1368
- cy: "48",
1369
- r: "46",
1370
- fill: "#ff0000"
1371
- }),
1372
- /* @__PURE__ */ jsx("circle", {
1373
- cx: "48",
1374
- cy: "48",
1375
- r: "37",
1376
- fill: "#fff"
1437
+ /* @__PURE__ */ jsx("defs", { id: "defs2886" }),
1438
+ /* @__PURE__ */ jsxs("g", {
1439
+ id: "cross",
1440
+ children: [/* @__PURE__ */ jsx("path", {
1441
+ 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",
1442
+ id: "outline",
1443
+ style: {
1444
+ fill: "none",
1445
+ stroke: "#3333bb",
1446
+ strokeWidth: 6
1447
+ }
1448
+ }), /* @__PURE__ */ jsx("path", {
1449
+ 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",
1450
+ id: "inner",
1451
+ style: {
1452
+ fill: "#0000bb",
1453
+ fillRule: "evenodd",
1454
+ stroke: "#ffffff",
1455
+ strokeWidth: 2
1456
+ }
1457
+ })]
1377
1458
  }),
1378
- /* @__PURE__ */ jsx("path", {
1379
- d: "M42 26h12v16h16v12H54v16H42V54H26V42h16z",
1380
- fill: "#ff0000"
1459
+ /* @__PURE__ */ jsxs("g", {
1460
+ id: "symbols",
1461
+ style: {
1462
+ fill: "#ffffff",
1463
+ fillRule: "evenodd",
1464
+ stroke: "#3333bb",
1465
+ strokeWidth: 2
1466
+ },
1467
+ children: [/* @__PURE__ */ jsx("path", {
1468
+ 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",
1469
+ id: "rod"
1470
+ }), /* @__PURE__ */ jsxs("g", {
1471
+ id: "snake",
1472
+ children: [/* @__PURE__ */ jsx("path", {
1473
+ 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",
1474
+ id: "body"
1475
+ }), /* @__PURE__ */ jsx("path", {
1476
+ d: "m 95,43 c 7,-3 -7,-3 0,0 z",
1477
+ id: "eye",
1478
+ style: {
1479
+ fill: "#3333bb",
1480
+ fillRule: "evenodd",
1481
+ stroke: "none"
1482
+ }
1483
+ })]
1484
+ })]
1381
1485
  })
1382
1486
  ]
1383
1487
  });
1384
1488
  }
1385
1489
 
1386
1490
  // src/react/components/Icon/index.tsx
1491
+ /** Icons whose artwork does not fit the default 24x24 grid need their own canvas. */
1492
+ const viewBoxes = { emergency: "0 0 640 640" };
1493
+ /** Icons rendered as a solid shape instead of a stroked outline. */
1494
+ const filledIcons = /* @__PURE__ */ new Set(["emergency"]);
1387
1495
  const paths = {
1388
1496
  close: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M18 6L6 18" }),
1389
1497
  "alert-triangle": /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -1435,21 +1543,18 @@ const paths = {
1435
1543
  /* @__PURE__ */ jsx("path", { d: "M12 7h.01" })
1436
1544
  ] }),
1437
1545
  "arrow-left": /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M19 12H5" }), /* @__PURE__ */ jsx("path", { d: "m12 19-7-7 7-7" })] }),
1438
- emergency: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M12 2v6M12 16v6M2 12h6M16 12h6" }), /* @__PURE__ */ jsx("circle", {
1439
- cx: "12",
1440
- cy: "12",
1441
- r: "3"
1442
- })] })
1546
+ emergency: /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ 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" }) })
1443
1547
  };
1444
1548
  function Icon({ name, className, title }) {
1549
+ const stroked = !filledIcons.has(name);
1445
1550
  return /* @__PURE__ */ jsxs("svg", {
1446
1551
  className,
1447
- viewBox: "0 0 24 24",
1448
- width: "1em",
1449
- height: "1em",
1450
- fill: "none",
1451
- stroke: "currentColor",
1452
- strokeWidth: "2",
1552
+ viewBox: viewBoxes[name] ?? "0 0 24 24",
1553
+ width: "1rem",
1554
+ height: "1rem",
1555
+ fill: stroked ? "none" : "currentColor",
1556
+ stroke: stroked ? "currentColor" : "none",
1557
+ strokeWidth: stroked ? 2 : void 0,
1453
1558
  strokeLinecap: "round",
1454
1559
  strokeLinejoin: "round",
1455
1560
  "aria-hidden": title ? void 0 : "true",
@@ -1461,100 +1566,88 @@ function Icon({ name, className, title }) {
1461
1566
 
1462
1567
  // src/styles/panel.module.css
1463
1568
  var panel_module_default = {
1464
- "de-emergency-fade-in": "de-emergency-de-emergency-fade-in-kMlO0G",
1465
- "de-emergency-pulse": "de-emergency-de-emergency-pulse-kMlO0G",
1466
- "de-emergency-pulse-error": "de-emergency-de-emergency-pulse-error-kMlO0G",
1467
- "de-emergency-slide-in": "de-emergency-de-emergency-slide-in-kMlO0G",
1468
- "de-emergency-slide-up": "de-emergency-de-emergency-slide-up-kMlO0G",
1469
- "de-emergency-spin": "de-emergency-de-emergency-spin-kMlO0G",
1470
- "emergency-confirmation": "de-emergency-emergency-confirmation-kMlO0G",
1471
- "emergency-confirmation__actions": "de-emergency-emergency-confirmation__actions-kMlO0G",
1472
- "emergency-confirmation__button": "de-emergency-emergency-confirmation__button-kMlO0G",
1473
- "emergency-confirmation__button--cancel": "de-emergency-emergency-confirmation__button--cancel-kMlO0G",
1474
- "emergency-confirmation__button--confirm": "de-emergency-emergency-confirmation__button--confirm-kMlO0G",
1475
- "emergency-confirmation__button--danger": "de-emergency-emergency-confirmation__button--danger-kMlO0G",
1476
- "emergency-confirmation__card": "de-emergency-emergency-confirmation__card-kMlO0G",
1477
- "emergency-confirmation__card--danger": "de-emergency-emergency-confirmation__card--danger-kMlO0G",
1478
- "emergency-confirmation__icon": "de-emergency-emergency-confirmation__icon-kMlO0G",
1479
- "emergency-confirmation__text": "de-emergency-emergency-confirmation__text-kMlO0G",
1480
- "emergency-confirmation__title": "de-emergency-emergency-confirmation__title-kMlO0G",
1481
- "emergency-error-message": "de-emergency-emergency-error-message-kMlO0G",
1482
- "emergency-error-message__container": "de-emergency-emergency-error-message__container-kMlO0G",
1483
- "emergency-error-message__content": "de-emergency-emergency-error-message__content-kMlO0G",
1484
- "emergency-error-message__detail": "de-emergency-emergency-error-message__detail-kMlO0G",
1485
- "emergency-error-message__details": "de-emergency-emergency-error-message__details-kMlO0G",
1486
- "emergency-error-message__icon": "de-emergency-emergency-error-message__icon-kMlO0G",
1487
- "emergency-error-message__text": "de-emergency-emergency-error-message__text-kMlO0G",
1488
- "emergency-error-message__title": "de-emergency-emergency-error-message__title-kMlO0G",
1489
- "emergency-fallback": "de-emergency-emergency-fallback-kMlO0G",
1490
- "emergency-fallback__phone": "de-emergency-emergency-fallback__phone-kMlO0G",
1491
- "emergency-fallback__text": "de-emergency-emergency-fallback__text-kMlO0G",
1492
- "emergency-fallback__title": "de-emergency-emergency-fallback__title-kMlO0G",
1493
- "emergency-feedback": "de-emergency-emergency-feedback-kMlO0G",
1494
- "emergency-feedback__dismiss": "de-emergency-emergency-feedback__dismiss-kMlO0G",
1495
- "emergency-panel": "de-emergency-emergency-panel-kMlO0G",
1496
- "emergency-panel__body": "de-emergency-emergency-panel__body-kMlO0G",
1497
- "emergency-panel__body-title": "de-emergency-emergency-panel__body-title-kMlO0G",
1498
- "emergency-panel__body-title-container": "de-emergency-emergency-panel__body-title-container-kMlO0G",
1499
- "emergency-panel__button": "de-emergency-emergency-panel__button-kMlO0G",
1500
- "emergency-panel__button--emergency": "de-emergency-emergency-panel__button--emergency-kMlO0G",
1501
- "emergency-panel__button--simulation": "de-emergency-emergency-panel__button--simulation-kMlO0G",
1502
- "emergency-panel__close-button": "de-emergency-emergency-panel__close-button-kMlO0G",
1503
- "emergency-panel__close-icon": "de-emergency-emergency-panel__close-icon-kMlO0G",
1504
- "emergency-panel__footer": "de-emergency-emergency-panel__footer-kMlO0G",
1505
- "emergency-panel__header": "de-emergency-emergency-panel__header-kMlO0G",
1506
- "emergency-panel__title": "de-emergency-emergency-panel__title-kMlO0G",
1507
- "emergency-panel--hidden": "de-emergency-emergency-panel--hidden-kMlO0G",
1508
- "emergency-resume-notification-button": "de-emergency-emergency-resume-notification-button-kMlO0G",
1509
- "emergency-resume-notification-card": "de-emergency-emergency-resume-notification-card-kMlO0G",
1510
- "emergency-resume-notification-icon": "de-emergency-emergency-resume-notification-icon-kMlO0G",
1511
- "emergency-resume-notification-message": "de-emergency-emergency-resume-notification-message-kMlO0G",
1512
- "emergency-resume-notification-overlay": "de-emergency-emergency-resume-notification-overlay-kMlO0G",
1513
- "emergency-resume-notification-title": "de-emergency-emergency-resume-notification-title-kMlO0G",
1514
- "emergency-status__abort-btn": "de-emergency-emergency-status__abort-btn-kMlO0G",
1515
- "emergency-status__body": "de-emergency-emergency-status__body-kMlO0G",
1516
- "emergency-status__cell": "de-emergency-emergency-status__cell-kMlO0G",
1517
- "emergency-status__cell-icon": "de-emergency-emergency-status__cell-icon-kMlO0G",
1518
- "emergency-status__cell-text": "de-emergency-emergency-status__cell-text-kMlO0G",
1519
- "emergency-status__cell-time": "de-emergency-emergency-status__cell-time-kMlO0G",
1520
- "emergency-status__grid": "de-emergency-emergency-status__grid-kMlO0G",
1521
- "emergency-status__header": "de-emergency-emergency-status__header-kMlO0G",
1522
- "emergency-status__loading": "de-emergency-emergency-status__loading-kMlO0G",
1523
- "emergency-status__loading-text": "de-emergency-emergency-status__loading-text-kMlO0G",
1524
- "emergency-status__message-icon": "de-emergency-emergency-status__message-icon-kMlO0G",
1525
- "emergency-status__message-icon--failed": "de-emergency-emergency-status__message-icon--failed-kMlO0G",
1526
- "emergency-status__message-icon--success": "de-emergency-emergency-status__message-icon--success-kMlO0G",
1527
- "emergency-status__message-row": "de-emergency-emergency-status__message-row-kMlO0G",
1528
- "emergency-status__message-row--failed": "de-emergency-emergency-status__message-row--failed-kMlO0G",
1529
- "emergency-status__message-row--success": "de-emergency-emergency-status__message-row--success-kMlO0G",
1530
- "emergency-status__message-sent-at": "de-emergency-emergency-status__message-sent-at-kMlO0G",
1531
- "emergency-status__message-text": "de-emergency-emergency-status__message-text-kMlO0G",
1532
- "emergency-status__message-text-container": "de-emergency-emergency-status__message-text-container-kMlO0G",
1533
- "emergency-status__panel": "de-emergency-emergency-status__panel-kMlO0G",
1534
- "emergency-status__row": "de-emergency-emergency-status__row-kMlO0G",
1535
- "emergency-status__row-container": "de-emergency-emergency-status__row-container-kMlO0G",
1536
- "emergency-status__spinner": "de-emergency-emergency-status__spinner-kMlO0G",
1537
- "emergency-status-panel__header": "de-emergency-emergency-status-panel__header-kMlO0G",
1538
- "emergency-status-panel__refresh-btn": "de-emergency-emergency-status-panel__refresh-btn-kMlO0G",
1539
- "emergency-status-panel__refresh-btn-container": "de-emergency-emergency-status-panel__refresh-btn-container-kMlO0G",
1540
- "emergency-status-panel__refresh-icon": "de-emergency-emergency-status-panel__refresh-icon-kMlO0G",
1541
- "emergency-status-panel__title": "de-emergency-emergency-status-panel__title-kMlO0G",
1542
- "responder-name": "de-emergency-responder-name-kMlO0G",
1543
- "sent-at--verified": "de-emergency-sent-at--verified-kMlO0G",
1544
- "simulacrum-success-message": "de-emergency-simulacrum-success-message-kMlO0G",
1545
- "simulacrum-success-message__container": "de-emergency-simulacrum-success-message__container-kMlO0G",
1546
- "simulacrum-success-message__content": "de-emergency-simulacrum-success-message__content-kMlO0G",
1547
- "simulacrum-success-message__detail": "de-emergency-simulacrum-success-message__detail-kMlO0G",
1548
- "simulacrum-success-message__details": "de-emergency-simulacrum-success-message__details-kMlO0G",
1549
- "simulacrum-success-message__icon": "de-emergency-simulacrum-success-message__icon-kMlO0G",
1550
- "simulacrum-success-message__text": "de-emergency-simulacrum-success-message__text-kMlO0G",
1551
- "simulacrum-success-message__title": "de-emergency-simulacrum-success-message__title-kMlO0G",
1552
- "sos-img": "de-emergency-sos-img-kMlO0G",
1553
- "sos-img__container": "de-emergency-sos-img__container-kMlO0G",
1554
- "status-icon": "de-emergency-status-icon-kMlO0G",
1555
- "status-icon--checked": "de-emergency-status-icon--checked-kMlO0G",
1556
- "status-icon--failed": "de-emergency-status-icon--failed-kMlO0G",
1557
- "status-icon--unchecked": "de-emergency-status-icon--unchecked-kMlO0G"
1569
+ "de-emergency-fade-in": "de-emergency-de-emergency-fade-in-nA5Hwa",
1570
+ "de-emergency-pulse": "de-emergency-de-emergency-pulse-nA5Hwa",
1571
+ "de-emergency-pulse-error": "de-emergency-de-emergency-pulse-error-nA5Hwa",
1572
+ "de-emergency-slide-in": "de-emergency-de-emergency-slide-in-nA5Hwa",
1573
+ "de-emergency-slide-up": "de-emergency-de-emergency-slide-up-nA5Hwa",
1574
+ "de-emergency-spin": "de-emergency-de-emergency-spin-nA5Hwa",
1575
+ "emergency-confirmation": "de-emergency-emergency-confirmation-nA5Hwa",
1576
+ "emergency-confirmation__body": "de-emergency-emergency-confirmation__body-nA5Hwa",
1577
+ "emergency-confirmation__button": "de-emergency-emergency-confirmation__button-nA5Hwa",
1578
+ "emergency-confirmation__button--cancel": "de-emergency-emergency-confirmation__button--cancel-nA5Hwa",
1579
+ "emergency-confirmation__button--confirm": "de-emergency-emergency-confirmation__button--confirm-nA5Hwa",
1580
+ "emergency-confirmation__button--danger": "de-emergency-emergency-confirmation__button--danger-nA5Hwa",
1581
+ "emergency-confirmation__card": "de-emergency-emergency-confirmation__card-nA5Hwa",
1582
+ "emergency-confirmation__footer": "de-emergency-emergency-confirmation__footer-nA5Hwa",
1583
+ "emergency-confirmation__icon": "de-emergency-emergency-confirmation__icon-nA5Hwa",
1584
+ "emergency-confirmation__icon--danger": "de-emergency-emergency-confirmation__icon--danger-nA5Hwa",
1585
+ "emergency-confirmation__icon--information": "de-emergency-emergency-confirmation__icon--information-nA5Hwa",
1586
+ "emergency-confirmation__text": "de-emergency-emergency-confirmation__text-nA5Hwa",
1587
+ "emergency-confirmation__title": "de-emergency-emergency-confirmation__title-nA5Hwa",
1588
+ "emergency-error-message": "de-emergency-emergency-error-message-nA5Hwa",
1589
+ "emergency-error-message__container": "de-emergency-emergency-error-message__container-nA5Hwa",
1590
+ "emergency-error-message__content": "de-emergency-emergency-error-message__content-nA5Hwa",
1591
+ "emergency-error-message__detail": "de-emergency-emergency-error-message__detail-nA5Hwa",
1592
+ "emergency-error-message__details": "de-emergency-emergency-error-message__details-nA5Hwa",
1593
+ "emergency-error-message__icon": "de-emergency-emergency-error-message__icon-nA5Hwa",
1594
+ "emergency-error-message__text": "de-emergency-emergency-error-message__text-nA5Hwa",
1595
+ "emergency-error-message__title": "de-emergency-emergency-error-message__title-nA5Hwa",
1596
+ "emergency-feedback": "de-emergency-emergency-feedback-nA5Hwa",
1597
+ "emergency-feedback__dismiss": "de-emergency-emergency-feedback__dismiss-nA5Hwa",
1598
+ "emergency-panel": "de-emergency-emergency-panel-nA5Hwa",
1599
+ "emergency-panel__body": "de-emergency-emergency-panel__body-nA5Hwa",
1600
+ "emergency-panel__body-title": "de-emergency-emergency-panel__body-title-nA5Hwa",
1601
+ "emergency-panel__body-title-container": "de-emergency-emergency-panel__body-title-container-nA5Hwa",
1602
+ "emergency-panel__button": "de-emergency-emergency-panel__button-nA5Hwa",
1603
+ "emergency-panel__button--emergency": "de-emergency-emergency-panel__button--emergency-nA5Hwa",
1604
+ "emergency-panel__button--simulation": "de-emergency-emergency-panel__button--simulation-nA5Hwa",
1605
+ "emergency-panel__close-button": "de-emergency-emergency-panel__close-button-nA5Hwa",
1606
+ "emergency-panel__close-icon": "de-emergency-emergency-panel__close-icon-nA5Hwa",
1607
+ "emergency-panel__footer": "de-emergency-emergency-panel__footer-nA5Hwa",
1608
+ "emergency-panel__header": "de-emergency-emergency-panel__header-nA5Hwa",
1609
+ "emergency-panel__title": "de-emergency-emergency-panel__title-nA5Hwa",
1610
+ "emergency-panel--hidden": "de-emergency-emergency-panel--hidden-nA5Hwa",
1611
+ "emergency-resume-notification-button": "de-emergency-emergency-resume-notification-button-nA5Hwa",
1612
+ "emergency-resume-notification-card": "de-emergency-emergency-resume-notification-card-nA5Hwa",
1613
+ "emergency-resume-notification-icon": "de-emergency-emergency-resume-notification-icon-nA5Hwa",
1614
+ "emergency-resume-notification-message": "de-emergency-emergency-resume-notification-message-nA5Hwa",
1615
+ "emergency-resume-notification-overlay": "de-emergency-emergency-resume-notification-overlay-nA5Hwa",
1616
+ "emergency-resume-notification-title": "de-emergency-emergency-resume-notification-title-nA5Hwa",
1617
+ "emergency-status__abort-btn": "de-emergency-emergency-status__abort-btn-nA5Hwa",
1618
+ "emergency-status__body": "de-emergency-emergency-status__body-nA5Hwa",
1619
+ "emergency-status__cell": "de-emergency-emergency-status__cell-nA5Hwa",
1620
+ "emergency-status__cell-icon": "de-emergency-emergency-status__cell-icon-nA5Hwa",
1621
+ "emergency-status__cell-text": "de-emergency-emergency-status__cell-text-nA5Hwa",
1622
+ "emergency-status__cell-time": "de-emergency-emergency-status__cell-time-nA5Hwa",
1623
+ "emergency-status__grid": "de-emergency-emergency-status__grid-nA5Hwa",
1624
+ "emergency-status__header": "de-emergency-emergency-status__header-nA5Hwa",
1625
+ "emergency-status__loading": "de-emergency-emergency-status__loading-nA5Hwa",
1626
+ "emergency-status__loading-text": "de-emergency-emergency-status__loading-text-nA5Hwa",
1627
+ "emergency-status__panel": "de-emergency-emergency-status__panel-nA5Hwa",
1628
+ "emergency-status__row": "de-emergency-emergency-status__row-nA5Hwa",
1629
+ "emergency-status__row-container": "de-emergency-emergency-status__row-container-nA5Hwa",
1630
+ "emergency-status__spinner": "de-emergency-emergency-status__spinner-nA5Hwa",
1631
+ "emergency-status-panel__header": "de-emergency-emergency-status-panel__header-nA5Hwa",
1632
+ "emergency-status-panel__refresh-btn": "de-emergency-emergency-status-panel__refresh-btn-nA5Hwa",
1633
+ "emergency-status-panel__refresh-btn-container": "de-emergency-emergency-status-panel__refresh-btn-container-nA5Hwa",
1634
+ "emergency-status-panel__refresh-icon": "de-emergency-emergency-status-panel__refresh-icon-nA5Hwa",
1635
+ "emergency-status-panel__title": "de-emergency-emergency-status-panel__title-nA5Hwa",
1636
+ "responder-name": "de-emergency-responder-name-nA5Hwa",
1637
+ "simulacrum-success-message": "de-emergency-simulacrum-success-message-nA5Hwa",
1638
+ "simulacrum-success-message__container": "de-emergency-simulacrum-success-message__container-nA5Hwa",
1639
+ "simulacrum-success-message__content": "de-emergency-simulacrum-success-message__content-nA5Hwa",
1640
+ "simulacrum-success-message__detail": "de-emergency-simulacrum-success-message__detail-nA5Hwa",
1641
+ "simulacrum-success-message__details": "de-emergency-simulacrum-success-message__details-nA5Hwa",
1642
+ "simulacrum-success-message__icon": "de-emergency-simulacrum-success-message__icon-nA5Hwa",
1643
+ "simulacrum-success-message__text": "de-emergency-simulacrum-success-message__text-nA5Hwa",
1644
+ "simulacrum-success-message__title": "de-emergency-simulacrum-success-message__title-nA5Hwa",
1645
+ "sos-img": "de-emergency-sos-img-nA5Hwa",
1646
+ "sos-img__container": "de-emergency-sos-img__container-nA5Hwa",
1647
+ "status-icon": "de-emergency-status-icon-nA5Hwa",
1648
+ "status-icon--checked": "de-emergency-status-icon--checked-nA5Hwa",
1649
+ "status-icon--failed": "de-emergency-status-icon--failed-nA5Hwa",
1650
+ "status-icon--unchecked": "de-emergency-status-icon--unchecked-nA5Hwa"
1558
1651
  };
1559
1652
 
1560
1653
  // src/react/classnames.ts
@@ -1579,7 +1672,10 @@ function MessageSurface(props) {
1579
1672
  className: cls(`${prefix}__container`),
1580
1673
  children: [/* @__PURE__ */ jsx("div", {
1581
1674
  className: cls(`${prefix}__icon`),
1582
- children: /* @__PURE__ */ jsx(Icon, { name: icon })
1675
+ children: /* @__PURE__ */ jsx(Icon, {
1676
+ name: icon,
1677
+ className: "status-icon"
1678
+ })
1583
1679
  }), /* @__PURE__ */ jsxs("div", {
1584
1680
  className: cls(`${prefix}__content`),
1585
1681
  children: [
@@ -1627,8 +1723,12 @@ function EmergencyError({ error, onRetry }) {
1627
1723
  });
1628
1724
  }
1629
1725
 
1630
- // src/react/components/EmergencyFallback/index.tsx
1631
- function errorCopy(error) {
1726
+ // src/react/components/EmergencyFeedback/index.tsx
1727
+ /** Time the feedback stays on screen before dismissing itself. */
1728
+ const FEEDBACK_AUTO_DISMISS_MS = 3e3;
1729
+ /** Time the geolocation feedback stays on screen before dismissing itself. */
1730
+ const GEOLOCATION_FEEDBACK_AUTO_DISMISS_MS = 5e3;
1731
+ function geolocationText(error) {
1632
1732
  switch (error.code) {
1633
1733
  case "geolocation_denied": return copy.geolocationDenied;
1634
1734
  case "geolocation_timeout": return copy.geolocationTimeout;
@@ -1636,34 +1736,35 @@ function errorCopy(error) {
1636
1736
  default: return copy.geolocationUnavailable;
1637
1737
  }
1638
1738
  }
1639
- function EmergencyFallback({ fallback, error }) {
1640
- return /* @__PURE__ */ jsxs("div", {
1641
- className: cls("emergency-fallback"),
1642
- children: [
1643
- /* @__PURE__ */ jsx("h4", {
1644
- className: cls("emergency-fallback__title"),
1645
- children: copy.fallbackTitle
1646
- }),
1647
- /* @__PURE__ */ jsx("p", {
1648
- className: cls("emergency-fallback__text"),
1649
- children: errorCopy(error)
1650
- }),
1651
- fallback ? /* @__PURE__ */ jsxs("a", {
1652
- className: cls("emergency-fallback__phone"),
1653
- href: `tel:${fallback.phone.replace(/[^\d+]/g, "")}`,
1654
- children: [/* @__PURE__ */ jsx(Icon, { name: "message" }), fallback.label]
1655
- }) : null
1656
- ]
1739
+ function EmergencyFeedback({ abortResult, simulationResult, geolocationError, activationError, onDismiss }) {
1740
+ const result = abortResult ?? simulationResult;
1741
+ const feedbackActivationError = result ? null : activationError ?? null;
1742
+ const feedbackGeolocationError = result || feedbackActivationError ? null : geolocationError;
1743
+ if (!result && !feedbackActivationError && !feedbackGeolocationError) return null;
1744
+ return /* @__PURE__ */ jsx(FeedbackSurface, {
1745
+ result,
1746
+ aborting: abortResult !== null,
1747
+ geolocationError: feedbackGeolocationError,
1748
+ activationError: feedbackActivationError,
1749
+ onDismiss
1657
1750
  });
1658
1751
  }
1659
-
1660
- // src/react/components/EmergencyFeedback/index.tsx
1661
- function EmergencyFeedback({ abortResult, simulationResult, onDismiss }) {
1662
- const result = abortResult ?? simulationResult;
1663
- if (!result) return null;
1664
- const aborting = abortResult !== null;
1665
- const success = result.ok;
1752
+ function FeedbackSurface({ result, aborting, geolocationError, activationError, onDismiss }) {
1753
+ const dismissRef = useRef(onDismiss);
1754
+ useEffect(() => {
1755
+ dismissRef.current = onDismiss;
1756
+ }, [onDismiss]);
1757
+ useEffect(() => {
1758
+ const timeout = setTimeout(() => dismissRef.current(), geolocationError || activationError ? GEOLOCATION_FEEDBACK_AUTO_DISMISS_MS : FEEDBACK_AUTO_DISMISS_MS);
1759
+ return () => clearTimeout(timeout);
1760
+ }, [
1761
+ result?.at,
1762
+ geolocationError,
1763
+ activationError
1764
+ ]);
1765
+ const success = result?.ok === true;
1666
1766
  const title = success ? aborting ? copy.abortSuccessTitle : copy.simulateSuccessTitle : copy.errorTitle;
1767
+ const text = success ? result?.message ?? "" : geolocationError ? geolocationText(geolocationError) : activationError ? activationError.message || copy.errorText : result?.message ?? copy.errorText;
1667
1768
  const details = success ? aborting ? [{
1668
1769
  icon: "message",
1669
1770
  text: copy.abortSuccessDetails
@@ -1684,7 +1785,7 @@ function EmergencyFeedback({ abortResult, simulationResult, onDismiss }) {
1684
1785
  variant: success ? "success" : "error",
1685
1786
  icon: success ? "check-circle" : "alert-triangle",
1686
1787
  title,
1687
- text: result.message,
1788
+ text,
1688
1789
  details,
1689
1790
  className: cls("emergency-feedback"),
1690
1791
  children: /* @__PURE__ */ jsx("button", {
@@ -1738,43 +1839,6 @@ function normalizePeriod(dayPeriod) {
1738
1839
  return /^a/i.test(dayPeriod) ? "am" : "";
1739
1840
  }
1740
1841
 
1741
- // src/react/components/EmergencyMessageRow/index.tsx
1742
- /**
1743
- * Renders one message row per responder.
1744
- */
1745
- function EmergencyMessageRow({ responder, locale }) {
1746
- const message = responder.lastMessage;
1747
- const hasContent = Boolean(message?.content);
1748
- const modifier = hasContent ? "emergency-status__message-row--success" : "emergency-status__message-row--failed";
1749
- const iconModifier = hasContent ? "emergency-status__message-icon--success" : "emergency-status__message-icon--failed";
1750
- return /* @__PURE__ */ jsxs("div", {
1751
- className: cls("emergency-status__message-row", modifier),
1752
- children: [/* @__PURE__ */ jsxs("p", {
1753
- className: cls("emergency-status__message-text-container"),
1754
- children: [/* @__PURE__ */ jsx(Icon, {
1755
- name: "flag",
1756
- className: cls("emergency-status__message-icon", iconModifier)
1757
- }), /* @__PURE__ */ jsxs("span", {
1758
- className: cls("emergency-status__message-text"),
1759
- children: [
1760
- /* @__PURE__ */ jsx("strong", { children: copy.statusPrefix }),
1761
- " ",
1762
- message?.content ?? ""
1763
- ]
1764
- })]
1765
- }), message ? /* @__PURE__ */ jsxs("p", {
1766
- className: cls("emergency-status__message-text-container", "sent-at--verified"),
1767
- children: [/* @__PURE__ */ jsx(Icon, {
1768
- name: "double-check",
1769
- className: cls("emergency-status__message-icon")
1770
- }), message.sentAt ? /* @__PURE__ */ jsx("span", {
1771
- className: cls("emergency-status__message-sent-at"),
1772
- children: formatShortTime(message.sentAt, locale)
1773
- }) : null]
1774
- }) : null]
1775
- });
1776
- }
1777
-
1778
1842
  // src/react/components/StatusIcon/index.tsx
1779
1843
  /**
1780
1844
  * Explicit responder state model:
@@ -1810,10 +1874,10 @@ function StatusCell({ confirmed, timestamp, failed = false, isFailedIcon = false
1810
1874
 
1811
1875
  // src/react/components/ResponderRow/index.tsx
1812
1876
  function ResponderRow({ responder, locale }) {
1813
- return /* @__PURE__ */ jsxs("div", {
1877
+ return /* @__PURE__ */ jsx("div", {
1814
1878
  className: cls("emergency-status__row-container"),
1815
1879
  "data-responder-id": responder.phone,
1816
- children: [/* @__PURE__ */ jsxs("div", {
1880
+ children: /* @__PURE__ */ jsxs("div", {
1817
1881
  className: cls("emergency-status__row"),
1818
1882
  children: [
1819
1883
  /* @__PURE__ */ jsx("div", {
@@ -1843,10 +1907,7 @@ function ResponderRow({ responder, locale }) {
1843
1907
  locale
1844
1908
  })
1845
1909
  ]
1846
- }), /* @__PURE__ */ jsx(EmergencyMessageRow, {
1847
- responder,
1848
- locale
1849
- })]
1910
+ })
1850
1911
  });
1851
1912
  }
1852
1913
 
@@ -1924,34 +1985,31 @@ function EmergencyStatusPanel({ responders, refreshing, locale, onRefresh }) {
1924
1985
 
1925
1986
  // src/react/components/EmergencyBody/index.tsx
1926
1987
  function EmergencyBody(props) {
1927
- const { active, responders, refreshing, loading, locale, geolocationError, error, fallback, abortResult, simulationResult, onRefresh, onRetry, onDismissFeedback } = props;
1988
+ const { active, responders, refreshing, loading, locale, geolocationError, activationError, error, abortResult, simulationResult, onRefresh, onRetry, onDismissFeedback } = props;
1989
+ const showingFeedback = geolocationError !== null || Boolean(activationError) || abortResult !== null || simulationResult !== null;
1928
1990
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1929
- /* @__PURE__ */ jsx("div", {
1991
+ !loading && !showingFeedback ? /* @__PURE__ */ jsx("div", {
1930
1992
  className: cls("sos-img__container"),
1931
1993
  id: "sos-img__container",
1932
1994
  children: /* @__PURE__ */ jsx(ParamedicalMark, {
1933
1995
  className: cls("sos-img"),
1934
1996
  title: copy.illustrationAlt
1935
1997
  })
1936
- }),
1937
- active ? null : /* @__PURE__ */ jsx("div", {
1998
+ }) : null,
1999
+ active || loading || showingFeedback ? null : /* @__PURE__ */ jsx("div", {
1938
2000
  className: cls("emergency-panel__body-title-container"),
1939
2001
  children: /* @__PURE__ */ jsx("h4", {
1940
2002
  className: cls("emergency-panel__body-title"),
1941
2003
  children: copy.question
1942
2004
  })
1943
2005
  }),
1944
- active ? /* @__PURE__ */ jsx(EmergencyStatusPanel, {
2006
+ active && !showingFeedback ? /* @__PURE__ */ jsx(EmergencyStatusPanel, {
1945
2007
  responders,
1946
2008
  refreshing,
1947
2009
  locale,
1948
2010
  onRefresh
1949
2011
  }) : null,
1950
2012
  loading ? /* @__PURE__ */ jsx(EmergencyLoading, {}) : null,
1951
- geolocationError ? /* @__PURE__ */ jsx(EmergencyFallback, {
1952
- fallback,
1953
- error: geolocationError
1954
- }) : null,
1955
2013
  error ? /* @__PURE__ */ jsx(EmergencyError, {
1956
2014
  error,
1957
2015
  onRetry
@@ -1959,6 +2017,8 @@ function EmergencyBody(props) {
1959
2017
  /* @__PURE__ */ jsx(EmergencyFeedback, {
1960
2018
  abortResult,
1961
2019
  simulationResult,
2020
+ geolocationError,
2021
+ activationError,
1962
2022
  onDismiss: onDismissFeedback
1963
2023
  })
1964
2024
  ] });
@@ -1977,6 +2037,7 @@ function EmergencyConfirmation(props) {
1977
2037
  if (!open) return null;
1978
2038
  const title = danger ? copy.abortConfirmTitle : copy.simulateConfirmTitle;
1979
2039
  const text = danger ? copy.abortConfirmText : copy.simulateConfirmText;
2040
+ const tone = danger ? "danger" : "information";
1980
2041
  return /* @__PURE__ */ jsx("div", {
1981
2042
  className: cls("emergency-confirmation"),
1982
2043
  role: "dialog",
@@ -1984,50 +2045,52 @@ function EmergencyConfirmation(props) {
1984
2045
  "aria-labelledby": titleId,
1985
2046
  children: /* @__PURE__ */ jsxs("div", {
1986
2047
  ref: cardRef,
1987
- className: cls("emergency-confirmation__card", danger && "emergency-confirmation__card--danger"),
1988
- children: [
1989
- /* @__PURE__ */ jsx("div", {
1990
- className: cls("emergency-confirmation__icon"),
1991
- children: /* @__PURE__ */ jsx(Icon, { name: danger ? "alert-triangle" : "info" })
1992
- }),
1993
- /* @__PURE__ */ jsx("h3", {
1994
- className: cls("emergency-confirmation__title"),
1995
- id: titleId,
1996
- children: title
1997
- }),
1998
- /* @__PURE__ */ jsx("p", {
1999
- className: cls("emergency-confirmation__text"),
2000
- children: text
2001
- }),
2002
- /* @__PURE__ */ jsxs("div", {
2003
- className: cls("emergency-confirmation__actions"),
2004
- children: [/* @__PURE__ */ jsx("button", {
2005
- type: "button",
2006
- className: cls("emergency-confirmation__button", "emergency-confirmation__button--cancel"),
2007
- onClick: danger ? onCancelAbort : onCancelSimulation,
2008
- children: danger ? copy.abortCancel : copy.simulateCancel
2009
- }), /* @__PURE__ */ jsx("button", {
2010
- type: "button",
2011
- className: cls("emergency-confirmation__button", danger ? "emergency-confirmation__button--danger" : "emergency-confirmation__button--confirm"),
2012
- onClick: danger ? onConfirmAbort : onConfirmSimulation,
2013
- children: danger ? copy.abortConfirm : copy.simulateConfirm
2014
- })]
2015
- })
2016
- ]
2048
+ className: cls("emergency-confirmation__card"),
2049
+ children: [/* @__PURE__ */ jsxs("div", {
2050
+ className: cls("emergency-confirmation__body"),
2051
+ children: [
2052
+ /* @__PURE__ */ jsx("div", {
2053
+ className: cls("emergency-confirmation__icon", `emergency-confirmation__icon--${tone}`),
2054
+ children: /* @__PURE__ */ jsx(Icon, { name: danger ? "alert-triangle" : "info" })
2055
+ }),
2056
+ /* @__PURE__ */ jsx("h5", {
2057
+ className: cls("emergency-confirmation__title"),
2058
+ id: titleId,
2059
+ children: title
2060
+ }),
2061
+ /* @__PURE__ */ jsx("p", {
2062
+ className: cls("emergency-confirmation__text"),
2063
+ children: text
2064
+ })
2065
+ ]
2066
+ }), /* @__PURE__ */ jsxs("div", {
2067
+ className: cls("emergency-confirmation__footer"),
2068
+ children: [/* @__PURE__ */ jsx("button", {
2069
+ type: "button",
2070
+ className: cls("emergency-confirmation__button", "emergency-confirmation__button--cancel"),
2071
+ onClick: danger ? onCancelAbort : onCancelSimulation,
2072
+ children: danger ? copy.abortCancel : copy.simulateCancel
2073
+ }), /* @__PURE__ */ jsx("button", {
2074
+ type: "button",
2075
+ className: cls("emergency-confirmation__button", danger ? "emergency-confirmation__button--danger" : "emergency-confirmation__button--confirm"),
2076
+ onClick: danger ? onConfirmAbort : onConfirmSimulation,
2077
+ children: danger ? copy.abortConfirm : copy.simulateConfirm
2078
+ })]
2079
+ })]
2017
2080
  })
2018
2081
  });
2019
2082
  }
2020
2083
 
2021
2084
  // src/react/components/EmergencyFooter/index.tsx
2022
2085
  function EmergencyFooter(props) {
2023
- const { active, busy, aborting, onActivate, onRequestAbort, onRequestSimulation } = props;
2086
+ const { active, busy, aborting, feedbackVisible, onActivate, onRequestAbort, onRequestSimulation } = props;
2024
2087
  if (active) return /* @__PURE__ */ jsx("footer", {
2025
2088
  className: cls("emergency-panel__footer"),
2026
2089
  children: /* @__PURE__ */ jsxs("button", {
2027
2090
  type: "button",
2028
2091
  className: cls("emergency-status__abort-btn"),
2029
2092
  "aria-label": copy.abort,
2030
- disabled: aborting,
2093
+ disabled: aborting || feedbackVisible,
2031
2094
  onClick: onRequestAbort,
2032
2095
  children: [copy.abort, /* @__PURE__ */ jsx(Icon, { name: "alert-triangle" })]
2033
2096
  })
@@ -2038,14 +2101,14 @@ function EmergencyFooter(props) {
2038
2101
  type: "button",
2039
2102
  className: cls("emergency-panel__button", "emergency-panel__button--emergency"),
2040
2103
  "aria-label": copy.emergencyAria,
2041
- disabled: busy,
2104
+ disabled: busy || feedbackVisible,
2042
2105
  onClick: onActivate,
2043
2106
  children: [copy.emergency, /* @__PURE__ */ jsx(Icon, { name: "emergency" })]
2044
2107
  }), /* @__PURE__ */ jsxs("button", {
2045
2108
  type: "button",
2046
2109
  className: cls("emergency-panel__button", "emergency-panel__button--simulation"),
2047
2110
  "aria-label": copy.testAria,
2048
- disabled: busy,
2111
+ disabled: busy || feedbackVisible,
2049
2112
  onClick: onRequestSimulation,
2050
2113
  children: [copy.test, /* @__PURE__ */ jsx(Icon, { name: "list-check" })]
2051
2114
  })]
@@ -2142,9 +2205,10 @@ function useFocusTrap(ref, active) {
2142
2205
 
2143
2206
  // src/react/components/EmergencyPanel/index.tsx
2144
2207
  function EmergencyPanel(props) {
2145
- const { open, theme, active, busy, aborting, loading, locale, responders, refreshing, geolocationError, error, fallback, abortResult, simulationResult, abortConfirmation, simulationConfirmation, onClose, onActivate, onRefresh, onRetry, onDismissFeedback, onRequestAbort, onRequestSimulation, onCancelAbort, onCancelSimulation, onConfirmAbort, onConfirmSimulation } = props;
2208
+ 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;
2146
2209
  const titleId = useId();
2147
2210
  const dialogRef = useRef(null);
2211
+ const feedbackVisible = geolocationError !== null || Boolean(activationError) || abortResult !== null || simulationResult !== null;
2148
2212
  const closeOnEscape = useCallback(() => {
2149
2213
  onClose("escape");
2150
2214
  }, [onClose]);
@@ -2175,8 +2239,8 @@ function EmergencyPanel(props) {
2175
2239
  loading,
2176
2240
  locale,
2177
2241
  geolocationError,
2242
+ activationError,
2178
2243
  error,
2179
- fallback,
2180
2244
  abortResult,
2181
2245
  simulationResult,
2182
2246
  onRefresh,
@@ -2188,6 +2252,7 @@ function EmergencyPanel(props) {
2188
2252
  active,
2189
2253
  busy,
2190
2254
  aborting,
2255
+ feedbackVisible,
2191
2256
  onActivate,
2192
2257
  onRequestAbort,
2193
2258
  onRequestSimulation
@@ -2291,7 +2356,9 @@ function EmergencyRoot() {
2291
2356
  const simulationConfirmation = useEmergencyStore((state) => state.simulationConfirmation);
2292
2357
  const active = snapshot?.active === true;
2293
2358
  const busy = BUSY_PHASES.includes(phase.kind);
2294
- const showError = phase.kind === "error" || lastError !== null && geolocationError === null && abortResult === null && simulationResult === null;
2359
+ const feedbackActive = geolocationError !== null || abortResult !== null || simulationResult !== null;
2360
+ const activationError = phase.kind === "ready" && !feedbackActive ? lastError : null;
2361
+ const showError = phase.kind === "error" || lastError !== null && !feedbackActive && activationError === null;
2295
2362
  const error = phase.kind === "error" ? phase.error : lastError;
2296
2363
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EmergencyResumeNotification, {
2297
2364
  resumeAvailable,
@@ -2307,8 +2374,8 @@ function EmergencyRoot() {
2307
2374
  responders,
2308
2375
  refreshing: phase.kind === "refreshing",
2309
2376
  geolocationError,
2377
+ activationError,
2310
2378
  error: showError ? error : null,
2311
- fallback: config.fallback ?? null,
2312
2379
  abortResult,
2313
2380
  simulationResult,
2314
2381
  abortConfirmation,
@@ -2433,6 +2500,7 @@ function mount(options) {
2433
2500
  const validation = validateConfig(options);
2434
2501
  if (!validation.ok || !validation.config) return reportConfigurationError(validation.error ?? createEmergencyError("configuration", "Invalid emergency configuration."), options);
2435
2502
  const config = validation.config;
2503
+ installEmergencyFonts(config.fontLoading);
2436
2504
  const controller = createEmergencyController({ config });
2437
2505
  const container = document.createElement("div");
2438
2506
  container.setAttribute("data-de-emergency-container", "");