@dataemergencia/emergency 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1576,6 +1576,12 @@ var panel_module_default = {
1576
1576
  "de-emergency-slide-in": "de-emergency-de-emergency-slide-in-nA5Hwa",
1577
1577
  "de-emergency-slide-up": "de-emergency-de-emergency-slide-up-nA5Hwa",
1578
1578
  "de-emergency-spin": "de-emergency-de-emergency-spin-nA5Hwa",
1579
+ "emergency-alert-row__badge": "de-emergency-emergency-alert-row__badge-nA5Hwa",
1580
+ "emergency-alert-row__button": "de-emergency-emergency-alert-row__button-nA5Hwa",
1581
+ "emergency-alert-row__stat": "de-emergency-emergency-alert-row__stat-nA5Hwa",
1582
+ "emergency-alert-row__stats": "de-emergency-emergency-alert-row__stats-nA5Hwa",
1583
+ "emergency-alert-row__time": "de-emergency-emergency-alert-row__time-nA5Hwa",
1584
+ "emergency-alert-row__top": "de-emergency-emergency-alert-row__top-nA5Hwa",
1579
1585
  "emergency-availability": "de-emergency-emergency-availability-nA5Hwa",
1580
1586
  "emergency-availability__card": "de-emergency-emergency-availability__card-nA5Hwa",
1581
1587
  "emergency-availability__card-body": "de-emergency-emergency-availability__card-body-nA5Hwa",
@@ -1599,6 +1605,19 @@ var panel_module_default = {
1599
1605
  "emergency-confirmation__icon--information": "de-emergency-emergency-confirmation__icon--information-nA5Hwa",
1600
1606
  "emergency-confirmation__text": "de-emergency-emergency-confirmation__text-nA5Hwa",
1601
1607
  "emergency-confirmation__title": "de-emergency-emergency-confirmation__title-nA5Hwa",
1608
+ "emergency-details": "de-emergency-emergency-details-nA5Hwa",
1609
+ "emergency-details__balance": "de-emergency-emergency-details__balance-nA5Hwa",
1610
+ "emergency-details__card": "de-emergency-emergency-details__card-nA5Hwa",
1611
+ "emergency-details__card-body": "de-emergency-emergency-details__card-body-nA5Hwa",
1612
+ "emergency-details__card-header": "de-emergency-emergency-details__card-header-nA5Hwa",
1613
+ "emergency-details__card-title": "de-emergency-emergency-details__card-title-nA5Hwa",
1614
+ "emergency-details__empty": "de-emergency-emergency-details__empty-nA5Hwa",
1615
+ "emergency-details__heading": "de-emergency-emergency-details__heading-nA5Hwa",
1616
+ "emergency-details__history-button": "de-emergency-emergency-details__history-button-nA5Hwa",
1617
+ "emergency-details__list": "de-emergency-emergency-details__list-nA5Hwa",
1618
+ "emergency-details__section": "de-emergency-emergency-details__section-nA5Hwa",
1619
+ "emergency-details__subtitle": "de-emergency-emergency-details__subtitle-nA5Hwa",
1620
+ "emergency-details__title": "de-emergency-emergency-details__title-nA5Hwa",
1602
1621
  "emergency-error-message": "de-emergency-emergency-error-message-nA5Hwa",
1603
1622
  "emergency-error-message__container": "de-emergency-emergency-error-message__container-nA5Hwa",
1604
1623
  "emergency-error-message__content": "de-emergency-emergency-error-message__content-nA5Hwa",
@@ -1609,11 +1628,33 @@ var panel_module_default = {
1609
1628
  "emergency-error-message__title": "de-emergency-emergency-error-message__title-nA5Hwa",
1610
1629
  "emergency-feedback": "de-emergency-emergency-feedback-nA5Hwa",
1611
1630
  "emergency-feedback__dismiss": "de-emergency-emergency-feedback__dismiss-nA5Hwa",
1631
+ "emergency-history": "de-emergency-emergency-history-nA5Hwa",
1632
+ "emergency-history__empty": "de-emergency-emergency-history__empty-nA5Hwa",
1633
+ "emergency-history__heading": "de-emergency-emergency-history__heading-nA5Hwa",
1634
+ "emergency-history__list": "de-emergency-emergency-history__list-nA5Hwa",
1635
+ "emergency-history__more": "de-emergency-emergency-history__more-nA5Hwa",
1636
+ "emergency-history__subtitle": "de-emergency-emergency-history__subtitle-nA5Hwa",
1637
+ "emergency-history__title": "de-emergency-emergency-history__title-nA5Hwa",
1638
+ "emergency-message-detail": "de-emergency-emergency-message-detail-nA5Hwa",
1639
+ "emergency-message-detail__back": "de-emergency-emergency-message-detail__back-nA5Hwa",
1640
+ "emergency-message-detail__card": "de-emergency-emergency-message-detail__card-nA5Hwa",
1641
+ "emergency-message-detail__card-header": "de-emergency-emergency-message-detail__card-header-nA5Hwa",
1642
+ "emergency-message-detail__card-title": "de-emergency-emergency-message-detail__card-title-nA5Hwa",
1643
+ "emergency-message-detail__empty": "de-emergency-emergency-message-detail__empty-nA5Hwa",
1644
+ "emergency-message-detail__empty-text": "de-emergency-emergency-message-detail__empty-text-nA5Hwa",
1645
+ "emergency-message-detail__label": "de-emergency-emergency-message-detail__label-nA5Hwa",
1646
+ "emergency-message-detail__list": "de-emergency-emergency-message-detail__list-nA5Hwa",
1647
+ "emergency-message-detail__row": "de-emergency-emergency-message-detail__row-nA5Hwa",
1648
+ "emergency-message-detail__value": "de-emergency-emergency-message-detail__value-nA5Hwa",
1612
1649
  "emergency-panel": "de-emergency-emergency-panel-nA5Hwa",
1613
1650
  "emergency-panel__availability-region": "de-emergency-emergency-panel__availability-region-nA5Hwa",
1614
1651
  "emergency-panel__body": "de-emergency-emergency-panel__body-nA5Hwa",
1652
+ "emergency-panel__body--details": "de-emergency-emergency-panel__body--details-nA5Hwa",
1653
+ "emergency-panel__body--history": "de-emergency-emergency-panel__body--history-nA5Hwa",
1654
+ "emergency-panel__body--message-detail": "de-emergency-emergency-panel__body--message-detail-nA5Hwa",
1615
1655
  "emergency-panel__body--pre-emergency": "de-emergency-emergency-panel__body--pre-emergency-nA5Hwa",
1616
1656
  "emergency-panel__body--pricing": "de-emergency-emergency-panel__body--pricing-nA5Hwa",
1657
+ "emergency-panel__body--primary": "de-emergency-emergency-panel__body--primary-nA5Hwa",
1617
1658
  "emergency-panel__body-split": "de-emergency-emergency-panel__body-split-nA5Hwa",
1618
1659
  "emergency-panel__body-split--with-availability": "de-emergency-emergency-panel__body-split--with-availability-nA5Hwa",
1619
1660
  "emergency-panel__body-title": "de-emergency-emergency-panel__body-title-nA5Hwa",
@@ -1622,13 +1663,14 @@ var panel_module_default = {
1622
1663
  "emergency-panel__button--emergency": "de-emergency-emergency-panel__button--emergency-nA5Hwa",
1623
1664
  "emergency-panel__button--simulation": "de-emergency-emergency-panel__button--simulation-nA5Hwa",
1624
1665
  "emergency-panel__close-button": "de-emergency-emergency-panel__close-button-nA5Hwa",
1666
+ "emergency-panel__close-button--prompt": "de-emergency-emergency-panel__close-button--prompt-nA5Hwa",
1625
1667
  "emergency-panel__close-icon": "de-emergency-emergency-panel__close-icon-nA5Hwa",
1626
- "emergency-panel__divider": "de-emergency-emergency-panel__divider-nA5Hwa",
1627
1668
  "emergency-panel__footer": "de-emergency-emergency-panel__footer-nA5Hwa",
1628
1669
  "emergency-panel__footer--single": "de-emergency-emergency-panel__footer--single-nA5Hwa",
1670
+ "emergency-panel__footer--square": "de-emergency-emergency-panel__footer--square-nA5Hwa",
1629
1671
  "emergency-panel__header": "de-emergency-emergency-panel__header-nA5Hwa",
1630
- "emergency-panel__header--close-only": "de-emergency-emergency-panel__header--close-only-nA5Hwa",
1631
1672
  "emergency-panel__prompt-region": "de-emergency-emergency-panel__prompt-region-nA5Hwa",
1673
+ "emergency-panel__prompt-region--idle": "de-emergency-emergency-panel__prompt-region--idle-nA5Hwa",
1632
1674
  "emergency-panel__sr-only": "de-emergency-emergency-panel__sr-only-nA5Hwa",
1633
1675
  "emergency-panel__title": "de-emergency-emergency-panel__title-nA5Hwa",
1634
1676
  "emergency-panel--hidden": "de-emergency-emergency-panel--hidden-nA5Hwa",
@@ -1847,18 +1889,27 @@ function useFocusTrap(ref, active) {
1847
1889
  }
1848
1890
 
1849
1891
  // src/react/screens/context.tsx
1892
+ const EMPTY_PARAMS = {};
1850
1893
  const EmergencyScreenContext = (0, react.createContext)(null);
1894
+ function paramsEqual(first, second) {
1895
+ return first.messageId === second.messageId;
1896
+ }
1851
1897
  function EmergencyScreenProvider({ children, initialScreen = "primary" }) {
1852
1898
  const [state, setState] = (0, react.useState)({
1853
1899
  screen: initialScreen,
1900
+ params: EMPTY_PARAMS,
1854
1901
  history: []
1855
1902
  });
1856
- const navigate = (0, react.useCallback)((next) => {
1903
+ const navigate = (0, react.useCallback)((next, params = EMPTY_PARAMS) => {
1857
1904
  setState((current) => {
1858
- if (current.screen === next) return current;
1905
+ if (current.screen === next && paramsEqual(current.params, params)) return current;
1859
1906
  return {
1860
1907
  screen: next,
1861
- history: [...current.history, current.screen]
1908
+ params,
1909
+ history: [...current.history, {
1910
+ screen: current.screen,
1911
+ params: current.params
1912
+ }]
1862
1913
  };
1863
1914
  });
1864
1915
  }, []);
@@ -1867,31 +1918,47 @@ function EmergencyScreenProvider({ children, initialScreen = "primary" }) {
1867
1918
  const previous = current.history.at(-1);
1868
1919
  if (!previous) return current;
1869
1920
  return {
1870
- screen: previous,
1921
+ screen: previous.screen,
1922
+ params: previous.params,
1871
1923
  history: current.history.slice(0, -1)
1872
1924
  };
1873
1925
  });
1874
1926
  }, []);
1927
+ const replace = (0, react.useCallback)((next, params = EMPTY_PARAMS) => {
1928
+ setState((current) => {
1929
+ if (current.screen === next && paramsEqual(current.params, params)) return current;
1930
+ return {
1931
+ screen: next,
1932
+ params,
1933
+ history: current.history.at(-1)?.screen === next ? current.history.slice(0, -1) : current.history
1934
+ };
1935
+ });
1936
+ }, []);
1875
1937
  const reset = (0, react.useCallback)(() => {
1876
1938
  setState((current) => {
1877
- if (current.screen === "primary" && current.history.length === 0) return current;
1939
+ if (current.screen === "primary" && current.params.messageId === void 0 && current.history.length === 0) return current;
1878
1940
  return {
1879
1941
  screen: "primary",
1942
+ params: EMPTY_PARAMS,
1880
1943
  history: []
1881
1944
  };
1882
1945
  });
1883
1946
  }, []);
1884
1947
  const value = (0, react.useMemo)(() => ({
1885
1948
  screen: state.screen,
1949
+ params: state.params,
1886
1950
  history: state.history,
1887
1951
  navigate,
1952
+ replace,
1888
1953
  back,
1889
1954
  reset
1890
1955
  }), [
1891
1956
  back,
1892
1957
  navigate,
1958
+ replace,
1893
1959
  reset,
1894
1960
  state.history,
1961
+ state.params,
1895
1962
  state.screen
1896
1963
  ]);
1897
1964
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenContext.Provider, {
@@ -1906,12 +1973,11 @@ function useScreenNavigation() {
1906
1973
  }
1907
1974
 
1908
1975
  // src/react/components/EmergencyHeader/index.tsx
1909
- function EmergencyHeader({ titleId, onClose, title = copy.panelLabel, onBack, variant = "default" }) {
1910
- const closeOnly = variant === "close-only";
1976
+ function EmergencyHeader({ titleId, onClose, title = copy.panelLabel, onBack }) {
1911
1977
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
1912
- className: cls("emergency-panel__header", closeOnly && "emergency-panel__header--close-only"),
1978
+ className: cls("emergency-panel__header"),
1913
1979
  children: [
1914
- onBack && !closeOnly ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1980
+ onBack ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1915
1981
  type: "button",
1916
1982
  className: cls("emergency-panel__close-button"),
1917
1983
  "aria-label": copy.back,
@@ -1922,7 +1988,7 @@ function EmergencyHeader({ titleId, onClose, title = copy.panelLabel, onBack, va
1922
1988
  })
1923
1989
  }) : null,
1924
1990
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
1925
- className: cls("emergency-panel__title", closeOnly && "emergency-panel__sr-only"),
1991
+ className: cls("emergency-panel__title"),
1926
1992
  id: titleId,
1927
1993
  tabIndex: -1,
1928
1994
  children: title
@@ -1941,6 +2007,245 @@ function EmergencyHeader({ titleId, onClose, title = copy.panelLabel, onBack, va
1941
2007
  });
1942
2008
  }
1943
2009
 
2010
+ // src/react/screens/primary/data.ts
2011
+ /**
2012
+ * Derives the remaining alert rounds from available messages and designated
2013
+ * responders. Invalid or non-positive input collapses to the minimum of one
2014
+ * round instead of producing `Infinity`, `NaN` or a negative value.
2015
+ */
2016
+ function calculateRounds(messages, responders) {
2017
+ if (!Number.isFinite(messages) || !Number.isFinite(responders)) return 1;
2018
+ const availableMessages = Math.floor(messages);
2019
+ const designatedResponders = Math.floor(responders);
2020
+ if (availableMessages <= 0 || designatedResponders <= 0) return 1;
2021
+ return Math.max(1, Math.floor(availableMessages / designatedResponders));
2022
+ }
2023
+
2024
+ // src/react/screens/details/copy.ts
2025
+ const detailsCopy = {
2026
+ title: "Detalles",
2027
+ summaryTitle: "Alertas Disponibles",
2028
+ historyTitle: "Historial de alertas",
2029
+ historySubtitle: "Tus últimas alertas y recargas.",
2030
+ historyEmpty: "Todavía no tienes alertas en tu historial.",
2031
+ summaryEmpty: "Todavía no tienes un saldo de alertas disponible.",
2032
+ viewHistory: "Ver historial",
2033
+ messagesSingular: "mensaje de alerta",
2034
+ messagesPlural: "mensajes de alerta",
2035
+ contactsSingular: "contacto de emergencia",
2036
+ contactsPlural: "contactos de emergencia",
2037
+ roundsSingular: "ronda de avisos",
2038
+ roundsPlural: "rondas de avisos"
2039
+ };
2040
+ /** Returns the balance sentence split into text and emphasized number parts. */
2041
+ function alertBalanceParts(messages, responders) {
2042
+ if (!Number.isFinite(messages) || !Number.isFinite(responders) || messages < 0 || responders < 0) return [];
2043
+ const rounds = calculateRounds(messages, responders);
2044
+ const messagesUnit = messages === 1 ? detailsCopy.messagesSingular : detailsCopy.messagesPlural;
2045
+ const contactsUnit = responders === 1 ? detailsCopy.contactsSingular : detailsCopy.contactsPlural;
2046
+ const roundsUnit = rounds === 1 ? detailsCopy.roundsSingular : detailsCopy.roundsPlural;
2047
+ return [
2048
+ messages === 1 ? "Te queda " : "Te quedan ",
2049
+ messages,
2050
+ ` ${messagesUnit}, dado que tienes `,
2051
+ responders,
2052
+ ` ${contactsUnit}, `,
2053
+ rounds === 1 ? "te queda " : "te quedan ",
2054
+ rounds,
2055
+ ` ${roundsUnit}.`
2056
+ ];
2057
+ }
2058
+
2059
+ // src/react/screens/details/AlertBalanceSentence.tsx
2060
+ /** Renders the balance sentence with its numbers visually emphasized. */
2061
+ function AlertBalanceSentence({ messages, responders }) {
2062
+ const parts = alertBalanceParts(messages, responders);
2063
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: parts.map((part, index) => typeof part === "number" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: part }, index) : part) });
2064
+ }
2065
+
2066
+ // src/core/date.ts
2067
+ /**
2068
+ * Formats a timestamp as `h:mmam` or `h:mmpm` in local time, without a space
2069
+ * or leading zero.
2070
+ */
2071
+ function formatShortTime(value, locale = "es") {
2072
+ if (value === null) return "";
2073
+ const date = value instanceof Date ? value : new Date(value);
2074
+ if (Number.isNaN(date.getTime())) return "";
2075
+ const parts = new Intl.DateTimeFormat(locale, {
2076
+ hour: "numeric",
2077
+ minute: "2-digit",
2078
+ hour12: true
2079
+ }).formatToParts(date);
2080
+ const hour = parts.find((part) => part.type === "hour")?.value;
2081
+ const minute = parts.find((part) => part.type === "minute")?.value;
2082
+ const dayPeriod = parts.find((part) => part.type === "dayPeriod")?.value;
2083
+ if (!hour || !minute) return "";
2084
+ return `${hour}:${minute}${normalizePeriod(dayPeriod)}`;
2085
+ }
2086
+ /**
2087
+ * Formats a timestamp as `dd/mm/yyyy hh:mm` in local time, using 24-hour time
2088
+ * and zero-padded parts. Missing or invalid input collapses to an empty string.
2089
+ */
2090
+ function formatDateTime(value, locale = "es") {
2091
+ if (value === null) return "";
2092
+ const date = value instanceof Date ? value : new Date(value);
2093
+ if (Number.isNaN(date.getTime())) return "";
2094
+ const parts = new Intl.DateTimeFormat(locale, {
2095
+ day: "2-digit",
2096
+ month: "2-digit",
2097
+ year: "numeric",
2098
+ hour: "2-digit",
2099
+ minute: "2-digit",
2100
+ hourCycle: "h23"
2101
+ }).formatToParts(date);
2102
+ const day = parts.find((part) => part.type === "day")?.value;
2103
+ const month = parts.find((part) => part.type === "month")?.value;
2104
+ const year = parts.find((part) => part.type === "year")?.value;
2105
+ const hour = parts.find((part) => part.type === "hour")?.value;
2106
+ const minute = parts.find((part) => part.type === "minute")?.value;
2107
+ if (!day || !month || !year || !hour || !minute) return "";
2108
+ return `${day}/${month}/${year} ${hour}:${minute}`;
2109
+ }
2110
+ function normalizePeriod(dayPeriod) {
2111
+ if (!dayPeriod) return "";
2112
+ if (/^p/i.test(dayPeriod)) return "pm";
2113
+ return /^a/i.test(dayPeriod) ? "am" : "";
2114
+ }
2115
+
2116
+ // src/react/screens/history/copy.ts
2117
+ const historyCopy = {
2118
+ title: "Historial de alertas",
2119
+ subtitle: "Consulta tus alertas, pruebas y recargas.",
2120
+ empty: "Todavía no tienes alertas en tu historial.",
2121
+ showMore: "Ver más",
2122
+ kindLabels: {
2123
+ emergency: "Emergencia",
2124
+ test: "Prueba",
2125
+ recharge: "Recarga"
2126
+ }
2127
+ };
2128
+ function formatContacts(count) {
2129
+ return count === 1 ? "1 contacto" : `${count} contactos`;
2130
+ }
2131
+ function formatMessages(count) {
2132
+ return count === 1 ? "1 mensaje" : `${count} mensajes`;
2133
+ }
2134
+ function formatHistoryRounds(count) {
2135
+ return count === 1 ? "1 ronda" : `${count} rondas`;
2136
+ }
2137
+
2138
+ // src/react/screens/history/data.ts
2139
+ /** Local demo alert history, newest first. */
2140
+ const DEMO_ALERT_HISTORY = [
2141
+ {
2142
+ id: "alert-2026-10-31",
2143
+ kind: "emergency",
2144
+ occurredAt: "2026-10-31T13:50:00",
2145
+ responders: 3,
2146
+ remainingMessages: 27
2147
+ },
2148
+ {
2149
+ id: "alert-2026-10-20",
2150
+ kind: "recharge",
2151
+ occurredAt: "2026-10-20T09:15:00",
2152
+ responders: 3,
2153
+ remainingMessages: 100
2154
+ },
2155
+ {
2156
+ id: "alert-2026-10-12",
2157
+ kind: "test",
2158
+ occurredAt: "2026-10-12T18:40:00",
2159
+ responders: 3,
2160
+ remainingMessages: 73
2161
+ },
2162
+ {
2163
+ id: "alert-2026-10-01",
2164
+ kind: "recharge",
2165
+ occurredAt: "2026-10-01T11:05:00",
2166
+ responders: 3,
2167
+ remainingMessages: 76
2168
+ }
2169
+ ];
2170
+ /** Returns a newest-first copy of the history. */
2171
+ function sortedHistoryEntries(entries = DEMO_ALERT_HISTORY) {
2172
+ return [...entries].sort((first, second) => new Date(second.occurredAt).getTime() - new Date(first.occurredAt).getTime());
2173
+ }
2174
+ /** Newest entry, used as the source of the current balance. */
2175
+ function latestHistoryEntry(entries = DEMO_ALERT_HISTORY) {
2176
+ return sortedHistoryEntries(entries)[0] ?? null;
2177
+ }
2178
+ /** Resolves a single history entry by id. */
2179
+ function historyEntryById(id, entries = DEMO_ALERT_HISTORY) {
2180
+ if (!id) return null;
2181
+ return entries.find((entry) => entry.id === id) ?? null;
2182
+ }
2183
+ /** Rounds represented by the entry's remaining messages and responders. */
2184
+ function historyEntryRounds(entry) {
2185
+ return calculateRounds(entry.remainingMessages, entry.responders);
2186
+ }
2187
+ /** Current balance derived from the newest history entry. */
2188
+ function currentAlertBalance(entries = DEMO_ALERT_HISTORY) {
2189
+ const latest = latestHistoryEntry(entries);
2190
+ if (!latest) return null;
2191
+ return {
2192
+ messages: latest.remainingMessages,
2193
+ responders: latest.responders,
2194
+ rounds: historyEntryRounds(latest)
2195
+ };
2196
+ }
2197
+
2198
+ // src/react/screens/history/AlertHistoryRow.tsx
2199
+ /** Reusable history row. The whole row is a button with a full text label. */
2200
+ function AlertHistoryRow({ entry, locale, onOpen }) {
2201
+ const occurredAt = formatDateTime(entry.occurredAt, locale);
2202
+ const rounds = historyEntryRounds(entry);
2203
+ const label = [
2204
+ historyCopy.kindLabels[entry.kind],
2205
+ occurredAt,
2206
+ formatContacts(entry.responders),
2207
+ `${formatMessages(entry.remainingMessages)} restantes`,
2208
+ `${formatHistoryRounds(rounds)} de avisos`
2209
+ ].join(", ");
2210
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
2211
+ className: cls("emergency-alert-row"),
2212
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2213
+ type: "button",
2214
+ className: cls("emergency-alert-row__button"),
2215
+ "aria-label": label,
2216
+ onClick: () => onOpen(entry.id),
2217
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2218
+ className: cls("emergency-alert-row__top"),
2219
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
2220
+ className: cls("emergency-alert-row__time"),
2221
+ dateTime: entry.occurredAt,
2222
+ children: occurredAt
2223
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2224
+ className: cls("emergency-alert-row__badge"),
2225
+ "data-kind": entry.kind,
2226
+ children: historyCopy.kindLabels[entry.kind]
2227
+ })]
2228
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2229
+ className: cls("emergency-alert-row__stats"),
2230
+ children: [
2231
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2232
+ className: cls("emergency-alert-row__stat"),
2233
+ children: formatContacts(entry.responders)
2234
+ }),
2235
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2236
+ className: cls("emergency-alert-row__stat"),
2237
+ children: formatMessages(entry.remainingMessages)
2238
+ }),
2239
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2240
+ className: cls("emergency-alert-row__stat"),
2241
+ children: formatHistoryRounds(rounds)
2242
+ })
2243
+ ]
2244
+ })]
2245
+ })
2246
+ });
2247
+ }
2248
+
1944
2249
  // src/react/screens/layout.tsx
1945
2250
  /**
1946
2251
  * Shared shell for every screen. The wrapper is `display: contents` so the
@@ -1962,46 +2267,254 @@ function EmergencyScreenLayout({ screen, titleId, header, footer, children, body
1962
2267
  });
1963
2268
  }
1964
2269
 
1965
- // src/react/screens/PlaceholderScreen.tsx
1966
- /** Minimal in-design screen used to prove navigation before real designs land. */
1967
- function PlaceholderScreen({ screen, titleId, title, description, onClose, onBack }) {
2270
+ // src/react/screens/details/index.tsx
2271
+ function DetailsScreen({ titleId, locale, onClose }) {
2272
+ const { back, navigate } = useScreenNavigation();
2273
+ const balance = currentAlertBalance();
2274
+ const preview = sortedHistoryEntries().slice(0, 2);
1968
2275
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenLayout, {
1969
- screen,
2276
+ screen: "details",
1970
2277
  titleId,
2278
+ bodyClassName: "emergency-panel__body--details",
1971
2279
  header: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyHeader, {
1972
2280
  titleId,
1973
- title,
1974
- onClose,
1975
- onBack
2281
+ title: detailsCopy.title,
2282
+ onClose: () => onClose("close"),
2283
+ onBack: back
1976
2284
  }),
1977
2285
  footer: null,
1978
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1979
- className: cls("emergency-screen__placeholder"),
1980
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1981
- className: cls("emergency-screen__placeholder-text"),
1982
- children: description
1983
- })
2286
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2287
+ className: cls("emergency-details"),
2288
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
2289
+ className: cls("emergency-details__section"),
2290
+ "aria-label": detailsCopy.summaryTitle,
2291
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2292
+ className: cls("emergency-details__card"),
2293
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2294
+ className: cls("emergency-details__card-header"),
2295
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2296
+ className: cls("emergency-details__card-title"),
2297
+ children: detailsCopy.summaryTitle
2298
+ })
2299
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2300
+ className: cls("emergency-details__card-body"),
2301
+ children: balance ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2302
+ className: cls("emergency-details__balance"),
2303
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlertBalanceSentence, {
2304
+ messages: balance.messages,
2305
+ responders: balance.responders
2306
+ })
2307
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2308
+ className: cls("emergency-details__empty"),
2309
+ children: detailsCopy.summaryEmpty
2310
+ })
2311
+ })]
2312
+ })
2313
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2314
+ className: cls("emergency-details__section"),
2315
+ "aria-label": detailsCopy.historyTitle,
2316
+ children: [
2317
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2318
+ className: cls("emergency-details__heading"),
2319
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2320
+ className: cls("emergency-details__title"),
2321
+ children: detailsCopy.historyTitle
2322
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2323
+ className: cls("emergency-details__subtitle"),
2324
+ children: detailsCopy.historySubtitle
2325
+ })]
2326
+ }),
2327
+ preview.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2328
+ className: cls("emergency-details__list"),
2329
+ children: preview.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlertHistoryRow, {
2330
+ entry,
2331
+ locale,
2332
+ onOpen: (messageId) => navigate("message-detail", { messageId })
2333
+ }, entry.id))
2334
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2335
+ className: cls("emergency-details__empty"),
2336
+ children: detailsCopy.historyEmpty
2337
+ }),
2338
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2339
+ type: "button",
2340
+ className: cls("emergency-details__history-button"),
2341
+ onClick: () => navigate("history"),
2342
+ children: detailsCopy.viewHistory
2343
+ })
2344
+ ]
2345
+ })]
1984
2346
  })
1985
2347
  });
1986
2348
  }
1987
2349
 
1988
- // src/react/screens/details/copy.ts
1989
- const detailsCopy = {
1990
- title: "Detalles",
1991
- description: "Aquí podrás consultar el detalle de tus alertas disponibles. Esta pantalla estará disponible próximamente."
1992
- };
2350
+ // src/react/screens/history/index.tsx
2351
+ function HistoryScreen({ titleId, locale, onClose }) {
2352
+ const { back, navigate } = useScreenNavigation();
2353
+ const listId = (0, react.useId)();
2354
+ const [expanded, setExpanded] = (0, react.useState)(false);
2355
+ const entries = sortedHistoryEntries();
2356
+ const hiddenCount = Math.max(0, entries.length - 2);
2357
+ const visibleEntries = expanded ? entries : entries.slice(0, 2);
2358
+ const showMore = hiddenCount > 0 && !expanded;
2359
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenLayout, {
2360
+ screen: "history",
2361
+ titleId,
2362
+ bodyClassName: "emergency-panel__body--history",
2363
+ header: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyHeader, {
2364
+ titleId,
2365
+ title: historyCopy.title,
2366
+ onClose: () => onClose("close"),
2367
+ onBack: back
2368
+ }),
2369
+ footer: null,
2370
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2371
+ className: cls("emergency-history"),
2372
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2373
+ className: cls("emergency-history__heading"),
2374
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2375
+ className: cls("emergency-history__title"),
2376
+ children: historyCopy.title
2377
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2378
+ className: cls("emergency-history__subtitle"),
2379
+ children: historyCopy.subtitle
2380
+ })]
2381
+ }), entries.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2382
+ className: cls("emergency-history__list"),
2383
+ id: listId,
2384
+ children: visibleEntries.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlertHistoryRow, {
2385
+ entry,
2386
+ locale,
2387
+ onOpen: (messageId) => navigate("message-detail", { messageId })
2388
+ }, entry.id))
2389
+ }), showMore ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2390
+ type: "button",
2391
+ className: cls("emergency-history__more"),
2392
+ "aria-expanded": expanded,
2393
+ "aria-controls": listId,
2394
+ onClick: () => setExpanded(true),
2395
+ children: historyCopy.showMore
2396
+ }) : null] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2397
+ className: cls("emergency-history__empty"),
2398
+ children: historyCopy.empty
2399
+ })]
2400
+ })
2401
+ });
2402
+ }
1993
2403
 
1994
- // src/react/screens/details/index.tsx
1995
- function DetailsScreen({ titleId, onClose }) {
1996
- const { back } = useScreenNavigation();
1997
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PlaceholderScreen, {
1998
- screen: "details",
2404
+ // src/react/screens/message-detail/index.tsx
2405
+ const messageDetailCopy = {
2406
+ title: "Detalle del mensaje",
2407
+ dateTime: "Fecha y hora",
2408
+ kind: "Tipo",
2409
+ responders: "Contactos de emergencia",
2410
+ messages: "Mensajes restantes",
2411
+ rounds: "Rondas de avisos",
2412
+ notFound: "No encontramos este mensaje. Puede que ya no esté disponible en tu historial.",
2413
+ backToHistory: "Volver al historial"
2414
+ };
2415
+ function MessageDetailScreen({ titleId, locale, onClose }) {
2416
+ const { back, params, replace } = useScreenNavigation();
2417
+ const entry = historyEntryById(params.messageId);
2418
+ const header = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyHeader, {
1999
2419
  titleId,
2000
- title: detailsCopy.title,
2001
- description: detailsCopy.description,
2420
+ title: messageDetailCopy.title,
2002
2421
  onClose: () => onClose("close"),
2003
2422
  onBack: back
2004
2423
  });
2424
+ if (!entry) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenLayout, {
2425
+ screen: "message-detail",
2426
+ titleId,
2427
+ bodyClassName: "emergency-panel__body--message-detail",
2428
+ header,
2429
+ footer: null,
2430
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2431
+ className: cls("emergency-message-detail__empty"),
2432
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2433
+ className: cls("emergency-message-detail__empty-text"),
2434
+ children: messageDetailCopy.notFound
2435
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2436
+ type: "button",
2437
+ className: cls("emergency-message-detail__back"),
2438
+ onClick: () => replace("history"),
2439
+ children: messageDetailCopy.backToHistory
2440
+ })]
2441
+ })
2442
+ });
2443
+ const rounds = historyEntryRounds(entry);
2444
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenLayout, {
2445
+ screen: "message-detail",
2446
+ titleId,
2447
+ bodyClassName: "emergency-panel__body--message-detail",
2448
+ header,
2449
+ footer: null,
2450
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2451
+ className: cls("emergency-message-detail"),
2452
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2453
+ className: cls("emergency-message-detail__card"),
2454
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2455
+ className: cls("emergency-message-detail__card-header"),
2456
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
2457
+ className: cls("emergency-message-detail__card-title"),
2458
+ children: messageDetailCopy.title
2459
+ })
2460
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
2461
+ className: cls("emergency-message-detail__list"),
2462
+ children: [
2463
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2464
+ className: cls("emergency-message-detail__row"),
2465
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
2466
+ className: cls("emergency-message-detail__label"),
2467
+ children: messageDetailCopy.dateTime
2468
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
2469
+ className: cls("emergency-message-detail__value"),
2470
+ children: formatDateTime(entry.occurredAt, locale)
2471
+ })]
2472
+ }),
2473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2474
+ className: cls("emergency-message-detail__row"),
2475
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
2476
+ className: cls("emergency-message-detail__label"),
2477
+ children: messageDetailCopy.kind
2478
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
2479
+ className: cls("emergency-message-detail__value"),
2480
+ children: historyCopy.kindLabels[entry.kind]
2481
+ })]
2482
+ }),
2483
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2484
+ className: cls("emergency-message-detail__row"),
2485
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
2486
+ className: cls("emergency-message-detail__label"),
2487
+ children: messageDetailCopy.responders
2488
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
2489
+ className: cls("emergency-message-detail__value"),
2490
+ children: formatContacts(entry.responders)
2491
+ })]
2492
+ }),
2493
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2494
+ className: cls("emergency-message-detail__row"),
2495
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
2496
+ className: cls("emergency-message-detail__label"),
2497
+ children: messageDetailCopy.messages
2498
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
2499
+ className: cls("emergency-message-detail__value"),
2500
+ children: formatMessages(entry.remainingMessages)
2501
+ })]
2502
+ }),
2503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2504
+ className: cls("emergency-message-detail__row"),
2505
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
2506
+ className: cls("emergency-message-detail__label"),
2507
+ children: messageDetailCopy.rounds
2508
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
2509
+ className: cls("emergency-message-detail__value"),
2510
+ children: formatHistoryRounds(rounds)
2511
+ })]
2512
+ })
2513
+ ]
2514
+ })]
2515
+ })
2516
+ })
2517
+ });
2005
2518
  }
2006
2519
 
2007
2520
  // src/core/phone.ts
@@ -2026,9 +2539,9 @@ function toVenezuelanE164(input) {
2026
2539
 
2027
2540
  // src/react/components/EmergencyFooter/index.tsx
2028
2541
  function EmergencyFooter(props) {
2029
- const { active, busy, aborting, feedbackVisible, showSimulation = true, emergencyDisabled = false, onActivate, onRequestAbort, onRequestSimulation } = props;
2542
+ const { active, busy, aborting, feedbackVisible, showSimulation = true, emergencyDisabled = false, square = false, onActivate, onRequestAbort, onRequestSimulation } = props;
2030
2543
  if (active) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
2031
- className: cls("emergency-panel__footer"),
2544
+ className: cls("emergency-panel__footer", square && "emergency-panel__footer--square"),
2032
2545
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2033
2546
  type: "button",
2034
2547
  className: cls("emergency-status__abort-btn"),
@@ -2039,7 +2552,7 @@ function EmergencyFooter(props) {
2039
2552
  })
2040
2553
  });
2041
2554
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
2042
- className: cls("emergency-panel__footer", !showSimulation && "emergency-panel__footer--single"),
2555
+ className: cls("emergency-panel__footer", !showSimulation && "emergency-panel__footer--single", square && "emergency-panel__footer--square"),
2043
2556
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2044
2557
  type: "button",
2045
2558
  className: cls("emergency-panel__button", "emergency-panel__button--emergency"),
@@ -2402,32 +2915,6 @@ function EmergencyLoading() {
2402
2915
  });
2403
2916
  }
2404
2917
 
2405
- // src/core/date.ts
2406
- /**
2407
- * Formats a timestamp as `h:mmam` or `h:mmpm` in local time, without a space
2408
- * or leading zero.
2409
- */
2410
- function formatShortTime(value, locale = "es") {
2411
- if (value === null) return "";
2412
- const date = value instanceof Date ? value : new Date(value);
2413
- if (Number.isNaN(date.getTime())) return "";
2414
- const parts = new Intl.DateTimeFormat(locale, {
2415
- hour: "numeric",
2416
- minute: "2-digit",
2417
- hour12: true
2418
- }).formatToParts(date);
2419
- const hour = parts.find((part) => part.type === "hour")?.value;
2420
- const minute = parts.find((part) => part.type === "minute")?.value;
2421
- const dayPeriod = parts.find((part) => part.type === "dayPeriod")?.value;
2422
- if (!hour || !minute) return "";
2423
- return `${hour}:${minute}${normalizePeriod(dayPeriod)}`;
2424
- }
2425
- function normalizePeriod(dayPeriod) {
2426
- if (!dayPeriod) return "";
2427
- if (/^p/i.test(dayPeriod)) return "pm";
2428
- return /^a/i.test(dayPeriod) ? "am" : "";
2429
- }
2430
-
2431
2918
  // src/react/components/StatusIcon/index.tsx
2432
2919
  /**
2433
2920
  * Explicit responder state model:
@@ -2588,23 +3075,9 @@ function formatRounds(rounds) {
2588
3075
  return `${rounds} ${roundsUnit(rounds)}`;
2589
3076
  }
2590
3077
 
2591
- // src/react/screens/primary/data.ts
2592
- /**
2593
- * Derives the remaining alert rounds from available messages and designated
2594
- * responders. Invalid or non-positive input collapses to the minimum of one
2595
- * round instead of producing `Infinity`, `NaN` or a negative value.
2596
- */
2597
- function calculateRounds(messages, responders) {
2598
- if (!Number.isFinite(messages) || !Number.isFinite(responders)) return 1;
2599
- const availableMessages = Math.floor(messages);
2600
- const designatedResponders = Math.floor(responders);
2601
- if (availableMessages <= 0 || designatedResponders <= 0) return 1;
2602
- return Math.max(1, Math.floor(availableMessages / designatedResponders));
2603
- }
2604
-
2605
3078
  // src/react/screens/primary/Availability.tsx
2606
3079
  function Availability({ onRecharge, onDetails }) {
2607
- const rounds = calculateRounds(100, 3);
3080
+ const rounds = calculateRounds(27, 3);
2608
3081
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2609
3082
  className: cls("emergency-availability"),
2610
3083
  "aria-label": primaryCopy.availabilityTitle,
@@ -2646,23 +3119,30 @@ function Availability({ onRecharge, onDetails }) {
2646
3119
 
2647
3120
  // src/react/components/EmergencyBody/index.tsx
2648
3121
  function EmergencyBody(props) {
2649
- const { active, responders, refreshing, loading, locale, geolocationError, activationError, error, abortResult, simulationResult, onRefresh, onRetry, onDismissFeedback, onRecharge, onDetails } = props;
3122
+ const { active, responders, refreshing, loading, locale, geolocationError, activationError, error, abortResult, simulationResult, onRefresh, onRetry, onDismissFeedback, onRecharge, onDetails, onClose } = props;
2650
3123
  const showingFeedback = geolocationError !== null || Boolean(activationError) || abortResult !== null || simulationResult !== null;
2651
3124
  const idle = !active && !loading && !showingFeedback && error === null;
2652
3125
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2653
3126
  className: cls("emergency-panel__body-split", idle && "emergency-panel__body-split--with-availability"),
2654
- children: [idle ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3127
+ children: [idle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2655
3128
  className: cls("emergency-panel__availability-region"),
2656
3129
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Availability, {
2657
3130
  onRecharge,
2658
3131
  onDetails
2659
3132
  })
2660
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("hr", {
2661
- className: cls("emergency-panel__divider"),
2662
- "aria-hidden": "true"
2663
- })] }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2664
- className: cls("emergency-panel__prompt-region"),
3133
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3134
+ className: cls("emergency-panel__prompt-region", idle && "emergency-panel__prompt-region--idle"),
2665
3135
  children: [
3136
+ idle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3137
+ type: "button",
3138
+ className: cls("emergency-panel__close-button", "emergency-panel__close-button--prompt"),
3139
+ "aria-label": copy.close,
3140
+ onClick: onClose,
3141
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
3142
+ name: "close",
3143
+ className: cls("emergency-panel__close-icon")
3144
+ })
3145
+ }) : null,
2666
3146
  !loading && !showingFeedback ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2667
3147
  className: cls("sos-img__container"),
2668
3148
  id: "sos-img__container",
@@ -2706,12 +3186,12 @@ function PrimaryScreen(props) {
2706
3186
  const { navigate } = useScreenNavigation();
2707
3187
  const idle = !props.active && !props.loading && !props.feedbackVisible && props.error === null;
2708
3188
  const needsContactPhone = props.contactPhone === null;
2709
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyScreenLayout, {
3189
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(EmergencyScreenLayout, {
2710
3190
  screen: "primary",
2711
3191
  titleId: props.titleId,
2712
- header: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyHeader, {
3192
+ bodyClassName: idle ? "emergency-panel__body--primary" : void 0,
3193
+ header: idle ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyHeader, {
2713
3194
  titleId: props.titleId,
2714
- variant: idle ? "close-only" : "default",
2715
3195
  onClose: () => props.onClose("close")
2716
3196
  }),
2717
3197
  footer: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyFooter, {
@@ -2719,11 +3199,17 @@ function PrimaryScreen(props) {
2719
3199
  busy: props.busy,
2720
3200
  aborting: props.aborting,
2721
3201
  feedbackVisible: props.feedbackVisible,
3202
+ square: idle,
2722
3203
  onActivate: needsContactPhone ? () => navigate("pre-emergency") : props.onActivate,
2723
3204
  onRequestAbort: props.onRequestAbort,
2724
3205
  onRequestSimulation: props.onRequestSimulation
2725
3206
  }),
2726
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyBody, {
3207
+ children: [idle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
3208
+ className: cls("emergency-panel__sr-only"),
3209
+ id: props.titleId,
3210
+ tabIndex: -1,
3211
+ children: copy.panelLabel
3212
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmergencyBody, {
2727
3213
  active: props.active,
2728
3214
  responders: props.responders,
2729
3215
  refreshing: props.refreshing,
@@ -2738,8 +3224,9 @@ function PrimaryScreen(props) {
2738
3224
  onRetry: props.onRetry,
2739
3225
  onDismissFeedback: props.onDismissFeedback,
2740
3226
  onRecharge: () => navigate("pricing"),
2741
- onDetails: () => navigate("details")
2742
- })
3227
+ onDetails: () => navigate("details"),
3228
+ onClose: () => props.onClose("close")
3229
+ })]
2743
3230
  });
2744
3231
  }
2745
3232
 
@@ -2912,7 +3399,9 @@ const screenRegistry = {
2912
3399
  primary: PrimaryScreen,
2913
3400
  "pre-emergency": PreEmergencyScreen,
2914
3401
  pricing: PricingScreen,
2915
- details: DetailsScreen
3402
+ details: DetailsScreen,
3403
+ history: HistoryScreen,
3404
+ "message-detail": MessageDetailScreen
2916
3405
  };
2917
3406
 
2918
3407
  // src/react/components/EmergencyPanel/index.tsx